]> code.ossystems Code Review - openembedded-core.git/commitdiff
sudo: CVE-2015-8239
authorSona Sarmadi <sona.sarmadi@enea.com>
Tue, 9 Aug 2016 11:04:41 +0000 (13:04 +0200)
committerRichard Purdie <richard.purdie@linuxfoundation.org>
Fri, 23 Sep 2016 14:26:08 +0000 (15:26 +0100)
Fixes race condition when checking digests in sudoers.

Reference:
http://seclists.org/oss-sec/2015/q4/327

Reference to upstream fixes:
https://www.sudo.ws/repos/sudo/raw-rev/397722cdd7ec
https://www.sudo.ws/repos/sudo/raw-rev/0cd3cc8fa195

Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
meta/recipes-extended/sudo/sudo/CVE-2015-8239-1.patch [new file with mode: 0644]
meta/recipes-extended/sudo/sudo/CVE-2015-8239-2.patch [new file with mode: 0644]
meta/recipes-extended/sudo/sudo_1.8.15.bb

diff --git a/meta/recipes-extended/sudo/sudo/CVE-2015-8239-1.patch b/meta/recipes-extended/sudo/sudo/CVE-2015-8239-1.patch
new file mode 100644 (file)
index 0000000..582c0bf
--- /dev/null
@@ -0,0 +1,699 @@
+# HG changeset patch
+# User Todd C. Miller <Todd.Miller@courtesan.com>
+# Date 1451928918 25200
+# Node ID 397722cdd7eceef0aec561909418215e275ccd44
+# Parent  33272418bb10ee780184dbd2d966a4e5c3bc597e
+Add support for using fexecve() if supported on commands that are
+checksummed.
+
+Reference to upstream patch:
+https://www.sudo.ws/repos/sudo/rev/397722cdd7ec
+
+CVE: CVE-2015-8239
+Upstream-Status: Backport
+Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
+---
+diff -ruN a/configure b/configure
+--- a/configure        2015-11-01 00:35:24.000000000 +0100
++++ b/configure        2016-08-08 12:56:03.441681854 +0200
+@@ -2650,6 +2650,7 @@
+ as_fn_append ac_header_list " sys/select.h"
+ as_fn_append ac_header_list " sys/stropts.h"
+ as_fn_append ac_header_list " sys/sysmacros.h"
++as_fn_append ac_func_list " fexecve"
+ as_fn_append ac_func_list " killpg"
+ as_fn_append ac_func_list " nl_langinfo"
+ as_fn_append ac_func_list " strftime"
+@@ -18078,6 +18079,8 @@
++
++
+ for ac_func in getgrouplist
+ do :
+   ac_fn_c_check_func "$LINENO" "getgrouplist" "ac_cv_func_getgrouplist"
+@@ -19903,8 +19906,8 @@
+ fi
+ done
+-    # Check for fexecve, posix_spawn, and posix_spawnp
+-    for ac_func in fexecve posix_spawn posix_spawnp
++    # Check for posix_spawn, and posix_spawnp
++    for ac_func in posix_spawn posix_spawnp
+ do :
+   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+diff -ruN a/configure.ac b/configure.ac
+--- a/configure.ac     2016-08-08 12:55:08.781888802 +0200
++++ b/configure.ac     2016-08-08 12:56:03.445681547 +0200
+@@ -1,7 +1,7 @@
+ dnl
+ dnl Use the top-level autogen.sh script to generate configure and config.h.in
+ dnl
+-dnl Copyright (c) 1994-1996,1998-2015 Todd C. Miller <Todd.Miller@courtesan.com>
++dnl Copyright (c) 1994-1996,1998-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+ dnl
+ AC_PREREQ([2.59])
+ AC_INIT([sudo], [1.8.15], [http://www.sudo.ws/bugs/], [sudo])
+@@ -2384,7 +2384,7 @@
+ dnl Function checks
+ dnl
+ AC_FUNC_GETGROUPS
+-AC_CHECK_FUNCS_ONCE([killpg nl_langinfo strftime pread pwrite openat])
++AC_CHECK_FUNCS_ONCE([fexecve killpg nl_langinfo strftime pread pwrite openat])
+ AC_CHECK_FUNCS([getgrouplist], [], [
+     case "$host_os" in
+     aix*)
+@@ -2676,8 +2676,8 @@
+ if test X"$with_noexec" != X"no"; then
+     # Check for non-standard exec functions
+     AC_CHECK_FUNCS([exect execvP execvpe])
+-    # Check for fexecve, posix_spawn, and posix_spawnp
+-    AC_CHECK_FUNCS([fexecve posix_spawn posix_spawnp])
++    # Check for posix_spawn, and posix_spawnp
++    AC_CHECK_FUNCS([posix_spawn posix_spawnp])
+ fi
+ dnl
+diff -ruN a/doc/sudoers.cat b/doc/sudoers.cat
+--- a/doc/sudoers.cat  2016-08-08 12:55:08.781888802 +0200
++++ b/doc/sudoers.cat  2016-08-08 12:56:03.445681547 +0200
+@@ -410,6 +410,13 @@
+      $ openssl dgst -binary -sha224 /bin/ls | openssl base64
+      EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ==
++     Warning, if the user has write access to the command itself (directly or
++     via a sudo command), it may be possible for the user to replace the
++     command after the digest check has been performed but before the command
++     is executed.  A similar race condition exists on systems that lack the
++     fexecve(2) system call when the directory in which the command is located
++     is writable by the user.
++
+      Command digests are only supported by version 1.8.7 or higher.
+    D\bDe\bef\bfa\bau\bul\blt\bts\bs
+diff -ruN a/doc/sudoers.man.in b/doc/sudoers.man.in
+--- a/doc/sudoers.man.in       2016-08-08 12:55:08.781888802 +0200
++++ b/doc/sudoers.man.in       2016-08-08 12:56:03.445681547 +0200
+@@ -1,7 +1,7 @@
+ .\" DO NOT EDIT THIS FILE, IT IS NOT THE MASTER!
+ .\" IT IS GENERATED AUTOMATICALLY FROM sudoers.mdoc.in
+ .\"
+-.\" Copyright (c) 1994-1996, 1998-2005, 2007-2015
++.\" Copyright (c) 1994-1996, 1998-2005, 2007-2016
+ .\"   Todd C. Miller <Todd.Miller@courtesan.com>
+ .\"
+ .\" Permission to use, copy, modify, and distribute this software for any
+@@ -877,6 +877,15 @@
+ .RE
+ .fi
+ .PP
++Warning, if the user has write access to the command itself (directly or via a
++ \fBsudo\fR
++command), it may be possible for the user to replace the command after the
++digest check has been performed but before the command is executed.
++A similar race condition exists on systems that lack the
++fexecve(2)
++system call when the directory in which the command is located
++is writable by the user.
++ .PP
+ Command digests are only supported by version 1.8.7 or higher.
+ .SS "Defaults"
+ Certain configuration options may be changed from their default
+diff -ruN a/doc/sudoers.mdoc.in b/doc/sudoers.mdoc.in
+--- a/doc/sudoers.mdoc.in      2016-08-08 12:55:08.781888802 +0200
++++ b/doc/sudoers.mdoc.in      2016-08-08 12:56:03.449681239 +0200
+@@ -1,5 +1,5 @@
+ .\"
+-.\" Copyright (c) 1994-1996, 1998-2005, 2007-2015
++.\" Copyright (c) 1994-1996, 1998-2005, 2007-2016
+ .\"   Todd C. Miller <Todd.Miller@courtesan.com>
+ .\"
+ .\" Permission to use, copy, modify, and distribute this software for any
+@@ -834,6 +834,15 @@
+ EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ==
+ .Ed
+ .Pp
++Warning, if the user has write access to the command itself (directly or via a
++ .Nm sudo
++command), it may be possible for the user to replace the command after the
++digest check has been performed but before the command is executed.
++A similar race condition exists on systems that lack the
++.Xr fexecve 2
++system call when the directory in which the command is located
++is writable by the user.
++ .Pp
+ Command digests are only supported by version 1.8.7 or higher.
+ .Ss Defaults
+ Certain configuration options may be changed from their default
+diff -ruN a/doc/sudo_plugin.cat b/doc/sudo_plugin.cat
+--- a/doc/sudo_plugin.cat      2016-08-08 12:55:08.781888802 +0200
++++ b/doc/sudo_plugin.cat      2016-08-08 12:56:03.449681239 +0200
+@@ -499,6 +499,11 @@
+                        This setting has no effect unless I/O logging is
+                        enabled or _\bu_\bs_\be_\b__\bp_\bt_\by is enabled.
++                 execfd=number
++                       If specified, s\bsu\bud\bdo\bo will use the fexecve(2) system call
++                       to execute the command instead of execve(2).  The
++                       specified _\bn_\bu_\bm_\bb_\be_\br must refer to an open file descriptor.
++
+                  iolog_compress=bool
+                        Set to true if the I/O logging plugins, if any, should
+                        compress the log data.  This is a hint to the I/O
+@@ -1505,6 +1510,9 @@
+            it supports plugin API version 1.8 or higher to receive a
+            conversation function pointer that supports this argument.
++     Version 1.9 (sudo 1.8.16)
++           The _\be_\bx_\be_\bc_\bf_\bd entry was added to the command_info list.
++
+ S\bSE\bEE\bE A\bAL\bLS\bSO\bO
+      sudo.conf(4), sudoers(4), sudo(1m)
+diff -ruN a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in
+--- a/doc/sudo_plugin.man.in   2016-08-08 12:55:08.781888802 +0200
++++ b/doc/sudo_plugin.man.in   2016-08-08 12:56:03.449681239 +0200
+@@ -1,7 +1,7 @@
+ .\" DO NOT EDIT THIS FILE, IT IS NOT THE MASTER!
+ .\" IT IS GENERATED AUTOMATICALLY FROM sudo_plugin.mdoc.in
+ .\"
+-.\" Copyright (c) 2009-2015 Todd C. Miller <Todd.Miller@courtesan.com>
++.\" Copyright (c) 2009-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+ .\"
+ .\" Permission to use, copy, modify, and distribute this software for any
+ .\" purpose with or without fee is hereby granted, provided that the above
+@@ -881,6 +881,17 @@
+ \fIuse_pty\fR
+ is enabled.
+ .TP 6n
++execfd=number
++If specified,
++\fBsudo\fR
++will use the
++fexecve(2)
++system call to execute the command instead of
++execve(2).
++The specified
++\fInumber\fR
++must refer to an open file descriptor.
++.TP 6n
+ iolog_compress=bool
+ Set to true if the I/O logging plugins, if any, should compress the
+ log data.
+@@ -2703,6 +2714,13 @@
+ definition has been updated to match.
+ The plugin must specify that it supports plugin API version 1.8 or higher
+ to receive a conversation function pointer that supports this argument.
++.TP 6n
++Version 1.9 (sudo 1.8.16)
++The
++\fIexecfd\fR
++entry was added to the
++\fRcommand_info\fR
++list.
+ .SH "SEE ALSO"
+ sudo.conf(@mansectform@),
+ sudoers(@mansectform@),
+diff -ruN a/doc/sudo_plugin.mdoc.in b/doc/sudo_plugin.mdoc.in
+--- a/doc/sudo_plugin.mdoc.in  2016-08-08 12:55:08.781888802 +0200
++++ b/doc/sudo_plugin.mdoc.in  2016-08-08 12:56:03.453680931 +0200
+@@ -1,5 +1,5 @@
+ .\"
+-.\" Copyright (c) 2009-2015 Todd C. Miller <Todd.Miller@courtesan.com>
++.\" Copyright (c) 2009-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+ .\"
+ .\" Permission to use, copy, modify, and distribute this software for any
+ .\" purpose with or without fee is hereby granted, provided that the above
+@@ -784,6 +784,16 @@
+ This setting has no effect unless I/O logging is enabled or
+ .Em use_pty
+ is enabled.
++.It execfd=number
++If specified,
++.Nm sudo
++will use the
++.Xr fexecve 2
++system call to execute the command instead of
++.Xr execve 2 .
++The specified
++.Em number
++must refer to an open file descriptor.
+ .It iolog_compress=bool
+ Set to true if the I/O logging plugins, if any, should compress the
+ log data.
+@@ -2367,6 +2377,12 @@
+ definition has been updated to match.
+ The plugin must specify that it supports plugin API version 1.8 or higher
+ to receive a conversation function pointer that supports this argument.
++.It Version 1.9 (sudo 1.8.16)
++The
++.Em execfd
++entry was added to the
++.Li command_info
++list.
+ .El
+ .Sh SEE ALSO
+ .Xr sudo.conf @mansectform@ ,
+diff -ruN a/include/sudo_plugin.h b/include/sudo_plugin.h
+--- a/include/sudo_plugin.h    2016-08-08 12:55:08.781888802 +0200
++++ b/include/sudo_plugin.h    2016-08-08 12:56:03.453680931 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2009-2015 Todd C. Miller <Todd.Miller@courtesan.com>
++ * Copyright (c) 2009-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -19,7 +19,7 @@
+ /* API version major/minor */
+ #define SUDO_API_VERSION_MAJOR 1
+-#define SUDO_API_VERSION_MINOR 8
++#define SUDO_API_VERSION_MINOR 9
+ #define SUDO_API_MKVERSION(x, y) (((x) << 16) | (y))
+ #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR)
+diff -ruN a/plugins/sudoers/match.c b/plugins/sudoers/match.c
+--- a/plugins/sudoers/match.c  2016-08-08 12:55:08.781888802 +0200
++++ b/plugins/sudoers/match.c  2016-08-08 12:56:03.453680931 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 1998-2005, 2007-2015
++ * Copyright (c) 1996, 1998-2005, 2007-2016
+  *    Todd C. Miller <Todd.Miller@courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+@@ -55,6 +55,7 @@
+ # include <netdb.h>
+ #endif /* HAVE_NETGROUP_H */
+ #include <dirent.h>
++#include <fcntl.h>
+ #include <pwd.h>
+ #include <grp.h>
+ #include <errno.h>
+@@ -583,17 +584,18 @@
+ };
+ static bool
+-digest_matches(const char *file, const struct sudo_digest *sd)
++digest_matches(const char *file, const struct sudo_digest *sd, int *fd)
+ {
+     unsigned char file_digest[SHA512_DIGEST_LENGTH];
+     unsigned char sudoers_digest[SHA512_DIGEST_LENGTH];
+     unsigned char buf[32 * 1024];
+     struct digest_function *func = NULL;
++    bool first = true;
++    bool is_script = false;
+     size_t nread;
+     SHA2_CTX ctx;
+     FILE *fp;
+     unsigned int i;
+-    int h;
+     debug_decl(digest_matches, SUDOERS_DEBUG_MATCH)
+     for (i = 0; digest_functions[i].digest_name != NULL; i++) {
+@@ -609,7 +611,7 @@
+     if (strlen(sd->digest_str) == func->digest_len * 2) {
+       /* Convert the command digest from ascii hex to binary. */
+       for (i = 0; i < func->digest_len; i++) {
+-          h = hexchar(&sd->digest_str[i + i]);
++          const int h = hexchar(&sd->digest_str[i + i]);
+           if (h == -1)
+               goto bad_format;
+           sudoers_digest[i] = (unsigned char)h;
+@@ -633,6 +635,12 @@
+     func->init(&ctx);
+     while ((nread = fread(buf, 1, sizeof(buf), fp)) != 0) {
++      /* Check for #! cookie and set is_script. */
++      if (first) {
++          first = false;
++          if (nread >= 2 && buf[0] == '#' && buf[1] == '!')
++              is_script = true;
++      }
+       func->update(&ctx, buf, nread);
+     }
+     if (ferror(fp)) {
+@@ -640,15 +648,36 @@
+       fclose(fp);
+       debug_return_bool(false);
+     }
+-    fclose(fp);
+     func->final(file_digest, &ctx);
+-    if (memcmp(file_digest, sudoers_digest, func->digest_len) == 0)
+-      debug_return_bool(true);
+-    sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
+-      "%s digest mismatch for %s, expecting %s",
+-      func->digest_name, file, sd->digest_str);
+-    debug_return_bool(false);
++    if (memcmp(file_digest, sudoers_digest, func->digest_len) != 0) {
++      fclose(fp);
++      sudo_debug_printf(SUDO_DEBUG_DIAG|SUDO_DEBUG_LINENO,
++          "%s digest mismatch for %s, expecting %s",
++          func->digest_name, file, sd->digest_str);
++      debug_return_bool(false);
++    }
++
++#ifdef HAVE_FEXECVE
++    /*
++     * On systems with fexecve(2) we can use that to execute the
++     * matching command even when the directory is writable.
++     */
++    if ((*fd = dup(fileno(fp))) == -1) {
++      sudo_debug_printf(SUDO_DEBUG_INFO, "unable to dup %s: %s",
++          file, strerror(errno));
++      fclose(fp);
++      debug_return_bool(false);
++    }
++    /*
++     * Shell scripts go through namei twice and so we can't set the close
++     * on exec flag on the fd for fexecve(2).
++     */
++    if (!is_script)
++      fcntl(*fd, F_SETFD, FD_CLOEXEC);
++#endif /* HAVE_FEXECVE */
++    fclose(fp);
++    debug_return_bool(true);
+ bad_format:
+     sudo_warnx(U_("digest for %s (%s) is not in %s form"), file,
+       sd->digest_str, func->digest_name);
+@@ -690,7 +719,11 @@
+       debug_return_bool(false);
+     if (!command_args_match(sudoers_cmnd, sudoers_args))
+       debug_return_bool(false);
+-    if (digest != NULL && !digest_matches(sudoers_cmnd, digest)) {
++    if (cmnd_fd != -1) {
++      close(cmnd_fd);
++      cmnd_fd = -1;
++    }
++    if (digest != NULL && !digest_matches(sudoers_cmnd, digest, &cmnd_fd)) {
+       /* XXX - log functions not available but we should log very loudly */
+       debug_return_bool(false);
+     }
+diff -ruN a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c
+--- a/plugins/sudoers/policy.c 2016-08-08 12:55:08.781888802 +0200
++++ b/plugins/sudoers/policy.c 2016-08-08 12:56:03.457680623 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2010-2015 Todd C. Miller <Todd.Miller@courtesan.com>
++ * Copyright (c) 2010-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -371,6 +371,9 @@
+     user_umask = umask(SUDO_UMASK);
+     umask(user_umask);
++    /* Some systems support fexecve() which we use for digest matches. */
++    cmnd_fd = -1;
++
+     /* Dump settings and user info (XXX - plugin args) */
+     for (cur = info->settings; *cur != NULL; cur++)
+       sudo_debug_printf(SUDO_DEBUG_INFO, "settings: %s", *cur);
+@@ -545,6 +548,16 @@
+       if (asprintf(&command_info[info_len++], "umask=0%o", (unsigned int)cmnd_umask) == -1)
+           goto oom;
+     }
++    if (cmnd_fd != -1) {
++      if (sudo_version < SUDO_API_MKVERSION(1, 9)) {
++          /* execfd only supported by plugin API 1.9 and higher */
++          close(cmnd_fd);
++          cmnd_fd = -1;
++      } else {
++          if (asprintf(&command_info[info_len++], "execfd=%d", cmnd_fd) == -1)
++              goto oom;
++      }
++    }
+ #ifdef HAVE_LOGIN_CAP_H
+     if (def_use_loginclass) {
+       if ((command_info[info_len++] = sudo_new_key_val("login_class", login_class)) == NULL)
+diff -ruN a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h
+--- a/plugins/sudoers/sudoers.h        2016-08-08 12:55:08.781888802 +0200
++++ b/plugins/sudoers/sudoers.h        2016-08-08 12:56:03.457680623 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1993-1996, 1998-2005, 2007-2015
++ * Copyright (c) 1993-1996, 1998-2005, 2007-2016
+  *    Todd C. Miller <Todd.Miller@courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+@@ -90,6 +90,7 @@
+     const char *cwd;
+     char *iolog_file;
+     GETGROUPS_T *gids;
++    int   execfd;
+     int   ngids;
+     int   closefrom;
+     int   lines;
+@@ -197,6 +198,7 @@
+ #define user_srunhost         (sudo_user.srunhost)
+ #define user_ccname           (sudo_user.krb5_ccname)
+ #define safe_cmnd             (sudo_user.cmnd_safe)
++#define cmnd_fd                       (sudo_user.execfd)
+ #define login_class           (sudo_user.class_name)
+ #define runas_pw              (sudo_user._runas_pw)
+ #define runas_gr              (sudo_user._runas_gr)
+diff -ruN a/src/exec.c b/src/exec.c
+--- a/src/exec.c       2016-08-08 12:55:08.781888802 +0200
++++ b/src/exec.c       2016-08-08 12:56:03.457680623 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2009-2015 Todd C. Miller <Todd.Miller@courtesan.com>
++ * Copyright (c) 2009-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -176,13 +176,13 @@
+       }
+ #ifdef HAVE_SELINUX
+       if (ISSET(details->flags, CD_RBAC_ENABLED)) {
+-          selinux_execve(details->command, details->argv, details->envp,
+-              ISSET(details->flags, CD_NOEXEC));
++          selinux_execve(details->execfd, details->command, details->argv,
++              details->envp, ISSET(details->flags, CD_NOEXEC));
+       } else
+ #endif
+       {
+-          sudo_execve(details->command, details->argv, details->envp,
+-              ISSET(details->flags, CD_NOEXEC));
++          sudo_execve(details->execfd, details->command, details->argv,
++              details->envp, ISSET(details->flags, CD_NOEXEC));
+       }
+     }
+     cstat->type = CMD_ERRNO;
+diff -ruN a/src/exec_common.c b/src/exec_common.c
+--- a/src/exec_common.c        2016-08-08 12:55:08.781888802 +0200
++++ b/src/exec_common.c        2016-08-08 12:56:03.457680623 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2009-2015 Todd C. Miller <Todd.Miller@courtesan.com>
++ * Copyright (c) 2009-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -134,14 +134,19 @@
+  * ala execvp(3) if we get ENOEXEC.
+  */
+ int
+-sudo_execve(const char *path, char *const argv[], char *const envp[], bool noexec)
++sudo_execve(int fd, const char *path, char *const argv[], char *const envp[], bool noexec)
+ {
+     /* Modify the environment as needed to disable further execve(). */
+     if (noexec)
+       envp = disable_execute(envp);
+-    execve(path, argv, envp);
+-    if (errno == ENOEXEC) {
++#ifdef HAVE_FEXECVE
++    if (fd != -1)
++           fexecve(fd, argv, envp);
++    else
++#endif
++           execve(path, argv, envp);
++    if (fd == -1 && errno == ENOEXEC) {
+       int argc;
+       char **nargv;
+diff -ruN a/src/selinux.c b/src/selinux.c
+--- a/src/selinux.c    2016-08-08 12:55:08.781888802 +0200
++++ b/src/selinux.c    2016-08-08 12:56:03.461680315 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2009-2015 Todd C. Miller <Todd.Miller@courtesan.com>
++ * Copyright (c) 2009-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+  * Copyright (c) 2008 Dan Walsh <dwalsh@redhat.com>
+  *
+  * Borrowed heavily from newrole source code
+@@ -373,7 +373,7 @@
+ }
+ void
+-selinux_execve(const char *path, char *const argv[], char *const envp[],
++selinux_execve(int fd, const char *path, char *const argv[], char *const envp[],
+     int noexec)
+ {
+     char **nargv;
+@@ -409,6 +409,8 @@
+      */
+     for (argc = 0; argv[argc] != NULL; argc++)
+       continue;
++    if (fd != -1)
++      argc++;
+     nargv = reallocarray(NULL, argc + 2, sizeof(char *));
+     if (nargv == NULL) {
+       sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
+@@ -418,11 +420,16 @@
+       nargv[0] = *argv[0] == '-' ? "-sesh-noexec" : "sesh-noexec";
+     else
+       nargv[0] = *argv[0] == '-' ? "-sesh" : "sesh";
+-    nargv[1] = (char *)path;
+-    memcpy(&nargv[2], &argv[1], argc * sizeof(char *)); /* copies NULL */
++    argc = 1;
++    if (fd != -1 && asprintf(&nargv[argc++], "--execfd=%d", fd) == -1) {
++      sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
++      debug_return;
++    }
++    nargv[argc] = (char *)path;
++    memcpy(&nargv[argc + 1], &argv[argc], argc * sizeof(char *)); /* copies NULL */
+     /* sesh will handle noexec for us. */
+-    sudo_execve(sesh, nargv, envp, false);
++    sudo_execve(-1, sesh, nargv, envp, false);
+     serrno = errno;
+     free(nargv);
+     errno = serrno;
+diff -ruN a/src/sesh.c b/src/sesh.c
+--- a/src/sesh.c       2016-08-08 12:55:08.781888802 +0200
++++ b/src/sesh.c       2016-08-08 12:56:03.461680315 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2008, 2010-2015 Todd C. Miller <Todd.Miller@courtesan.com>
++ * Copyright (c) 2008, 2010-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -87,6 +87,7 @@
+     } else {
+       bool login_shell, noexec = false;
+       char *cp, *cmnd;
++      int fd = -1;
+       /* If the first char of argv[0] is '-', we are running a login shell. */
+       login_shell = argv[0][0] == '-';
+@@ -95,6 +96,18 @@
+       if ((cp = strrchr(argv[0], '-')) != NULL && cp != argv[0])
+           noexec = strcmp(cp, "-noexec") == 0;
++      /* If argv[1] is --execfd=%d, extract the fd to exec with. */
++      if (strncmp(argv[1], "--execfd=", 9) == 0) {
++          const char *errstr;
++
++          cp = argv[1] + 9;
++          fd = strtonum(cp, 0, INT_MAX, &errstr);
++          if (errstr != NULL)
++              sudo_fatalx(U_("invalid file descriptor number: %s"), cp);
++          argv++;
++          argc--;
++      }
++
+       /* Shift argv and make a copy of the command to execute. */
+       argv++;
+       argc--;
+@@ -108,7 +121,7 @@
+           *cp = '-';
+           argv[0] = cp;
+       }
+-      sudo_execve(cmnd, argv, envp, noexec);
++      sudo_execve(fd, cmnd, argv, envp, noexec);
+       sudo_warn(U_("unable to execute %s"), cmnd);
+       ret = SESH_ERR_FAILURE;
+     }
+diff -ruN a/src/sudo.c b/src/sudo.c
+--- a/src/sudo.c       2016-08-08 12:55:08.781888802 +0200
++++ b/src/sudo.c       2016-08-08 12:56:03.461680315 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2009-2015 Todd C. Miller <Todd.Miller@courtesan.com>
++ * Copyright (c) 2009-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -585,6 +585,7 @@
+     memset(details, 0, sizeof(*details));
+     details->closefrom = -1;
++    details->execfd = -1;
+     TAILQ_INIT(&details->preserved_fds);
+ #define SET_STRING(s, n) \
+@@ -615,6 +616,21 @@
+                       SET(details->flags, CD_EXEC_BG);
+                   break;
+               }
++              if (strncmp("execfd=", info[i], sizeof("execfd=") - 1) == 0) {
++                  cp = info[i] + sizeof("execfd=") - 1;
++                  details->execfd = strtonum(cp, 0, INT_MAX, &errstr);
++                  if (errstr != NULL)
++                      sudo_fatalx(U_("%s: %s"), info[i], U_(errstr));
++#ifdef HAVE_FEXECVE
++                  /* Must keep fd open during exec. */
++                  add_preserved_fd(&details->preserved_fds, details->execfd);
++#else
++                  /* Plugin thinks we support fexecve() but we don't. */
++                  fcntl(details->execfd, F_SETFD, FD_CLOEXEC);
++                  details->execfd = -1;
++#endif
++                  break;
++              }
+               break;
+           case 'l':
+               SET_STRING("login_class=", login_class)
+diff -ruN a/src/sudo_exec.h b/src/sudo_exec.h
+--- a/src/sudo_exec.h  2016-08-08 12:55:08.781888802 +0200
++++ b/src/sudo_exec.h  2016-08-08 13:04:19.127533565 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2010-2013 Todd C. Miller <Todd.Miller@courtesan.com>
++ * Copyright (c) 2010-2016 Todd C. Miller <Todd.Miller@courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+  * purpose with or without fee is hereby granted, provided that the above
+@@ -74,7 +74,7 @@
+ /* exec.c */
+ struct sudo_event_base;
+-int sudo_execve(const char *path, char *const argv[], char *const envp[], bool noexec);
++int sudo_execve(int fd, const char *path, char *const argv[], char *const envp[], bool noexec);
+ extern volatile pid_t cmnd_pid;
+ /* exec_pty.c */
+diff -ruN a/src/sudo.h b/src/sudo.h
+--- a/src/sudo.h       2016-08-08 12:55:08.781888802 +0200
++++ b/src/sudo.h       2016-08-08 12:56:03.465680007 +0200
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1993-1996, 1998-2005, 2007-2014
++ * Copyright (c) 1993-1996, 1998-2005, 2007-2016
+  *    Todd C. Miller <Todd.Miller@courtesan.com>
+  *
+  * Permission to use, copy, modify, and distribute this software for any
+@@ -149,6 +149,7 @@
+     int ngroups;
+     int closefrom;
+     int flags;
++    int execfd;
+     struct preserved_fd_list preserved_fds;
+     struct passwd *pw;
+     GETGROUPS_T *groups;
+@@ -221,7 +222,7 @@
+ int selinux_restore_tty(void);
+ int selinux_setup(const char *role, const char *type, const char *ttyn,
+     int ttyfd);
+-void selinux_execve(const char *path, char *const argv[], char *const envp[],
++void selinux_execve(int fd, const char *path, char *const argv[], char *envp[],
+     int noexec);
+ /* solaris.c */
diff --git a/meta/recipes-extended/sudo/sudo/CVE-2015-8239-2.patch b/meta/recipes-extended/sudo/sudo/CVE-2015-8239-2.patch
new file mode 100644 (file)
index 0000000..6c48e4c
--- /dev/null
@@ -0,0 +1,45 @@
+
+# HG changeset patch
+# User Todd C. Miller <Todd.Miller@courtesan.com>
+# Date 1452556552 25200
+# Node ID 0cd3cc8fa19565d3f7eb7d960f6ba5da0dec4889
+# Parent  4d2c1761c75245fb88ce397d68bea10afea9c037
+Silence warning in digest_matches() on systems with no fexecve(2).
+
+Reference to upstream patch:
+https://www.sudo.ws/repos/sudo/raw-rev/0cd3cc8fa195
+
+CVE: CVE-2015-8239
+Upstream-Status: Backport
+Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
+---
+diff -r 4d2c1761c752 -r 0cd3cc8fa195 plugins/sudoers/match.c
+--- a/plugins/sudoers/match.c  Mon Jan 11 16:52:52 2016 -0700
++++ b/plugins/sudoers/match.c  Mon Jan 11 16:55:52 2016 -0700
+@@ -590,8 +590,10 @@
+     unsigned char sudoers_digest[SHA512_DIGEST_LENGTH];
+     unsigned char buf[32 * 1024];
+     struct digest_function *func = NULL;
++#ifdef HAVE_FEXECVE
+     bool first = true;
+     bool is_script = false;
++#endif /* HAVE_FEXECVE */
+     size_t nread;
+     SHA2_CTX ctx;
+     FILE *fp;
+@@ -635,12 +637,14 @@
+     func->init(&ctx);
+     while ((nread = fread(buf, 1, sizeof(buf), fp)) != 0) {
++#ifdef HAVE_FEXECVE
+       /* Check for #! cookie and set is_script. */
+       if (first) {
+           first = false;
+           if (nread >= 2 && buf[0] == '#' && buf[1] == '!')
+               is_script = true;
+       }
++#endif /* HAVE_FEXECVE */
+       func->update(&ctx, buf, nread);
+     }
+     if (ferror(fp)) {
+
index 042043ecef8d24c899ec438a04db2cf6aca1f16e..a03e2cd213d9c221e038d1afc433dbc0b6e14920 100644 (file)
@@ -3,6 +3,8 @@ require sudo.inc
 SRC_URI = "http://ftp.sudo.ws/sudo/dist/sudo-${PV}.tar.gz \
            ${@bb.utils.contains('DISTRO_FEATURES', 'pam', '${PAM_SRC_URI}', '', d)} \
            file://0001-Include-sys-types.h-for-id_t-definition.patch \
+           file://CVE-2015-8239-1.patch \
+           file://CVE-2015-8239-2.patch \
            "
 
 PAM_SRC_URI = "file://sudo.pam"