Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1795)

Unified Diff: sandbox/linux/suid/init_process.c

Issue 10389214: Revert setuid sandbox as a "init process" changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sandbox/linux/suid/init_process.h ('k') | sandbox/linux/suid/sandbox.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sandbox/linux/suid/init_process.c
diff --git a/sandbox/linux/suid/init_process.c b/sandbox/linux/suid/init_process.c
deleted file mode 100644
index e854202086448a32b4806cfedfac7eeb9733aff7..0000000000000000000000000000000000000000
--- a/sandbox/linux/suid/init_process.c
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#define _GNU_SOURCE
-#include "init_process.h"
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-
-static int getProcessStatus(int proc_fd, const char *process,
- const char *field) {
- int ret = -1;
-
- // Open "/proc/${process}/status"
- char *buf = malloc(strlen(process) + 80);
- sprintf(buf, "%s/status", process);
- int fd = openat(proc_fd, buf, O_RDONLY);
- if (fd >= 0) {
- // Only bother to read the first 4kB. All of the fields that we
- // are interested in will show up much earlier.
- buf = realloc(buf, 4097);
- size_t sz = read(fd, buf, 4096);
- if (sz > 0) {
- // Find a matching "field"
- buf[sz] = '\000';
- char *f = malloc(strlen(field) + 4);
- sprintf(f, "\n%s:\t", field);
- char *ptr = strstr(buf, f);
- if (ptr) {
- // Extract the numerical value of the "field"
- ret = atoi(ptr + strlen(f));
- }
- free(f);
- }
- close(fd);
- }
- free(buf);
- return ret;
-}
-
-static bool hasChildren(int proc_fd, int pid) {
- bool ret = false;
-
- // Open "/proc"
- int fd = dup(proc_fd);
- lseek(fd, SEEK_SET, 0);
- DIR *dir = fd >= 0 ? fdopendir(fd) : NULL;
- struct dirent de, *res;
- while (dir && !readdir_r(dir, &de, &res) && res) {
- // Find numerical entries. Those are processes.
- if (res->d_name[0] <= '0' || res->d_name[0] > '9') {
- continue;
- }
-
- // For each process, check the parent's pid
- int ppid = getProcessStatus(proc_fd, res->d_name, "PPid");
-
- if (ppid == pid) {
- // We found a child process. We can stop searching, now
- ret = true;
- break;
- }
- }
- closedir(dir);
- return ret;
-}
-
-void SystemInitProcess(int init_fd, int child_pid, int proc_fd, int null_fd) {
- int ret = 0;
-
- // CLONE_NEWPID doesn't adjust the contents of the "/proc" file system.
- // This is very confusing. And it is even possible the kernel developers
- // will consider this a bug and fix it at some point in the future.
- // So, to be on the safe side, we explicitly retrieve our process id
- // from the "/proc" file system. This should continue to work, even if
- // the kernel eventually gets fixed so that "/proc" shows the view from
- // inside of the new pid namespace.
- pid_t init_pid = getProcessStatus(proc_fd, "self", "Pid");
- if (init_pid <= 0) {
- fprintf(stderr,
- "Failed to determine real process id of new \"init\" process\n");
- _exit(1);
- }
-
- // Redirect stdio to /dev/null
- if (null_fd < 0 ||
- dup2(null_fd, 0) != 0 ||
- dup2(null_fd, 1) != 1 ||
- dup2(null_fd, 2) != 2) {
- fprintf(stderr, "Failed to point stdio to a safe place\n");
- _exit(1);
- }
- close(null_fd);
-
- // Close all file handles
- int fds_fd = openat(proc_fd, "self/fd", O_RDONLY | O_DIRECTORY);
- DIR *dir = fds_fd >= 0 ? fdopendir(fds_fd) : NULL;
- if (dir == NULL) {
- // If we don't know the list of our open file handles, just try closing
- // all valid ones.
- for (int fd = sysconf(_SC_OPEN_MAX); --fd > 2; ) {
- if (fd != init_fd && fd != proc_fd) {
- close(fd);
- }
- }
- } else {
- // If available, it is much more efficient to just close the file
- // handles that show up in "/proc/self/fd/"
- struct dirent de, *res;
- while (!readdir_r(dir, &de, &res) && res) {
- if (res->d_name[0] < '0')
- continue;
- int fd = atoi(res->d_name);
- if (fd > 2 && fd != init_fd && fd != proc_fd && fd != dirfd(dir)) {
- close(fd);
- }
- }
- closedir(dir);
- }
-
- // Set up signal handler to catch SIGCHLD, but mask the signal for now
- sigset_t mask;
- sigemptyset(&mask);
- sigaddset(&mask, SIGCHLD);
- sigprocmask(SIG_BLOCK, &mask, NULL);
-
- // Notify other processes that we are done initializing
- if (write(init_fd, " ", 1)) { }
- close(init_fd);
-
- // Handle dying processes that have been re-parented to the "init" process
- for (;;) {
- bool retry = false;
- do {
- for (;;) {
- // Reap all exit codes of our child processes. This includes both
- // processes that originally were our immediate children, and processes
- // that have since been re-parented to be our children.
- int status;
- pid_t pid = waitpid(0, &status, __WALL | WNOHANG);
- if (pid <= 0) {
- break;
- } else {
- // We found some newly deceased child processes. Better schedule
- // another very thorough inspection of our state.
- retry = false;
- }
- if (pid == child_pid) {
- // If our first immediate child died, remember its exit code. That's
- // the exit code that we should be reporting to our parent process
- if (WIFEXITED(status)) {
- ret = WEXITSTATUS(status);
- } else if (WIFSIGNALED(status)) {
- ret = -WTERMSIG(status);
- }
- }
- }
- if (hasChildren(proc_fd, init_pid)) {
- // As long as we still have child processes, continue waiting for
- // their ultimate demise.
- retry = false;
- } else {
- if (retry) {
- // No more child processes. We can exit now.
- if (ret < 0) {
- // Try to exit with the same signal that our child terminated with
- signal(-ret, SIG_DFL);
- kill(1, -ret);
- ret = 1;
- }
- // Exit with the same exit code that our child exited with
- _exit(ret);
- } else {
- // There is a little bit of a race condition between getting
- // notifications and scanning the "/proc" file system. This is
- // particularly true, because scanning "/proc" cannot possibly be
- // an atomic operation.
- // If we find that we no longer appear to have any children, we check
- // one more time whether there are any children we can now reap.
- // They might have died while we were scanning "/proc" and if so,
- // they should now show up.
- retry = true;
- }
- }
- } while (retry);
-
- // Wait until we receive a SIGCHLD signal. Our signal handler doesn't
- // actually need to do anything, though
- sigwaitinfo(&mask, NULL);
- }
-}
« no previous file with comments | « sandbox/linux/suid/init_process.h ('k') | sandbox/linux/suid/sandbox.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698