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.
19 #include <sys/types.h>
20 #include <sys/utsname.h>
28 bool getLinuxVersion(int version[3]) {
29 // Check the kernel version
30 struct utsname utsname;
31 if (uname(&utsname) != 0) {
32 logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__);
41 char *ch = utsname.release;
42 while (*ch >= '0' && *ch <= '9' && part < 3) {
43 version[part] = 10*version[part] + *ch - '0';
55 static int pgrep_gator(DynBuf *const printb) {
58 DIR *proc = opendir("/proc");
60 logg->logError(__FILE__, __LINE__, "gator: error: opendir failed");
66 struct dirent *dirent;
67 while ((dirent = readdir(proc)) != NULL) {
69 const int pid = strtol(dirent->d_name, &endptr, 10);
70 if (*endptr != '\0' || (pid == self)) {
71 // Ignore proc items that are not integers like ., cpuinfo, etc...
75 if (!printb->printf("/proc/%i/stat", pid)) {
76 logg->logError(__FILE__, __LINE__, "gator: error: DynBuf::printf failed");
80 if (!b.read(printb->getBuf())) {
81 // This is not a fatal error - the thread just doesn't exist any more
85 char *comm = strchr(b.getBuf(), '(');
87 logg->logError(__FILE__, __LINE__, "gator: error: parsing stat begin failed");
91 char *const str = strrchr(comm, ')');
93 logg->logError(__FILE__, __LINE__, "gator: error: parsing stat end failed");
98 if (strncmp(comm, "gator", 5) == 0) {
99 // Assume there is only one gator process
109 int update(const char *const gatorPath) {
110 printf("gator: starting\n");
113 if (!getLinuxVersion(version)) {
114 logg->logError(__FILE__, __LINE__, "gator: error: getLinuxVersion failed");
118 if (KERNEL_VERSION(version[0], version[1], version[2]) < KERNEL_VERSION(2, 6, 32)) {
119 logg->logError(__FILE__, __LINE__, "gator: error: Streamline can't automatically setup gator as this kernel version is not supported. Please upgrade the kernel on your device.");
123 if (KERNEL_VERSION(version[0], version[1], version[2]) < KERNEL_VERSION(3, 4, 0)) {
124 logg->logError(__FILE__, __LINE__, "gator: error: Streamline can't automatically setup gator as gator.ko is required for this version of Linux. Please build gator.ko and gatord and install them on your device.");
128 if (access("/sys/module/gator", F_OK) == 0) {
129 logg->logError(__FILE__, __LINE__, "gator: error: Streamline has detected that the gator kernel module is loaded on your device. Please build an updated version of gator.ko and gatord and install them on your device.");
133 if (geteuid() != 0) {
134 printf("gator: trying sudo\n");
135 execlp("sudo", "sudo", gatorPath, "-u", NULL);
136 // Streamline will provide the password if needed
138 printf("gator: trying su\n");
140 snprintf(buf, sizeof(buf), "%s -u", gatorPath);
141 execlp("su", "su", "-", "-c", buf, NULL);
142 // Streamline will provide the password if needed
144 logg->logError(__FILE__, __LINE__, "gator: error: Streamline was unable to sudo to root on your device. Please double check passwords, ensure sudo or su work with this user or try a different username.");
147 printf("gator: now root\n");
149 // setenforce 0 not needed for userspace gator
151 // Kill existing gator
152 DynBuf gatorStatPath;
153 int gator_main = pgrep_gator(&gatorStatPath);
154 if (gator_main > 0) {
155 if (kill(gator_main, SIGTERM) != 0) {
156 logg->logError(__FILE__, __LINE__, "gator: error: kill SIGTERM failed");
159 for (int i = 0; ; ++i) {
160 if (access(gatorStatPath.getBuf(), F_OK) != 0) {
164 if (kill(gator_main, SIGKILL) != 0) {
165 logg->logError(__FILE__, __LINE__, "gator: error: kill SIGKILL failed");
168 } else if (i >= 10) {
169 logg->logError(__FILE__, __LINE__, "gator: error: unable to kill running gator");
175 printf("gator: no gatord running\n");
177 rename("gatord", "gatord.old");
178 rename("gator.ko", "gator.ko.old");
180 // Rename gatord.YYYYMMDDHHMMSSMMMM to gatord
181 char *newGatorPath = strdup(gatorPath);
182 char *dot = strrchr(newGatorPath, '.');
185 if (rename(gatorPath, newGatorPath) != 0) {
186 logg->logError(__FILE__, __LINE__, "gator: error: rename failed");
191 // Fork and start gatord (redirect stdout and stderr)
194 logg->logError(__FILE__, __LINE__, "gator: error: fork failed");
196 } else if (child == 0) {
197 int inFd = open("/dev/null", O_RDONLY | O_CLOEXEC);
199 logg->logError(__FILE__, __LINE__, "gator: error: open of /dev/null failed");
202 int outFd = open("gatord.out", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
204 logg->logError(__FILE__, __LINE__, "gator: error: open of gatord.out failed");
207 int errFd = open("gatord.err", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
209 logg->logError(__FILE__, __LINE__, "gator: error: open of gatord.err failed");
212 if (dup2(inFd, STDIN_FILENO) < 0) {
213 logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stdin failed");
216 if (dup2(outFd, STDOUT_FILENO) < 0) {
217 logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stdout failed");
220 if (dup2(errFd, STDERR_FILENO) < 0) {
221 logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stderr failed");
224 execlp(newGatorPath, newGatorPath, "-a", NULL);
225 logg->logError(__FILE__, __LINE__, "gator: error: execlp failed");
229 printf("gator: done\n");