summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSona Sarmadi <sona.sarmadi@enea.com>2016-08-09 13:04:41 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-09-23 15:27:04 +0100
commit016df260e531c4e8209b3b3a79697c2055f8e0ce (patch)
tree18d558ab592df37ab83cbb31fb6c62862619a5d9
parent5d781f41ff29654520d177c7aab7a244751044a2 (diff)
downloadpoky-016df260e531c4e8209b3b3a79697c2055f8e0ce.tar.gz
poky-016df260e531c4e8209b3b3a79697c2055f8e0ce.tar.bz2
poky-016df260e531c4e8209b3b3a79697c2055f8e0ce.zip
sudo: CVE-2015-8239
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 (From OE-Core rev: 3564999bd987b08188e2e0eead59a49bebbc5e32) Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> Signed-off-by: Armin Kuster <akuster808@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/recipes-extended/sudo/sudo/CVE-2015-8239-1.patch699
-rw-r--r--meta/recipes-extended/sudo/sudo/CVE-2015-8239-2.patch45
-rw-r--r--meta/recipes-extended/sudo/sudo_1.8.15.bb2
3 files changed, 746 insertions, 0 deletions
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
index 0000000000..582c0bf638
--- /dev/null
+++ b/meta/recipes-extended/sudo/sudo/CVE-2015-8239-1.patch
@@ -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.
+
+ DDeeffaauullttss
+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 _u_s_e___p_t_y is enabled.
+
++ execfd=number
++ If specified, ssuuddoo will use the fexecve(2) system call
++ to execute the command instead of execve(2). The
++ specified _n_u_m_b_e_r 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 _e_x_e_c_f_d entry was added to the command_info list.
++
+ SSEEEE AALLSSOO
+ 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
index 0000000000..6c48e4cf14
--- /dev/null
+++ b/meta/recipes-extended/sudo/sudo/CVE-2015-8239-2.patch
@@ -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)) {
+
diff --git a/meta/recipes-extended/sudo/sudo_1.8.15.bb b/meta/recipes-extended/sudo/sudo_1.8.15.bb
index 042043ecef..a03e2cd213 100644
--- a/meta/recipes-extended/sudo/sudo_1.8.15.bb
+++ b/meta/recipes-extended/sudo/sudo_1.8.15.bb
@@ -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"