int main(int argc, char** argv) { if (argc <= 1) { if (argc <= 0) { return 1; } fprintf(stderr, "Usage: %s <renderer process> <args...>\n", argv[0]); return 1; } // Allow someone to query our API version if (argc == 2 && 0 == strcmp(argv[1], kSuidSandboxGetApiSwitch)) { printf("%ld\n", kSUIDSandboxApiNumber); return 0; } // We cannot adjust /proc/pid/oom_adj for sandboxed renderers // because those files are owned by root. So we need a helper here. if (argc == 4 && (0 == strcmp(argv[1], kAdjustOOMScoreSwitch))) { char* endptr = NULL; long score; errno = 0; unsigned long pid_ul = strtoul(argv[2], &endptr, 10); if (pid_ul == ULONG_MAX || !endptr || *endptr || errno != 0) return 1; pid_t pid = pid_ul; endptr = NULL; errno = 0; score = strtol(argv[3], &endptr, 10); if (score == LONG_MAX || score == LONG_MIN || !endptr || *endptr || errno != 0) { return 1; } return AdjustOOMScore(pid, score); } // Protect the core setuid sandbox functionality with an API version if (!CheckAndExportApiVersion()) { return 1; } if (geteuid() != 0) { fprintf(stderr, "The setuid sandbox is not running as root. Common causes:\n" " * An unprivileged process using ptrace on it, like a debugger.\n" " * A parent process set prctl(PR_SET_NO_NEW_PRIVS, ...)\n"); } if (!MoveToNewNamespaces()) return 1; if (!SpawnChrootHelper()) return 1; if (!DropRoot()) return 1; if (!SetupChildEnvironment()) return 1; execv(argv[1], &argv[1]); FatalError("execv failed"); return 1; }
int main(int argc, char **argv) { if (argc <= 1) { if (argc <= 0) { return 1; } fprintf(stderr, "Usage: %s <renderer process> <args...>\n", argv[0]); return 1; } // Allow someone to query our API version if (argc == 2 && 0 == strcmp(argv[1], kSuidSandboxGetApiSwitch)) { printf("%ld\n", kSUIDSandboxApiNumber); return 0; } // In the SUID sandbox, if we succeed in calling MoveToNewNamespaces() // below, then the zygote and all the renderers are in an alternate PID // namespace and do not know their real PIDs. As such, they report the wrong // PIDs to the task manager. // // To fix this, when the zygote spawns a new renderer, it gives the renderer // a dummy socket, which has a unique inode number. Then it asks the sandbox // host to find the PID of the process holding that fd by searching /proc. // // Since the zygote and renderers are all spawned by this setuid executable, // their entries in /proc are owned by root and only readable by root. In // order to search /proc for the fd we want, this setuid executable has to // double as a helper and perform the search. The code block below does this // when you call it with --find-inode INODE_NUMBER. if (argc == 3 && (0 == strcmp(argv[1], kFindInodeSwitch))) { pid_t pid; char* endptr = NULL; errno = 0; ino_t inode = strtoull(argv[2], &endptr, 10); if (inode == ULLONG_MAX || !endptr || *endptr || errno != 0) return 1; if (!FindProcessHoldingSocket(&pid, inode)) return 1; printf("%d\n", pid); return 0; } // Likewise, we cannot adjust /proc/pid/oom_adj for sandboxed renderers // because those files are owned by root. So we need another helper here. if (argc == 4 && (0 == strcmp(argv[1], kAdjustOOMScoreSwitch))) { char* endptr = NULL; long score; errno = 0; unsigned long pid_ul = strtoul(argv[2], &endptr, 10); if (pid_ul == ULONG_MAX || !endptr || *endptr || errno != 0) return 1; pid_t pid = pid_ul; endptr = NULL; errno = 0; score = strtol(argv[3], &endptr, 10); if (score == LONG_MAX || score == LONG_MIN || !endptr || *endptr || errno != 0) return 1; return AdjustOOMScore(pid, score); } #if defined(OS_CHROMEOS) if (argc == 3 && (0 == strcmp(argv[1], kAdjustLowMemMarginSwitch))) { char* endptr = NULL; errno = 0; unsigned long margin_mb = strtoul(argv[2], &endptr, 10); if (!endptr || *endptr || errno != 0) return 1; return AdjustLowMemoryMargin(margin_mb); } #endif // Protect the core setuid sandbox functionality with an API version if (!CheckAndExportApiVersion()) { return 1; } if (!MoveToNewNamespaces()) return 1; if (!SpawnChrootHelper()) return 1; if (!DropRoot()) return 1; if (!SetupChildEnvironment()) return 1; execv(argv[1], &argv[1]); FatalError("execv failed"); return 1; }