--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: jessie-pu: package slurm-llnl/14.03.9-5
- From: Gennaro Oliva <oliva.g@na.icar.cnr.it>
- Date: Fri, 28 Jul 2017 15:40:05 +0200
- Message-id: <20170728134005.GA24250@luke.sic.rm.cnr.it>
Package: release.debian.org
Severity: normal
Tags: jessie
User: release.debian.org@packages.debian.org
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 <oliva.g@na.icar.cnr.it> 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 <tim@schedmd.com>
+
+---
+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
--- End Message ---