diff --git a/SOURCES/sudo-1.9.7-tty-relabel1.patch b/SOURCES/sudo-1.9.7-tty-relabel1.patch new file mode 100644 index 0000000..678f613 --- /dev/null +++ b/SOURCES/sudo-1.9.7-tty-relabel1.patch @@ -0,0 +1,235 @@ +From bcf8c3dd5ea4c085d1f6f8e7cbee0c516a4e1d78 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Fri, 27 Sep 2019 08:47:41 -0600 +Subject: [PATCH] Add some debugging around context setting and tty labeling + Also be more extact with error return values + +--- + src/selinux.c | 96 ++++++++++++++++++++++++++++----------------------- + 1 file changed, 52 insertions(+), 44 deletions(-) + +diff --git a/src/selinux.c b/src/selinux.c +index e56be9e17..801999e61 100644 +--- a/src/selinux.c ++++ b/src/selinux.c +@@ -106,42 +106,53 @@ audit_role_change(const security_context_t old_context, + * fd - referencing the opened ttyn + * ttyn - name of tty to restore + * +- * Returns zero on success, non-zero otherwise ++ * Returns 0 on success and -1 on failure. + */ + int + selinux_restore_tty(void) + { +- int retval = 0; ++ int ret = -1; + security_context_t chk_tty_context = NULL; + debug_decl(selinux_restore_tty, SUDO_DEBUG_SELINUX) + +- if (se_state.ttyfd == -1 || se_state.new_tty_context == NULL) +- goto skip_relabel; ++ if (se_state.ttyfd == -1 || se_state.new_tty_context == NULL) { ++ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: no tty, skip relabel", ++ __func__); ++ debug_return_int(0); ++ } ++ ++ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %s -> %s", ++ __func__, se_state.new_tty_context, se_state.tty_context); + + /* Verify that the tty still has the context set by sudo. */ +- if ((retval = fgetfilecon(se_state.ttyfd, &chk_tty_context)) < 0) { ++ if (fgetfilecon(se_state.ttyfd, &chk_tty_context) == -1) { + sudo_warn(U_("unable to fgetfilecon %s"), se_state.ttyn); + goto skip_relabel; + } + +- if ((retval = strcmp(chk_tty_context, se_state.new_tty_context))) { ++ if (strcmp(chk_tty_context, se_state.new_tty_context) == 0) { + sudo_warnx(U_("%s changed labels"), se_state.ttyn); ++ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: tty label changed, skipping", ++ __func__); + goto skip_relabel; + } + +- if ((retval = fsetfilecon(se_state.ttyfd, se_state.tty_context)) < 0) ++ if (fsetfilecon(se_state.ttyfd, se_state.tty_context) == -1) { + sudo_warn(U_("unable to restore context for %s"), se_state.ttyn); ++ goto skip_relabel; ++ } ++ ++ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: successfully set tty label to %s", ++ __func__, se_state.tty_context); ++ ret = 0; + + skip_relabel: + if (se_state.ttyfd != -1) { + close(se_state.ttyfd); + se_state.ttyfd = -1; + } +- if (chk_tty_context != NULL) { +- freecon(chk_tty_context); +- chk_tty_context = NULL; +- } +- debug_return_int(retval); ++ freecon(chk_tty_context); ++ debug_return_int(ret); + } + + /* +@@ -164,8 +175,11 @@ relabel_tty(const char *ttyn, int ptyfd) + se_state.ttyfd = ptyfd; + + /* It is perfectly legal to have no tty. */ +- if (ptyfd == -1 && ttyn == NULL) ++ if (ptyfd == -1 && ttyn == NULL) { ++ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: no tty, skip relabel", ++ __func__); + debug_return_int(0); ++ } + + /* If sudo is not allocating a pty for the command, open current tty. */ + if (ptyfd == -1) { +@@ -183,26 +197,28 @@ relabel_tty(const char *ttyn, int ptyfd) + fcntl(se_state.ttyfd, F_GETFL, 0) & ~O_NONBLOCK); + } + +- if (fgetfilecon(se_state.ttyfd, &tty_con) < 0) { ++ if (fgetfilecon(se_state.ttyfd, &tty_con) == -1) { + sudo_warn(U_("unable to get current tty context, not relabeling tty")); + goto bad; + } + +- if (tty_con) { ++ if (tty_con != NULL) { + security_class_t tclass = string_to_security_class("chr_file"); + if (tclass == 0) { + sudo_warn(U_("unknown security class \"chr_file\", not relabeling tty")); + goto bad; + } + if (security_compute_relabel(se_state.new_context, tty_con, +- tclass, &new_tty_con) < 0) { ++ tclass, &new_tty_con) == -1) { + sudo_warn(U_("unable to get new tty context, not relabeling tty")); + goto bad; + } + } + + if (new_tty_con != NULL) { +- if (fsetfilecon(se_state.ttyfd, new_tty_con) < 0) { ++ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: tty context %s -> %s", ++ __func__, tty_con, new_tty_con); ++ if (fsetfilecon(se_state.ttyfd, new_tty_con) == -1) { + sudo_warn(U_("unable to set new tty context")); + goto bad; + } +@@ -276,12 +292,12 @@ get_exec_context(security_context_t old_context, const char *role, const char *t + debug_decl(get_exec_context, SUDO_DEBUG_SELINUX) + + /* We must have a role, the type is optional (we can use the default). */ +- if (!role) { ++ if (role == NULL) { + sudo_warnx(U_("you must specify a role for type %s"), type); + errno = EINVAL; + goto bad; + } +- if (!type) { ++ if (type == NULL) { + if (get_default_type(role, &typebuf)) { + sudo_warnx(U_("unable to get default type for role %s"), role); + errno = EINVAL; +@@ -291,10 +307,13 @@ get_exec_context(security_context_t old_context, const char *role, const char *t + } + + /* +- * Expand old_context into a context_t so that we extract and modify ++ * Expand old_context into a context_t so that we can extract and modify + * its components easily. + */ +- context = context_new(old_context); ++ if ((context = context_new(old_context)) == NULL) { ++ sudo_warn(U_("failed to get new context")); ++ goto bad; ++ } + + /* + * Replace the role and type in "context" with the role and +@@ -316,24 +335,20 @@ get_exec_context(security_context_t old_context, const char *role, const char *t + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + goto bad; + } +- if (security_check_context(new_context) < 0) { ++ if (security_check_context(new_context) == -1) { + sudo_warnx(U_("%s is not a valid context"), new_context); + errno = EINVAL; + goto bad; + } + +-#ifdef DEBUG +- sudo_warnx("Your new context is %s", new_context); +-#endif +- + context_free(context); +- debug_return_ptr(new_context); ++ debug_return_str(new_context); + + bad: + free(typebuf); + context_free(context); + freecon(new_context); +- debug_return_ptr(NULL); ++ debug_return_str(NULL); + } + + /* +@@ -352,40 +367,33 @@ selinux_setup(const char *role, const char *type, const char *ttyn, + + /* Store the caller's SID in old_context. */ + if (getprevcon(&se_state.old_context)) { +- sudo_warn(U_("failed to get old_context")); ++ sudo_warn(U_("failed to get old context")); + goto done; + } + + se_state.enforcing = security_getenforce(); +- if (se_state.enforcing < 0) { ++ if (se_state.enforcing == -1) { + sudo_warn(U_("unable to determine enforcing mode.")); + goto done; + } + +-#ifdef DEBUG +- sudo_warnx("your old context was %s", se_state.old_context); +-#endif ++ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: old context %s", __func__, ++ se_state.old_context); + se_state.new_context = get_exec_context(se_state.old_context, role, type); +- if (!se_state.new_context) { ++ if (se_state.new_context == NULL) { + #ifdef HAVE_LINUX_AUDIT +- audit_role_change(se_state.old_context, "?", +- se_state.ttyn, 0); ++ audit_role_change(se_state.old_context, "?", se_state.ttyn, 0); + #endif + goto done; + } ++ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: new context %s", __func__, ++ se_state.new_context); + +- if (relabel_tty(ttyn, ptyfd) < 0) { ++ if (relabel_tty(ttyn, ptyfd) == -1) { + sudo_warn(U_("unable to set tty context to %s"), se_state.new_context); + goto done; + } + +-#ifdef DEBUG +- if (se_state.ttyfd != -1) { +- sudo_warnx("your old tty context is %s", se_state.tty_context); +- sudo_warnx("your new tty context is %s", se_state.new_tty_context); +- } +-#endif +- + #ifdef HAVE_LINUX_AUDIT + audit_role_change(se_state.old_context, se_state.new_context, + se_state.ttyn, 1); diff --git a/SOURCES/sudo-1.9.7-tty-relabel2.patch b/SOURCES/sudo-1.9.7-tty-relabel2.patch new file mode 100644 index 0000000..6095352 --- /dev/null +++ b/SOURCES/sudo-1.9.7-tty-relabel2.patch @@ -0,0 +1,223 @@ +diff -up ./src/exec.c.tty2 ./src/exec.c +--- ./src/exec.c.tty2 2018-04-29 21:59:24.000000000 +0200 ++++ ./src/exec.c 2021-07-02 13:34:53.803816249 +0200 +@@ -99,19 +99,11 @@ restore_nproc(void) + * Returns true on success and false on failure. + */ + static bool +-exec_setup(struct command_details *details, const char *ptyname, int ptyfd) ++exec_setup(struct command_details *details) + { + bool ret = false; + debug_decl(exec_setup, SUDO_DEBUG_EXEC) + +-#ifdef HAVE_SELINUX +- if (ISSET(details->flags, CD_RBAC_ENABLED)) { +- if (selinux_setup(details->selinux_role, details->selinux_type, +- ptyname ? ptyname : user_details.tty, ptyfd) == -1) +- goto done; +- } +-#endif +- + /* Restore coredumpsize resource limit before running. */ + if (sudo_conf_disable_coredump()) + disable_coredump(true); +@@ -141,7 +133,7 @@ exec_setup(struct command_details *detai + #endif /* HAVE_PRIV_SET */ + + #ifdef HAVE_GETUSERATTR +- if (aix_prep_user(details->pw->pw_name, ptyname ? ptyname : user_details.tty) != 0) { ++ if (aix_prep_user(details->pw->pw_name, details->tty) != 0) { + /* error message displayed by aix_prep_user */ + goto done; + } +@@ -262,7 +254,7 @@ exec_cmnd(struct command_details *detail + debug_decl(exec_cmnd, SUDO_DEBUG_EXEC) + + restore_signals(); +- if (exec_setup(details, NULL, -1) == true) { ++ if (exec_setup(details) == true) { + /* headed for execve() */ + if (details->closefrom >= 0) { + int fd, maxfd; +diff -up ./src/exec_monitor.c.tty2 ./src/exec_monitor.c +--- ./src/exec_monitor.c.tty2 2021-07-02 10:07:33.951025634 +0200 ++++ ./src/exec_monitor.c 2021-07-02 13:34:00.388475413 +0200 +@@ -549,10 +549,26 @@ exec_monitor(struct command_details *det + if (pipe2(errpipe, O_CLOEXEC) != 0) + sudo_fatal(U_("unable to create pipe")); + ++#ifdef HAVE_SELINUX ++ if (ISSET(details->flags, CD_RBAC_ENABLED)) { ++ if (selinux_setup(details->selinux_role, details->selinux_type, ++ details->tty, io_fds[SFD_SLAVE]) == -1) ++ goto bad; ++ } ++#endif ++ + mc.cmnd_pid = sudo_debug_fork(); + switch (mc.cmnd_pid) { + case -1: + sudo_warn(U_("unable to fork")); ++ ++#ifdef HAVE_SELINUX ++ if (ISSET(details->flags, CD_RBAC_ENABLED)) { ++ if (selinux_restore_tty() != 0) ++ sudo_warnx(U_("unable to restore tty label")); ++ } ++#endif ++ + goto bad; + case 0: + /* child */ +diff -up ./src/exec_nopty.c.tty2 ./src/exec_nopty.c +--- ./src/exec_nopty.c.tty2 2018-04-29 21:59:31.000000000 +0200 ++++ ./src/exec_nopty.c 2021-07-02 10:07:33.951025634 +0200 +@@ -371,6 +371,17 @@ exec_nopty(struct command_details *detai + debug_return; + } + ++#ifdef HAVE_SELINUX ++ if (ISSET(details->flags, CD_RBAC_ENABLED)) { ++ if (selinux_setup(details->selinux_role, details->selinux_type, ++ details->tty, -1) == -1) { ++ cstat->type = CMD_ERRNO; ++ cstat->val = errno; ++ debug_return; ++ } ++ } ++#endif ++ + ec.cmnd_pid = sudo_debug_fork(); + switch (ec.cmnd_pid) { + case -1: +diff -up ./src/exec_pty.c.tty2 ./src/exec_pty.c +--- ./src/exec_pty.c.tty2 2021-07-02 10:07:33.940025770 +0200 ++++ ./src/exec_pty.c 2021-07-02 13:40:49.569392687 +0200 +@@ -95,7 +95,7 @@ struct io_buffer { + }; + SLIST_HEAD(io_buffer_list, io_buffer); + +-static char slavename[PATH_MAX]; ++static char ptyname[PATH_MAX]; + int io_fds[6] = { -1, -1, -1, -1, -1, -1}; + static bool foreground, pipeline; + static bool tty_initialized; +@@ -123,7 +123,7 @@ pty_cleanup(void) + if (io_fds[SFD_USERTTY] != -1) + sudo_term_restore(io_fds[SFD_USERTTY], false); + if (utmp_user != NULL) +- utmp_logout(slavename, 0); ++ utmp_logout(ptyname, 0); + + debug_return; + } +@@ -131,7 +131,7 @@ pty_cleanup(void) + /* + * Allocate a pty if /dev/tty is a tty. + * Fills in io_fds[SFD_USERTTY], io_fds[SFD_MASTER], io_fds[SFD_SLAVE] +- * and slavename globals. ++ * and ptyname globals. + */ + static bool + pty_setup(struct command_details *details, const char *tty) +@@ -146,14 +146,17 @@ pty_setup(struct command_details *detail + } + + if (!get_pty(&io_fds[SFD_MASTER], &io_fds[SFD_SLAVE], +- slavename, sizeof(slavename), details->euid)) ++ ptyname, sizeof(ptyname), details->euid)) + sudo_fatal(U_("unable to allocate pty")); + ++ /* Update tty name in command details (used by SELinux and AIX). */ ++ details->tty = ptyname; ++ + /* Add entry to utmp/utmpx? */ + if (ISSET(details->flags, CD_SET_UTMP)) { + utmp_user = + details->utmp_user ? details->utmp_user : user_details.username; +- utmp_login(tty, slavename, io_fds[SFD_SLAVE], utmp_user); ++ utmp_login(tty, ptyname, io_fds[SFD_SLAVE], utmp_user); + } + + sudo_debug_printf(SUDO_DEBUG_INFO, +@@ -172,8 +175,8 @@ pty_make_controlling(void) + if (ioctl(io_fds[SFD_SLAVE], TIOCSCTTY, NULL) != 0) + return -1; + #else +- /* Set controlling tty by reopening slave. */ +- int fd = open(slavename, O_RDWR); ++ /* Set controlling tty by reopening pty slave. */ ++ int fd = open(ptyname, O_RDWR); + if (fd == -1) + return -1; + close(fd); +@@ -787,7 +790,7 @@ pty_close(struct command_status *cstat) + + /* Update utmp */ + if (utmp_user != NULL) +- utmp_logout(slavename, cstat->type == CMD_WSTATUS ? cstat->val : 0); ++ utmp_logout(ptyname, cstat->type == CMD_WSTATUS ? cstat->val : 0); + + /* Close pty master. */ + if (io_fds[SFD_MASTER] != -1) +diff -up ./src/selinux.c.tty2 ./src/selinux.c +--- ./src/selinux.c.tty2 2021-07-02 10:07:33.950025646 +0200 ++++ ./src/selinux.c 2021-07-02 10:07:33.952025622 +0200 +@@ -123,10 +123,11 @@ selinux_restore_tty(void) + goto skip_relabel; + } + +- if (strcmp(chk_tty_context, se_state.new_tty_context) == 0) { ++ if (strcmp(chk_tty_context, se_state.new_tty_context) != 0) { + sudo_warnx(U_("%s changed labels"), se_state.ttyn); +- sudo_debug_printf(SUDO_DEBUG_INFO, "%s: tty label changed, skipping", +- __func__); ++ sudo_debug_printf(SUDO_DEBUG_INFO, ++ "%s: not restoring tty label, expected %s, have %s", ++ __func__, se_state.new_tty_context, chk_tty_context); + goto skip_relabel; + } + +@@ -173,6 +174,7 @@ relabel_tty(const char *ttyn, int ptyfd) + __func__); + debug_return_int(0); + } ++ sudo_debug_printf(SUDO_DEBUG_INFO, "%s: relabeling tty %s", __func__, ttyn); + + /* If sudo is not allocating a pty for the command, open current tty. */ + if (ptyfd == -1) { +@@ -345,8 +347,9 @@ bad: + } + + /* +- * Set the exec and tty contexts in preparation for fork/exec. +- * Must run as root, before the uid change. ++ * Determine the exec and tty contexts in preparation for fork/exec. ++ * Must run as root, before forking the child process. ++ * Sets the tty context but not the exec context (which happens later). + * If ptyfd is not -1, it indicates we are running + * in a pty and do not need to reset std{in,out,err}. + * Returns 0 on success and -1 on failure. +diff -up ./src/sudo.c.tty2 ./src/sudo.c +--- ./src/sudo.c.tty2 2018-04-29 21:59:31.000000000 +0200 ++++ ./src/sudo.c 2021-07-02 10:07:33.952025622 +0200 +@@ -277,6 +277,7 @@ main(int argc, char *argv[], char *envp[ + } + /* Setup command details and run command/edit. */ + command_info_to_details(command_info, &command_details); ++ command_details.tty = user_details.tty; + command_details.argv = argv_out; + command_details.envp = user_env_out; + if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) +diff -up ./src/sudo.h.tty2 ./src/sudo.h +--- ./src/sudo.h.tty2 2018-04-29 21:59:24.000000000 +0200 ++++ ./src/sudo.h 2021-07-02 10:07:33.952025622 +0200 +@@ -162,6 +162,7 @@ struct command_details { + const char *selinux_role; + const char *selinux_type; + const char *utmp_user; ++ const char *tty; + char **argv; + char **envp; + #ifdef HAVE_PRIV_SET diff --git a/SPECS/sudo.spec b/SPECS/sudo.spec index a9d8e28..59f97f9 100644 --- a/SPECS/sudo.spec +++ b/SPECS/sudo.spec @@ -1,7 +1,7 @@ Summary: Allows restricted root access for specified users Name: sudo Version: 1.8.23 -Release: 10%{?dist}.1 +Release: 10%{?dist}.2 License: ISC Group: Applications/System URL: http://www.courtesan.com/sudo/ @@ -77,6 +77,10 @@ Patch18: sudo-1.8.29-expired-password-part2.patch # 1917729 - EMBARGOED CVE-2021-3156 sudo: Heap-buffer overflow in argument parsing [rhel-7.9.z] Patch19: sudo-1.8.31-CVE-2021-3156.patch +# 1972820 - Defaults use_pty plus SELinux ROLE in user specification breaks terminal +Patch20: sudo-1.9.7-tty-relabel1.patch +Patch21: sudo-1.9.7-tty-relabel2.patch + %description Sudo (superuser do) allows a system administrator to give certain users (or groups of users) the ability to run some (or all) commands @@ -126,6 +130,10 @@ plugins that use %{name}. %patch19 -p1 -b .heap-buffer +%patch20 -p1 -b .tty1 +%patch21 -p1 -b .tty2 + + %build autoreconf -I m4 -fv --install @@ -261,6 +269,11 @@ rm -rf %{buildroot} %{_mandir}/man8/sudo_plugin.8* %changelog +* Fri Jul 09 2021 Radovan Sroka - 1.8.23-10.2 +- RHEL 7.9.Z ERRATUM +- defaults use_pty plus SELinux ROLE in user specification breaks terminal + Resolves: rhbz#1972820 + * Wed Jan 20 2021 Radovan Sroka - 1.8.23-10.1 - RHEL 7.9.Z ERRATUM - CVE-2021-3156