|
|
|
@ -25,6 +25,7 @@
|
|
|
|
|
#include <android-base/properties.h>
|
|
|
|
|
#include <android-base/stringprintf.h>
|
|
|
|
|
#include <android-base/strings.h>
|
|
|
|
|
#include <android-base/unique_fd.h>
|
|
|
|
|
#include <cutils/fs.h>
|
|
|
|
|
#include <logwrap/logwrap.h>
|
|
|
|
|
#include <private/android_filesystem_config.h>
|
|
|
|
@ -235,7 +236,7 @@ static status_t readMetadata(const std::string& path, std::string* fsType, std::
|
|
|
|
|
cmd.push_back(path);
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> output;
|
|
|
|
|
status_t res = ForkExecvp(cmd, output, untrusted ? sBlkidUntrustedContext : sBlkidContext);
|
|
|
|
|
status_t res = ForkExecvp(cmd, &output, untrusted ? sBlkidUntrustedContext : sBlkidContext);
|
|
|
|
|
if (res != OK) {
|
|
|
|
|
LOG(WARNING) << "blkid failed to identify " << path;
|
|
|
|
|
return res;
|
|
|
|
@ -261,101 +262,93 @@ status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType, std
|
|
|
|
|
return readMetadata(path, fsType, fsUuid, fsLabel, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status_t ForkExecvp(const std::vector<std::string>& args) {
|
|
|
|
|
return ForkExecvp(args, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status_t ForkExecvp(const std::vector<std::string>& args, security_context_t context) {
|
|
|
|
|
std::lock_guard<std::mutex> lock(kSecurityLock);
|
|
|
|
|
size_t argc = args.size();
|
|
|
|
|
char** argv = (char**)calloc(argc, sizeof(char*));
|
|
|
|
|
for (size_t i = 0; i < argc; i++) {
|
|
|
|
|
argv[i] = (char*)args[i].c_str();
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
LOG(DEBUG) << args[i];
|
|
|
|
|
static std::vector<const char*> ConvertToArgv(const std::vector<std::string>& args) {
|
|
|
|
|
std::vector<const char*> argv;
|
|
|
|
|
argv.reserve(args.size() + 1);
|
|
|
|
|
for (const auto& arg : args) {
|
|
|
|
|
if (argv.empty()) {
|
|
|
|
|
LOG(DEBUG) << arg;
|
|
|
|
|
} else {
|
|
|
|
|
LOG(DEBUG) << " " << args[i];
|
|
|
|
|
LOG(DEBUG) << " " << arg;
|
|
|
|
|
}
|
|
|
|
|
argv.emplace_back(arg.data());
|
|
|
|
|
}
|
|
|
|
|
argv.emplace_back(nullptr);
|
|
|
|
|
return argv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (context) {
|
|
|
|
|
if (setexeccon(context)) {
|
|
|
|
|
LOG(ERROR) << "Failed to setexeccon";
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
static status_t ReadLinesFromFdAndLog(std::vector<std::string>* output,
|
|
|
|
|
android::base::unique_fd ufd) {
|
|
|
|
|
std::unique_ptr<FILE, int (*)(FILE*)> fp(android::base::Fdopen(std::move(ufd), "r"), fclose);
|
|
|
|
|
if (!fp) {
|
|
|
|
|
PLOG(ERROR) << "fdopen in ReadLinesFromFdAndLog";
|
|
|
|
|
return -errno;
|
|
|
|
|
}
|
|
|
|
|
status_t res = android_fork_execvp(argc, argv, NULL, false, true);
|
|
|
|
|
if (context) {
|
|
|
|
|
if (setexeccon(nullptr)) {
|
|
|
|
|
LOG(ERROR) << "Failed to setexeccon";
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
if (output) output->clear();
|
|
|
|
|
char line[1024];
|
|
|
|
|
while (fgets(line, sizeof(line), fp.get()) != nullptr) {
|
|
|
|
|
LOG(DEBUG) << line;
|
|
|
|
|
if (output) output->emplace_back(line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(argv);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>& output) {
|
|
|
|
|
return ForkExecvp(args, output, nullptr);
|
|
|
|
|
return OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>& output,
|
|
|
|
|
status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>* output,
|
|
|
|
|
security_context_t context) {
|
|
|
|
|
std::lock_guard<std::mutex> lock(kSecurityLock);
|
|
|
|
|
std::string cmd;
|
|
|
|
|
for (size_t i = 0; i < args.size(); i++) {
|
|
|
|
|
cmd += args[i] + " ";
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
LOG(DEBUG) << args[i];
|
|
|
|
|
} else {
|
|
|
|
|
LOG(DEBUG) << " " << args[i];
|
|
|
|
|
}
|
|
|
|
|
auto argv = ConvertToArgv(args);
|
|
|
|
|
|
|
|
|
|
int fd[2];
|
|
|
|
|
if (pipe2(fd, O_CLOEXEC) != 0) {
|
|
|
|
|
PLOG(ERROR) << "pipe2 in ForkExecvp";
|
|
|
|
|
return -errno;
|
|
|
|
|
}
|
|
|
|
|
output.clear();
|
|
|
|
|
android::base::unique_fd pipe_read(fd[0]);
|
|
|
|
|
android::base::unique_fd pipe_write(fd[1]);
|
|
|
|
|
|
|
|
|
|
if (context) {
|
|
|
|
|
if (setexeccon(context)) {
|
|
|
|
|
LOG(ERROR) << "Failed to setexeccon";
|
|
|
|
|
abort();
|
|
|
|
|
pid_t pid = fork();
|
|
|
|
|
if (pid == 0) {
|
|
|
|
|
if (context) {
|
|
|
|
|
if (setexeccon(context)) {
|
|
|
|
|
LOG(ERROR) << "Failed to setexeccon";
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
FILE* fp = popen(cmd.c_str(), "r"); // NOLINT
|
|
|
|
|
if (context) {
|
|
|
|
|
if (setexeccon(nullptr)) {
|
|
|
|
|
LOG(ERROR) << "Failed to setexeccon";
|
|
|
|
|
abort();
|
|
|
|
|
pipe_read.reset();
|
|
|
|
|
if (pipe_write.get() != STDOUT_FILENO) {
|
|
|
|
|
dup2(pipe_write.get(), STDOUT_FILENO);
|
|
|
|
|
pipe_write.reset();
|
|
|
|
|
}
|
|
|
|
|
execvp(argv[0], const_cast<char**>(argv.data()));
|
|
|
|
|
PLOG(ERROR) << "Failed to exec";
|
|
|
|
|
_exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
if (pid == -1) {
|
|
|
|
|
PLOG(ERROR) << "fork in ForkExecvp";
|
|
|
|
|
return -errno;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!fp) {
|
|
|
|
|
PLOG(ERROR) << "Failed to popen " << cmd;
|
|
|
|
|
pipe_write.reset();
|
|
|
|
|
auto st = ReadLinesFromFdAndLog(output, std::move(pipe_read));
|
|
|
|
|
if (st != 0) return st;
|
|
|
|
|
|
|
|
|
|
int status;
|
|
|
|
|
if (waitpid(pid, &status, 0) == -1) {
|
|
|
|
|
PLOG(ERROR) << "waitpid in ForkExecvp";
|
|
|
|
|
return -errno;
|
|
|
|
|
}
|
|
|
|
|
char line[1024];
|
|
|
|
|
while (fgets(line, sizeof(line), fp) != nullptr) {
|
|
|
|
|
LOG(DEBUG) << line;
|
|
|
|
|
output.push_back(std::string(line));
|
|
|
|
|
if (!WIFEXITED(status)) {
|
|
|
|
|
LOG(ERROR) << "Process did not exit normally, status: " << status;
|
|
|
|
|
return -ECHILD;
|
|
|
|
|
}
|
|
|
|
|
if (pclose(fp) != 0) {
|
|
|
|
|
PLOG(ERROR) << "Failed to pclose " << cmd;
|
|
|
|
|
return -errno;
|
|
|
|
|
if (WEXITSTATUS(status)) {
|
|
|
|
|
LOG(ERROR) << "Process exited with code: " << WEXITSTATUS(status);
|
|
|
|
|
return WEXITSTATUS(status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pid_t ForkExecvpAsync(const std::vector<std::string>& args) {
|
|
|
|
|
size_t argc = args.size();
|
|
|
|
|
char** argv = (char**)calloc(argc + 1, sizeof(char*));
|
|
|
|
|
for (size_t i = 0; i < argc; i++) {
|
|
|
|
|
argv[i] = (char*)args[i].c_str();
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
LOG(DEBUG) << args[i];
|
|
|
|
|
} else {
|
|
|
|
|
LOG(DEBUG) << " " << args[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
auto argv = ConvertToArgv(args);
|
|
|
|
|
|
|
|
|
|
pid_t pid = fork();
|
|
|
|
|
if (pid == 0) {
|
|
|
|
@ -363,18 +356,14 @@ pid_t ForkExecvpAsync(const std::vector<std::string>& args) {
|
|
|
|
|
close(STDOUT_FILENO);
|
|
|
|
|
close(STDERR_FILENO);
|
|
|
|
|
|
|
|
|
|
if (execvp(argv[0], argv)) {
|
|
|
|
|
PLOG(ERROR) << "Failed to exec";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_exit(1);
|
|
|
|
|
execvp(argv[0], const_cast<char**>(argv.data()));
|
|
|
|
|
PLOG(ERROR) << "exec in ForkExecvpAsync";
|
|
|
|
|
_exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pid == -1) {
|
|
|
|
|
PLOG(ERROR) << "Failed to exec";
|
|
|
|
|
PLOG(ERROR) << "fork in ForkExecvpAsync";
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(argv);
|
|
|
|
|
return pid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|