Index: head/security/sudo/Makefile =================================================================== --- head/security/sudo/Makefile (revision 468220) +++ head/security/sudo/Makefile (revision 468221) @@ -1,117 +1,117 @@ # Created by: erich@rrnet.com # $FreeBSD$ PORTNAME= sudo PORTVERSION= 1.8.22 -PORTREVISION= 4 +PORTREVISION= 5 CATEGORIES= security MASTER_SITES= SUDO MAINTAINER= garga@FreeBSD.org COMMENT= Allow others to run commands as root LICENSE= sudo LICENSE_NAME= Sudo license LICENSE_FILE= ${WRKSRC}/doc/LICENSE LICENSE_PERMS= dist-mirror dist-sell pkg-mirror pkg-sell auto-accept USES= cpe libtool CPE_VENDOR= todd_miller USE_LDCONFIG= yes GNU_CONFIGURE= yes LDFLAGS+= -lgcc CONFIGURE_ARGS= --sysconfdir=${PREFIX}/etc \ --with-ignore-dot \ --with-tty-tickets \ --with-env-editor \ --with-logincap \ --with-long-otp-prompt OPTIONS_DEFINE= LDAP INSULTS DISABLE_ROOT_SUDO DISABLE_AUTH NOARGS_SHELL \ AUDIT OPIE PAM NLS SSSD DOCS EXAMPLES OPTIONS_RADIO= KERBEROS OPTIONS_DEFAULT= AUDIT PAM OPTIONS_SUB= yes INSULTS_DESC= Enable insults on failures DISABLE_ROOT_SUDO_DESC= Do not allow root to run sudo DISABLE_AUTH_DESC= Do not require authentication by default NOARGS_SHELL_DESC= Run a shell if no arguments are given AUDIT_DESC= Enable BSM audit support KERBEROS_DESC= Enable Kerberos 5 authentication (no PAM support) OPIE_DESC= Enable one-time passwords (no PAM support) SSSD_DESC= Enable SSSD backend support. PAM_PREVENTS= OPIE GSSAPI_BASE GSSAPI_HEIMDAL GSSAPI_MIT PAM_PREVENTS_MSG= PAM cannot be combined with any other authentication plugin LOGFAC?= authpriv CONFIGURE_ARGS+= --with-logfac=${LOGFAC} # This is intentionally not an option. # SUDO_SECURE_PATH is a PATH string that will override the user's PATH. # ex: make SUDO_SECURE_PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin" .if defined(SUDO_SECURE_PATH) CONFIGURE_ARGS+= --with-secure-path="${SUDO_SECURE_PATH}" .endif NLS_USES= gettext NLS_CONFIGURE_ENABLE= nls NLS_LDFLAGS= -L${LOCALBASE}/lib -lintl NLS_CFLAGS= -I${LOCALBASE}/include INSULTS_CONFIGURE_ON= --with-insults INSULTS_CONFIGURE_ON+= --with-all-insults LDAP_USE= OPENLDAP=yes LDAP_CONFIGURE_ON= --with-ldap=${PREFIX} SUDO_LDAP_CONF?= ldap.conf LDAP_CONFIGURE_ON+= --with-ldap-conf-file=${PREFIX}/etc/${SUDO_LDAP_CONF} DISABLE_ROOT_SUDO_CONFIGURE_ON= --disable-root-sudo DISABLE_AUTH_CONFIGURE_ON= --disable-authentication NOARGS_SHELL_CONFIGURE_ENABLE= noargs-shell AUDIT_CONFIGURE_WITH= bsm-audit PAM_CONFIGURE_ON= --with-pam OPIE_CONFIGURE_ON= --with-opie SSSD_CONFIGURE_ON= --with-sssd SSSD_RUN_DEPENDS= sssd:security/sssd OPTIONS_RADIO_KERBEROS= GSSAPI_BASE GSSAPI_HEIMDAL GSSAPI_MIT GSSAPI_BASE_USES= gssapi GSSAPI_BASE_CONFIGURE_ON= --with-kerb5=${GSSAPIBASEDIR} ${GSSAPI_CONFIGURE_ARGS} GSSAPI_HEIMDAL_USES= gssapi:heimdal GSSAPI_HEIMDAL_CONFIGURE_ON= --with-kerb5=${GSSAPIBASEDIR} ${GSSAPI_CONFIGURE_ARGS} GSSAPI_MIT_USES= gssapi:mit GSSAPI_MIT_CONFIGURE_ON= --with-kerb5=${GSSAPIBASEDIR} ${GSSAPI_CONFIGURE_ARGS} # This is intentionally not an option. # SUDO_KERB5_INSTANCE is an optional instance string that will be appended to kerberos # principals when to perform authentication. Common choices are "admin" and "sudo". .if defined(SUDO_KERB5_INSTANCE) CONFIGURE_ARGS+= --enable-kerb5-instance="${SUDO_KERB5_INSTANCE}" .endif .include .if ${ARCH} == "arm" CONFIGURE_ARGS+= --disable-pie .endif post-patch: @${REINPLACE_CMD} -E '/install-(binaries|noexec):/,/^$$/ \ s/\$$\(INSTALL\)/& ${STRIP}/;s/-b\~/-b ~/' \ ${WRKSRC}/src/Makefile.in @${REINPLACE_CMD} -e 's,$$(srcdir)/sudoers2ldif $$(DESTDIR)$$(docdir),$$(srcdir)/sudoers2ldif $$(DESTDIR)$$(bindir),' \ ${WRKSRC}/plugins/sudoers/Makefile.in post-install: ${INSTALL_DATA} ${FILESDIR}/pam.conf ${STAGEDIR}${PREFIX}/etc/pam.d/sudo.default ${RM} ${STAGEDIR}${PREFIX}/etc/sudoers ${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/sudoreplay ${STRIP_CMD} ${STAGEDIR}${PREFIX}/sbin/visudo .for f in group_file.so libsudo_util.so sudoers.so system_group.so ${STRIP_CMD} ${STAGEDIR}${PREFIX}/libexec/sudo/${f} .endfor .include Index: head/security/sudo/files/patch-plugins_sudoers_match.c =================================================================== --- head/security/sudo/files/patch-plugins_sudoers_match.c (revision 468220) +++ head/security/sudo/files/patch-plugins_sudoers_match.c (revision 468221) @@ -1,95 +1,208 @@ ---- plugins/sudoers/match.c.orig 2018-04-24 10:49:39 UTC -+++ plugins/sudoers/match.c -@@ -1,5 +1,5 @@ +--- plugins/sudoers/match.c Mon Jan 15 10:31:56 2018 -0700 ++++ plugins/sudoers/match.c Tue Apr 24 09:49:28 2018 -0600 +@@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2017 + * Copyright (c) 1996, 1998-2005, 2007-2018 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any -@@ -446,32 +446,22 @@ do_stat(int fd, const char *path, struct stat *sb) - debug_return_bool(stat(path, sb) == 0); +@@ -447,31 +447,20 @@ do_stat(int fd, const char *path, struct } -+#ifdef HAVE_FEXECVE /* - * On systems with fexecve(2), set the close-on-exec flag on the file - * descriptor only if the file is not a script. Because scripts need - * to be executed by an interpreter the fd must remain open for the - * interpreter to use. + * Check whether the fd refers to a shell script with a "#!" shebang. */ -static void -set_cloexec(int fd) +static bool +is_script(int fd) { - bool is_script = false; -#ifdef HAVE_FEXECVE + bool ret = false; char magic[2]; - /* Check for #! cookie and set is_script. */ if (read(fd, magic, 2) == 2) { if (magic[0] == '#' && magic[1] == '!') - is_script = true; + ret = true; } (void) lseek(fd, (off_t)0, SEEK_SET); -#endif /* HAVE_FEXECVE */ - /* - * 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) - (void)fcntl(fd, F_SETFD, FD_CLOEXEC); + return ret; } /* -@@ -500,10 +490,36 @@ open_cmnd(const char *path, const struct sudo_digest * +@@ -500,16 +489,57 @@ open_cmnd(const char *path, const struct if (fd == -1) debug_return_bool(false); - set_cloexec(fd); -+ if (is_script(fd)) { -+ char fdpath[PATH_MAX]; -+ struct stat sb; ++ (void)fcntl(fd, F_SETFD, FD_CLOEXEC); + *fdp = fd; + debug_return_bool(true); + } + ++static void ++set_cmnd_fd(int fd) ++{ ++ debug_decl(set_cmnd_fd, SUDOERS_DEBUG_MATCH) + -+ /* We can only use fexecve() on a script if /dev/fd/N exists. */ -+ snprintf(fdpath, sizeof(fdpath), "/dev/fd/%d", fd); -+ if (stat(fdpath, &sb) != 0) { ++ if (cmnd_fd != -1) ++ close(cmnd_fd); ++ ++ if (fd != -1) { ++ if (def_fdexec == never) { ++ /* Never use fexedcve() */ + close(fd); -+ debug_return_bool(true); -+ } ++ fd = -1; ++ } else if (is_script(fd)) { ++ char fdpath[PATH_MAX]; ++ struct stat sb; ++ int flags; + -+ /* -+ * Shell scripts go through namei twice so we can't set the -+ * close on exec flag on the fd for fexecve(2). -+ */ -+ } else { -+ /* Not a script, close on exec is safe. */ -+ (void)fcntl(fd, F_SETFD, FD_CLOEXEC); ++ /* We can only use fexecve() on a script if /dev/fd/N exists. */ ++ snprintf(fdpath, sizeof(fdpath), "/dev/fd/%d", fd); ++ if (stat(fdpath, &sb) != 0) { ++ /* Missing /dev/fd file, can't use fexecve(). */ ++ close(fd); ++ fd = -1; ++ } else { ++ /* ++ * Shell scripts go through namei twice so we can't have the ++ * close on exec flag set on the fd for fexecve(2). ++ */ ++ flags = fcntl(fd, F_GETFD) & ~FD_CLOEXEC; ++ (void)fcntl(fd, F_SETFD, flags); ++ } ++ } + } + - *fdp = fd; - debug_return_bool(true); - } -+#else /* HAVE_FEXECVE */ -+static bool -+open_cmnd(const char *path, const struct sudo_digest *digest, int *fdp) -+{ -+ return true; ++ cmnd_fd = fd; ++ ++ debug_return; +} -+#endif /* HAVE_FEXECVE */ - ++ static bool command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args, -@@ -728,6 +744,7 @@ digest_matches(int fd, const char *file, const struct + const struct sudo_digest *digest) + { + struct stat sb; /* XXX - unused */ ++ int fd = -1; + debug_decl(command_matches_fnmatch, SUDOERS_DEBUG_MATCH) + + /* +@@ -522,30 +552,22 @@ command_matches_fnmatch(const char *sudo + if (fnmatch(sudoers_cmnd, user_cmnd, FNM_PATHNAME) != 0) + debug_return_bool(false); + if (command_args_match(sudoers_cmnd, sudoers_args)) { +- if (cmnd_fd != -1) { +- close(cmnd_fd); +- cmnd_fd = -1; +- } + /* Open the file for fdexec or for digest matching. */ +- if (!open_cmnd(user_cmnd, digest, &cmnd_fd)) ++ if (!open_cmnd(user_cmnd, digest, &fd)) + goto bad; +- if (!do_stat(cmnd_fd, user_cmnd, &sb)) ++ if (!do_stat(fd, user_cmnd, &sb)) + goto bad; + /* Check digest of user_cmnd since sudoers_cmnd is a pattern. */ +- if (digest != NULL) { +- if (!digest_matches(cmnd_fd, user_cmnd, digest)) +- goto bad; +- if (def_fdexec == never) { +- close(cmnd_fd); +- cmnd_fd = -1; +- } +- } ++ if (digest != NULL && !digest_matches(fd, user_cmnd, digest)) ++ goto bad; ++ set_cmnd_fd(fd); ++ + /* No need to set safe_cmnd since user_cmnd matches sudoers_cmnd */ + debug_return_bool(true); + bad: +- if (cmnd_fd != -1) { +- close(cmnd_fd); +- cmnd_fd = -1; ++ if (fd != -1) { ++ close(fd); ++ fd = -1; + } + debug_return_bool(false); + } +@@ -673,16 +695,7 @@ done: + if (cp != NULL) { + if (command_args_match(sudoers_cmnd, sudoers_args)) { + /* safe_cmnd was set above. */ +- if (cmnd_fd != -1) { +- close(cmnd_fd); +- cmnd_fd = -1; +- } +- if (fd != -1) { +- if (def_fdexec == never) +- close(fd); +- else +- cmnd_fd = fd; +- } ++ set_cmnd_fd(fd); + debug_return_bool(true); + } + } +@@ -728,6 +741,7 @@ digest_matches(int fd, const char *file, debug_decl(digest_matches, SUDOERS_DEBUG_MATCH) file_digest = sudo_filedigest(fd, file, sd->digest_type, &digest_len); + lseek(fd, SEEK_SET, (off_t)0); if (file_digest == NULL) { /* Warning (if any) printed by sudo_filedigest() */ goto done; +@@ -826,16 +840,7 @@ command_matches_normal(const char *sudoe + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + goto bad; + } +- if (cmnd_fd != -1) { +- close(cmnd_fd); +- cmnd_fd = -1; +- } +- if (fd != -1) { +- if (def_fdexec == never) +- close(fd); +- else +- cmnd_fd = fd; +- } ++ set_cmnd_fd(fd); + debug_return_bool(true); + bad: + if (fd != -1) +@@ -921,16 +926,7 @@ command_matches_dir(const char *sudoers_ + closedir(dirp); + + if (dent != NULL) { +- if (cmnd_fd != -1) { +- close(cmnd_fd); +- cmnd_fd = -1; +- } +- if (fd != -1) { +- if (def_fdexec == never) +- close(fd); +- else +- cmnd_fd = fd; +- } ++ set_cmnd_fd(fd); + debug_return_bool(true); + } + if (fd != -1)