Package: release.debian.org Severity: normal Tags: jessie User: [email protected] Usertags: pu
I'd like to update slurm-llnl in the next oldstable point release to address a vulnerability in how the slurmd daemon informs users of a Prolog failure on a compute node. That vulnerability could allow a user to assume control of an arbitrary file on the system. Any exploitation of this is dependent on the user being able to cause or anticipate the failure (non-zero return code) of a Prolog script that their job would run on (CVE-2016-10030). debdiff is attached. The diffstat is: changelog | 7 + patches/CVE-2016-10030 | 198 +++++++++++++++++++++++++++++++++++++++++++++++++ patches/series | 1 3 files changed, 206 insertions(+) Thanks -- Gennaro Oliva
diff -Nru slurm-llnl-14.03.9/debian/changelog slurm-llnl-14.03.9/debian/changelog --- slurm-llnl-14.03.9/debian/changelog 2014-11-12 12:07:35.000000000 +0100 +++ slurm-llnl-14.03.9/debian/changelog 2017-07-28 10:52:47.000000000 +0200 @@ -1,3 +1,10 @@ +slurm-llnl (14.03.9-5+deb8u1) jessie-security; urgency=high + + * Fix security issue caused by insecure file path handling triggered by + the failure of a Prolog script (CVE-2016-10030) + + -- Gennaro Oliva <[email protected]> Fri, 28 Jul 2017 10:06:41 +0200 + slurm-llnl (14.03.9-5) unstable; urgency=medium [ Roland Fehrenbacher ] diff -Nru slurm-llnl-14.03.9/debian/patches/CVE-2016-10030 slurm-llnl-14.03.9/debian/patches/CVE-2016-10030 --- slurm-llnl-14.03.9/debian/patches/CVE-2016-10030 1970-01-01 01:00:00.000000000 +0100 +++ slurm-llnl-14.03.9/debian/patches/CVE-2016-10030 2017-07-28 10:03:53.000000000 +0200 @@ -0,0 +1,198 @@ +Description: FIX CVE-2016-10030 + Fix security issue caused by insecure file path handling triggered by + the failure of a Prolog script. To exploit this a user needs to + anticipate or cause the Prolog to fail for their job. +Author: Tim Wickberg <[email protected]> + +--- +Origin: https://github.com/SchedMD/slurm/commit/465c98ccff9f1e0018e6a0e6e86ee485ae480ae6 +Bug: <url in upstream bugtracker> +Bug-Debian: https://bugs.debian.org/850491 +Last-Update: 28-07-2017 + +--- slurm-llnl-14.03.9.orig/src/slurmd/slurmd/req.c ++++ slurm-llnl-14.03.9/src/slurmd/slurmd/req.c +@@ -155,6 +155,7 @@ static int _kill_all_active_steps(uint3 + static void _note_batch_job_finished(uint32_t job_id); + static int _step_limits_match(void *x, void *key); + static int _terminate_all_steps(uint32_t jobid, bool batch); ++static int _receive_fd(int socket); + static void _rpc_launch_tasks(slurm_msg_t *); + static void _rpc_abort_job(slurm_msg_t *); + static void _rpc_batch_job(slurm_msg_t *msg, bool new_msg); +@@ -214,6 +215,7 @@ static void _add_job_running_prolog(uint + static void _remove_job_running_prolog(uint32_t job_id); + static int _compare_job_running_prolog(void *s0, void *s1); + static void _wait_for_job_running_prolog(uint32_t job_id); ++static int _open_as_other(char *path_name, batch_job_launch_msg_t *req); + + /* + * List of threads waiting for jobs to complete +@@ -1275,9 +1277,8 @@ _prolog_error(batch_job_launch_msg_t *re + else + snprintf(path_name, MAXPATHLEN, "/%s", err_name_ptr); + +- if ((fd = open(path_name, (O_CREAT|O_APPEND|O_WRONLY), 0644)) == -1) { +- error("Unable to open %s: %s", path_name, +- slurm_strerror(errno)); ++ if ((fd = _open_as_other(path_name, req)) == -1) { ++ error("Unable to open %s: Permission denied", path_name); + return; + } + snprintf(err_name, sizeof(err_name), +@@ -5306,4 +5307,155 @@ done: + slurm_send_rc_msg(msg, rc); + } + ++/* pass an open file descriptor back to the parent process */ ++static void _send_back_fd(int socket, int fd) ++{ ++ struct msghdr msg = { 0 }; ++ struct cmsghdr *cmsg; ++ char buf[CMSG_SPACE(sizeof(fd))]; ++ memset(buf, '\0', sizeof(buf)); ++ ++ msg.msg_iov = NULL; ++ msg.msg_iovlen = 0; ++ msg.msg_control = buf; ++ msg.msg_controllen = sizeof(buf); ++ ++ cmsg = CMSG_FIRSTHDR(&msg); ++ cmsg->cmsg_level = SOL_SOCKET; ++ cmsg->cmsg_type = SCM_RIGHTS; ++ cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); ++ ++ memmove(CMSG_DATA(cmsg), &fd, sizeof(fd)); ++ msg.msg_controllen = cmsg->cmsg_len; ++ ++ if (sendmsg(socket, &msg, 0) < 0) ++ error("%s: failed to send fd: %m", __func__); ++} + ++/* receive an open file descriptor from fork()'d child over unix socket */ ++static int _receive_fd(int socket) ++{ ++ struct msghdr msg = {0}; ++ struct cmsghdr *cmsg; ++ int fd; ++ msg.msg_iov = NULL; ++ msg.msg_iovlen = 0; ++ char c_buffer[256]; ++ msg.msg_control = c_buffer; ++ msg.msg_controllen = sizeof(c_buffer); ++ ++ if (recvmsg(socket, &msg, 0) < 0) { ++ error("%s: failed to receive fd: %m", __func__); ++ return -1; ++ } ++ ++ cmsg = CMSG_FIRSTHDR(&msg); ++ memmove(&fd, CMSG_DATA(cmsg), sizeof(fd)); ++ return fd; ++} ++ ++/* ++ * Open file based upon permissions of a different user ++ * IN path_name - name of file to open ++ * IN uid - User ID to use for file access check ++ * IN gid - Group ID to use for file access check ++ * RET -1 on error, file descriptor otherwise ++ */ ++static int _open_as_other(char *path_name, batch_job_launch_msg_t *req) ++{ ++ pid_t child; ++ int ngroups = 16; ++ gid_t *groups; ++ int pipe[2]; ++ int fd = -1, rc = 0; ++ ++ if ((rc = _get_grouplist(&req->user_name, req->uid, ++ req->gid, &ngroups, &groups)) < 0) { ++ error("%s: getgrouplist(%u): %m", __func__, req->uid); ++ return rc; ++ } ++ ++ if ((rc = container_g_create(req->job_id))) { ++ error("%s: container_g_create(%u): %m", __func__, req->job_id); ++ xfree(groups); ++ return -1; ++ } ++ ++ /* child process will setuid to the user, register the process ++ * with the container, and open the file for us. */ ++ if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pipe) != 0) { ++ error("%s: Failed to open pipe: %m", __func__); ++ xfree(groups); ++ return -1; ++ } ++ ++ child = fork(); ++ if (child == -1) { ++ error("%s: fork failure", __func__); ++ xfree(groups); ++ close(pipe[0]); ++ close(pipe[1]); ++ return -1; ++ } else if (child > 0) { ++ close(pipe[0]); ++ (void) waitpid(child, &rc, 0); ++ xfree(groups); ++ if (WIFEXITED(rc) && (WEXITSTATUS(rc) == 0)) ++ fd = _receive_fd(pipe[1]); ++ close(pipe[1]); ++ return fd; ++ } ++ ++ /* child process below here */ ++ ++ close(pipe[1]); ++ ++ /* container_g_add_pid needs to be called in the ++ * forked process part of the fork to avoid a race ++ * condition where if this process makes a file or ++ * detacts itself from a child before we add the pid ++ * to the container in the parent of the fork. */ ++ if (container_g_add_pid(req->job_id, getpid(), req->uid)) { ++ error("%s container_g_add_pid(%u): %m", __func__, req->job_id); ++ exit(SLURM_ERROR); ++ } ++ ++ /* The child actually performs the I/O and exits with ++ * a return code, do not return! */ ++ ++ /*********************************************************************\ ++ * NOTE: It would be best to do an exec() immediately after the fork() ++ * in order to help prevent a possible deadlock in the child process ++ * due to locks being set at the time of the fork and being freed by ++ * the parent process, but not freed by the child process. Performing ++ * the work inline is done for simplicity. Note that the logging ++ * performed by error() should be safe due to the use of ++ * atfork_install_handlers() as defined in src/common/log.c. ++ * Change the code below with caution. ++ \*********************************************************************/ ++ ++ if (setgroups(ngroups, groups) < 0) { ++ error("%s: uid: %u setgroups failed: %m", __func__, req->uid); ++ exit(errno); ++ } ++ xfree(groups); ++ ++ if (setgid(req->gid) < 0) { ++ error("%s: uid:%u setgid(%u): %m", __func__, req->uid,req->gid); ++ exit(errno); ++ } ++ if (setuid(req->uid) < 0) { ++ error("%s: getuid(%u): %m", __func__, req->uid); ++ exit(errno); ++ } ++ ++ fd = open(path_name, (O_CREAT|O_APPEND|O_WRONLY), 0644); ++ if (fd == -1) { ++ error("%s: uid:%u can't open `%s`: %m", ++ __func__, req->uid, path_name); ++ exit(errno); ++ } ++ _send_back_fd(pipe[0], fd); ++ close(fd); ++ exit(SLURM_SUCCESS); ++} diff -Nru slurm-llnl-14.03.9/debian/patches/series slurm-llnl-14.03.9/debian/patches/series --- slurm-llnl-14.03.9/debian/patches/series 2014-11-06 10:22:27.000000000 +0100 +++ slurm-llnl-14.03.9/debian/patches/series 2017-07-28 10:02:04.000000000 +0200 @@ -3,3 +3,4 @@ sacctmgr-increase-buffer manpages honor-without-rpath-hwloc +CVE-2016-10030

