/* * This is for debugging ONLY and should not be considered secure. */ static int run_as_noworker(enum run_as_cmd cmd, struct run_as_data *data, uid_t uid, gid_t gid) { int ret, saved_errno; mode_t old_mask; run_as_fct fct; fct = run_as_enum_to_fct(cmd); if (!fct) { errno = -ENOSYS; ret = -1; goto end; } old_mask = umask(0); ret = fct(data); saved_errno = errno; umask(old_mask); errno = saved_errno; end: return ret; }
/* * Return < 0 on error, 0 if OK, 1 on hangup. */ static int handle_one_cmd(struct run_as_worker *worker) { int ret = 0; struct run_as_data data; ssize_t readlen, writelen; struct run_as_ret sendret; run_as_fct cmd; uid_t prev_euid; memset(&sendret, 0, sizeof(sendret)); sendret.fd = -1; /* * Stage 1: Receive run_as_data struct from the master. * The structure contains the command type and all the parameters needed for * its execution */ readlen = lttcomm_recv_unix_sock(worker->sockpair[1], &data, sizeof(data)); if (readlen == 0) { /* hang up */ ret = 1; goto end; } if (readlen < sizeof(data)) { PERROR("lttcomm_recv_unix_sock error"); ret = -1; goto end; } cmd = run_as_enum_to_fct(data.cmd); if (!cmd) { ret = -1; goto end; } /* * Stage 2: Receive file descriptor from master. * Some commands need a file descriptor as input so if it's needed we * receive the fd using the Unix socket. */ ret = recv_fd_from_master(worker, data.cmd, &data.fd); if (ret < 0) { PERROR("recv_fd_from_master error"); ret = -1; goto end; } prev_euid = getuid(); if (data.gid != getegid()) { ret = setegid(data.gid); if (ret < 0) { sendret._error = true; sendret._errno = errno; PERROR("setegid"); goto write_return; } } if (data.uid != prev_euid) { ret = seteuid(data.uid); if (ret < 0) { sendret._error = true; sendret._errno = errno; PERROR("seteuid"); goto write_return; } } /* * Also set umask to 0 for mkdir executable bit. */ umask(0); /* * Stage 3: Execute the command */ ret = (*cmd)(&data, &sendret); if (ret < 0) { DBG("Execution of command returned an error"); } write_return: ret = cleanup_received_fd(data.cmd, data.fd); if (ret < 0) { ERR("Error cleaning up FD"); goto end; } /* * Stage 4: Send run_as_ret structure to the master. * This structure contain the return value of the command and the errno. */ writelen = lttcomm_send_unix_sock(worker->sockpair[1], &sendret, sizeof(sendret)); if (writelen < sizeof(sendret)) { PERROR("lttcomm_send_unix_sock error"); ret = -1; goto end; } /* * Stage 5: Send file descriptor to the master * Some commands return a file descriptor so if it's needed we pass it back * to the master using the Unix socket. */ ret = send_fd_to_master(worker, data.cmd, sendret.fd); if (ret < 0) { DBG("Sending FD to master returned an error"); goto end; } if (seteuid(prev_euid) < 0) { PERROR("seteuid"); ret = -1; goto end; } ret = 0; end: return ret; }
/* * Return < 0 on error, 0 if OK, 1 on hangup. */ static int handle_one_cmd(struct run_as_worker *worker) { int ret = 0; struct run_as_data data; ssize_t readlen, writelen; struct run_as_ret sendret; run_as_fct cmd; uid_t prev_euid; /* Read data */ readlen = lttcomm_recv_unix_sock(worker->sockpair[1], &data, sizeof(data)); if (readlen == 0) { /* hang up */ ret = 1; goto end; } if (readlen < sizeof(data)) { PERROR("lttcomm_recv_unix_sock error"); ret = -1; goto end; } cmd = run_as_enum_to_fct(data.cmd); if (!cmd) { ret = -1; goto end; } prev_euid = getuid(); if (data.gid != getegid()) { ret = setegid(data.gid); if (ret < 0) { PERROR("setegid"); goto write_return; } } if (data.uid != prev_euid) { ret = seteuid(data.uid); if (ret < 0) { PERROR("seteuid"); goto write_return; } } /* * Also set umask to 0 for mkdir executable bit. */ umask(0); ret = (*cmd)(&data); write_return: sendret.ret = ret; sendret._errno = errno; /* send back return value */ writelen = lttcomm_send_unix_sock(worker->sockpair[1], &sendret, sizeof(sendret)); if (writelen < sizeof(sendret)) { PERROR("lttcomm_send_unix_sock error"); ret = -1; goto end; } ret = do_send_fd(worker, data.cmd, ret); if (ret) { PERROR("do_send_fd error"); ret = -1; goto end; } if (seteuid(prev_euid) < 0) { PERROR("seteuid"); ret = -1; goto end; } ret = 0; end: return ret; }