X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Frunas.c;h=08979fb79c15bee3bfd9f60bd3d084a141e79d08;hb=f8f66d38569fb800905759a1f706bc39e2d35669;hp=42ca55266ca43767b38c9e2af46cef74efd6933f;hpb=da9ee8323287d74fc2ec5477ecf83e61da36f5ce;p=lttng-tools.git diff --git a/src/common/runas.c b/src/common/runas.c index 42ca55266..08979fb79 100644 --- a/src/common/runas.c +++ b/src/common/runas.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -364,7 +365,6 @@ int run_as_cmd(struct run_as_worker *worker, ssize_t readlen, writelen; struct run_as_ret recvret; - pthread_mutex_lock(&worker_lock); /* * If we are non-root, we can only deal with our own uid. */ @@ -410,7 +410,6 @@ int run_as_cmd(struct run_as_worker *worker, } end: - pthread_mutex_unlock(&worker_lock); errno = recvret._errno; return recvret.ret; } @@ -442,15 +441,17 @@ end: } static -int run_as(struct run_as_worker *worker, - enum run_as_cmd cmd, - struct run_as_data *data, uid_t uid, gid_t gid) +int run_as(enum run_as_cmd cmd, struct run_as_data *data, uid_t uid, gid_t gid) { int ret; - if (worker) { + if (use_clone()) { DBG("Using run_as worker"); - ret = run_as_cmd(worker, cmd, data, uid, gid); + pthread_mutex_lock(&worker_lock); + assert(global_worker); + ret = run_as_cmd(global_worker, cmd, data, uid, gid); + pthread_mutex_unlock(&worker_lock); + } else { DBG("Using run_as without worker"); ret = run_as_noworker(cmd, data, uid, gid); @@ -461,7 +462,6 @@ int run_as(struct run_as_worker *worker, LTTNG_HIDDEN int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) { - struct run_as_worker *worker = global_worker; struct run_as_data data; DBG3("mkdir() recursive %s with mode %d for uid %d and gid %d", @@ -469,13 +469,12 @@ int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid) strncpy(data.u.mkdir.path, path, PATH_MAX - 1); data.u.mkdir.path[PATH_MAX - 1] = '\0'; data.u.mkdir.mode = mode; - return run_as(worker, RUN_AS_MKDIR_RECURSIVE, &data, uid, gid); + return run_as(RUN_AS_MKDIR_RECURSIVE, &data, uid, gid); } LTTNG_HIDDEN int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) { - struct run_as_worker *worker = global_worker; struct run_as_data data; DBG3("mkdir() %s with mode %d for uid %d and gid %d", @@ -483,7 +482,7 @@ int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) strncpy(data.u.mkdir.path, path, PATH_MAX - 1); data.u.mkdir.path[PATH_MAX - 1] = '\0'; data.u.mkdir.mode = mode; - return run_as(worker, RUN_AS_MKDIR, &data, uid, gid); + return run_as(RUN_AS_MKDIR, &data, uid, gid); } /* @@ -493,7 +492,6 @@ int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) LTTNG_HIDDEN int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid) { - struct run_as_worker *worker = global_worker; struct run_as_data data; DBG3("open() %s with flags %X mode %d for uid %d and gid %d", @@ -502,33 +500,47 @@ int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid) data.u.open.path[PATH_MAX - 1] = '\0'; data.u.open.flags = flags; data.u.open.mode = mode; - return run_as(worker, RUN_AS_OPEN, &data, uid, gid); + return run_as(RUN_AS_OPEN, &data, uid, gid); } LTTNG_HIDDEN int run_as_unlink(const char *path, uid_t uid, gid_t gid) { - struct run_as_worker *worker = global_worker; struct run_as_data data; DBG3("unlink() %s with for uid %d and gid %d", path, uid, gid); strncpy(data.u.unlink.path, path, PATH_MAX - 1); data.u.unlink.path[PATH_MAX - 1] = '\0'; - return run_as(worker, RUN_AS_UNLINK, &data, uid, gid); + return run_as(RUN_AS_UNLINK, &data, uid, gid); } LTTNG_HIDDEN int run_as_rmdir_recursive(const char *path, uid_t uid, gid_t gid) { - struct run_as_worker *worker = global_worker; struct run_as_data data; DBG3("rmdir_recursive() %s with for uid %d and gid %d", path, uid, gid); strncpy(data.u.rmdir_recursive.path, path, PATH_MAX - 1); data.u.rmdir_recursive.path[PATH_MAX - 1] = '\0'; - return run_as(worker, RUN_AS_RMDIR_RECURSIVE, &data, uid, gid); + return run_as(RUN_AS_RMDIR_RECURSIVE, &data, uid, gid); +} + +static +void reset_sighandler(void) +{ + int sig; + + for (sig = SIGHUP; sig <= SIGUNUSED; sig++) { + /* Skip unblockable signals. */ + if (sig == SIGKILL || sig == SIGSTOP) { + continue; + } + if (signal(sig, SIG_DFL) == SIG_ERR) { + PERROR("reset signal %d", sig); + } + } } LTTNG_HIDDEN @@ -540,7 +552,13 @@ int run_as_create_worker(char *procname) struct run_as_ret recvret; struct run_as_worker *worker; + pthread_mutex_lock(&worker_lock); + assert(!global_worker); if (!use_clone()) { + /* + * Don't initialize a worker, all run_as tasks will be performed + * in the current process. + */ ret = 0; goto end; } @@ -564,6 +582,10 @@ int run_as_create_worker(char *procname) } else if (pid == 0) { /* Child */ + reset_sighandler(); + + /* The child has no use for this lock. */ + pthread_mutex_unlock(&worker_lock); /* Just close, no shutdown. */ if (close(worker->sockpair[0])) { PERROR("close"); @@ -600,6 +622,7 @@ int run_as_create_worker(char *procname) global_worker = worker; } end: + pthread_mutex_unlock(&worker_lock); return ret; /* Error handling. */ @@ -615,6 +638,7 @@ error_fork: } error_sock: free(worker); + pthread_mutex_unlock(&worker_lock); return ret; } @@ -622,11 +646,10 @@ LTTNG_HIDDEN void run_as_destroy_worker(void) { struct run_as_worker *worker = global_worker; - int status; - pid_t pid; + pthread_mutex_lock(&worker_lock); if (!worker) { - return; + goto end; } /* Close unix socket */ if (lttcomm_close_unix_sock(worker->sockpair[0])) { @@ -634,10 +657,32 @@ void run_as_destroy_worker(void) } worker->sockpair[0] = -1; /* Wait for worker. */ - pid = waitpid(worker->pid, &status, 0); - if (pid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { - PERROR("wait"); + for (;;) { + int status; + pid_t wait_ret; + + wait_ret = waitpid(worker->pid, &status, 0); + if (wait_ret < 0) { + if (errno == EINTR) { + continue; + } + PERROR("waitpid"); + break; + } + + if (WIFEXITED(status)) { + LOG(WEXITSTATUS(status) == 0 ? PRINT_DBG : PRINT_ERR, + DEFAULT_RUN_AS_WORKER_NAME " terminated with status code %d", + WEXITSTATUS(status)); + break; + } else if (WIFSIGNALED(status)) { + ERR(DEFAULT_RUN_AS_WORKER_NAME " was killed by signal %d", + WTERMSIG(status)); + break; + } } free(worker); global_worker = NULL; +end: + pthread_mutex_unlock(&worker_lock); }