2 * Copyright (C) ARM Limited 2014. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
14 #include <sys/prctl.h>
15 #include <sys/resource.h>
17 #include <sys/syscall.h>
19 #include <sys/types.h>
24 #include "SessionData.h"
26 static int getUid(const char *const name, char *const shPath, const char *const tmpDir) {
27 // Lookups may fail when using a different libc or a statically compiled executable
29 snprintf(gatorTemp, sizeof(gatorTemp), "%s/gator_temp", tmpDir);
31 const int fd = open(gatorTemp, 600, O_CREAT | O_CLOEXEC);
38 snprintf(cmd, sizeof(cmd), "chown %s %s || rm %s", name, gatorTemp, gatorTemp);
40 const int pid = fork();
42 logg->logError(__FILE__, __LINE__, "fork failed");
54 execv(cargv[0], cargv);
57 while ((waitpid(pid, NULL, 0) < 0) && (errno == EINTR));
61 if (stat(gatorTemp, &st) == 0) {
68 static int getUid(const char *const name) {
69 // Look up the username
70 struct passwd *const user = getpwnam(name);
77 char cargv0l[] = "/bin/sh";
78 if ((access(cargv0l, X_OK) == 0) && (access("/tmp", W_OK) == 0)) {
79 return getUid(name, cargv0l, "/tmp");
83 char cargv0a[] = "/system/bin/sh";
84 if ((access(cargv0a, X_OK) == 0) && (access("/data", W_OK) == 0)) {
85 return getUid(name, cargv0a, "/data");
91 void *commandThread(void *) {
92 prctl(PR_SET_NAME, (unsigned long)&"gatord-command", 0, 0, 0);
94 const char *const name = gSessionData->mCaptureUser == NULL ? "nobody" : gSessionData->mCaptureUser;
95 const int uid = getUid(name);
97 logg->logError(__FILE__, __LINE__, "Unable to lookup the user %s, please double check that the user exists", name);
105 if (pipe_cloexec(pipefd) != 0) {
106 logg->logError(__FILE__, __LINE__, "pipe failed");
110 const int pid = fork();
112 logg->logError(__FILE__, __LINE__, "fork failed");
116 char cargv0l[] = "/bin/sh";
117 char cargv0a[] = "/system/bin/sh";
118 char cargv1[] = "-c";
122 gSessionData->mCaptureCommand,
129 // Gator runs at a high priority, reset the priority to the default
130 if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), 0) == -1) {
131 snprintf(buf, sizeof(buf), "setpriority failed");
135 if (setuid(uid) != 0) {
136 snprintf(buf, sizeof(buf), "setuid failed");
141 const char *const path = gSessionData->mCaptureWorkingDir == NULL ? "/" : gSessionData->mCaptureWorkingDir;
142 if (chdir(path) != 0) {
143 snprintf(buf, sizeof(buf), "Unable to cd to %s, please verify the directory exists and is accessable to %s", path, name);
148 execv(cargv[0], cargv);
150 execv(cargv[0], cargv);
151 snprintf(buf, sizeof(buf), "execv failed");
154 if (buf[0] != '\0') {
155 const ssize_t bytes = write(pipefd[1], buf, sizeof(buf));
156 // Can't do anything if this fails
164 const ssize_t bytes = read(pipefd[0], buf, sizeof(buf));
166 logg->logError(__FILE__, __LINE__, buf);