Don't start logcat from vsock_logcat to keep selinux happy
Start it in its own process and make it write to a named pipe created
by vsock_logcat, which in turn forwards the logs to the host side
process. As with qemu, logcat is started when vsock_logcat sets the
vendor.ser.cf-logcat property.
Bug: 129163131
Test: run locally under crosvm, check there are no avc: denied
messages.
Change-Id: I8a9b04c33f21272698e40f88e5264c1355552955
diff --git a/guest/commands/vsock_logcat/main.cpp b/guest/commands/vsock_logcat/main.cpp
index fbac839..51d97e3 100644
--- a/guest/commands/vsock_logcat/main.cpp
+++ b/guest/commands/vsock_logcat/main.cpp
@@ -18,6 +18,10 @@
#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
#include <fstream>
#include <sstream>
#include <string>
@@ -27,14 +31,19 @@
#include <glog/logging.h>
#include "common/libs/fs/shared_fd.h"
+#include "common/libs/utils/files.h"
#include "common/libs/utils/subprocess.h"
DEFINE_uint32(port, property_get_int32("ro.boot.vsock_logcat_port", 0),
"VSOCK port to send logcat output to");
DEFINE_uint32(cid, 2, "VSOCK CID to send logcat output to");
+DEFINE_string(pipe_name, "/dev/cf_logcat_pipe",
+ "The path for the named pipe logcat will write to");
namespace {
+constexpr char kLogcatExitMsg[] = "\nDetected exit of logcat process\n\n";
+
class ServiceStatus {
public:
static const char* kServiceStatusProperty;
@@ -106,32 +115,26 @@
<< ServiceStatus::kServiceStatusProperty;
}
- cvd::Command logcat_cmd("/system/bin/logcat");
- logcat_cmd.AddParameter("-b");
- logcat_cmd.AddParameter("all");
- logcat_cmd.AddParameter("-v");
- logcat_cmd.AddParameter("threadtime");
- logcat_cmd.AddParameter("*:V");
-
- logcat_cmd.RedirectStdIO(cvd::Subprocess::StdIOChannel::kStdOut, log_fd);
-
- while (true) {
- int wstatus;
- logcat_cmd.Start().Wait(&wstatus, 0);
- std::ostringstream exit_msg_builder;
- exit_msg_builder << std::endl
- << "Logcat process exited with wstatus " << wstatus
- << ", restarting ..." << std::endl
- << std::endl;
- auto exit_msg = exit_msg_builder.str();
- size_t written = log_fd->Write(exit_msg.c_str(), exit_msg.size());
- if (written != exit_msg.size()) {
- std::ostringstream ss;
- ss << exit_msg << std::endl
- << "Unable to write complete message on socket: "
- << log_fd->StrError();
- LogFailed(ss.str(), &status);
- return 2;
+ if (cvd::FileExists(FLAGS_pipe_name)) {
+ LOG(WARNING) << "The file " << FLAGS_pipe_name << " already exists. Deleting...";
+ cvd::RemoveFile(FLAGS_pipe_name);
+ }
+ auto pipe = mkfifo(FLAGS_pipe_name.c_str(), 0600);
+ if (pipe != 0) {
+ LOG(FATAL) << "unable to create pipe: " << strerror(errno);
+ }
+ property_set("vendor.ser.cf-logcat", FLAGS_pipe_name.c_str());
+ while (1) {
+ auto conn = cvd::SharedFD::Open(FLAGS_pipe_name.c_str(), O_RDONLY);
+ while (conn->IsOpen()) {
+ char buff[4096];
+ auto read = conn->Read(buff, sizeof(buff));
+ if (read) {
+ log_fd->Write(buff, read);
+ } else {
+ conn->Close();
+ }
}
+ log_fd->Write(kLogcatExitMsg, sizeof(kLogcatExitMsg) - 1);
}
}