Fix restoring the file context of the user's tty with SELinux.

Also fix broken tty labeling when running a command in a pty.
Includes a fix for a typo introduced in the last change set.
This commit is contained in:
Todd C. Miller
2019-09-27 15:32:49 -06:00
parent b7b3fb72d0
commit 112dff276a
7 changed files with 50 additions and 25 deletions

View File

@@ -106,19 +106,11 @@ restore_nproc(void)
* Returns true on success and false on failure. * Returns true on success and false on failure.
*/ */
static bool static bool
exec_setup(struct command_details *details, const char *ptyname, int ptyfd) exec_setup(struct command_details *details)
{ {
bool ret = false; bool ret = false;
debug_decl(exec_setup, SUDO_DEBUG_EXEC) 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
if (details->pw != NULL) { if (details->pw != NULL) {
#ifdef HAVE_PROJECT_H #ifdef HAVE_PROJECT_H
set_project(details->pw); set_project(details->pw);
@@ -144,7 +136,7 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
#endif /* HAVE_PRIV_SET */ #endif /* HAVE_PRIV_SET */
#ifdef HAVE_GETUSERATTR #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 */ /* error message displayed by aix_prep_user */
goto done; goto done;
} }
@@ -265,7 +257,7 @@ exec_cmnd(struct command_details *details, int errfd)
debug_decl(exec_cmnd, SUDO_DEBUG_EXEC) debug_decl(exec_cmnd, SUDO_DEBUG_EXEC)
restore_signals(); restore_signals();
if (exec_setup(details, NULL, -1) == true) { if (exec_setup(details) == true) {
/* headed for execve() */ /* headed for execve() */
if (details->closefrom >= 0) { if (details->closefrom >= 0) {
int fd, maxfd; int fd, maxfd;

View File

@@ -610,10 +610,24 @@ exec_monitor(struct command_details *details, sigset_t *oset,
sudo_fatal(U_("unable to receive message from parent")); sudo_fatal(U_("unable to receive message from parent"));
} }
#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(); mc.cmnd_pid = sudo_debug_fork();
switch (mc.cmnd_pid) { switch (mc.cmnd_pid) {
case -1: case -1:
sudo_warn(U_("unable to fork")); 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; goto bad;
case 0: case 0:
/* child */ /* child */

View File

@@ -378,6 +378,17 @@ exec_nopty(struct command_details *details, struct command_status *cstat)
debug_return; 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(); ec.cmnd_pid = sudo_debug_fork();
switch (ec.cmnd_pid) { switch (ec.cmnd_pid) {
case -1: case -1:

View File

@@ -104,7 +104,7 @@ struct io_buffer {
}; };
SLIST_HEAD(io_buffer_list, 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}; int io_fds[6] = { -1, -1, -1, -1, -1, -1};
static bool foreground, pipeline; static bool foreground, pipeline;
static int ttymode = TERM_COOKED; static int ttymode = TERM_COOKED;
@@ -131,7 +131,7 @@ pty_cleanup(void)
if (io_fds[SFD_USERTTY] != -1) if (io_fds[SFD_USERTTY] != -1)
sudo_term_restore(io_fds[SFD_USERTTY], false); sudo_term_restore(io_fds[SFD_USERTTY], false);
if (utmp_user != NULL) if (utmp_user != NULL)
utmp_logout(slavename, 0); utmp_logout(ptyname, 0);
debug_return; debug_return;
} }
@@ -139,7 +139,7 @@ pty_cleanup(void)
/* /*
* Allocate a pty if /dev/tty is a tty. * Allocate a pty if /dev/tty is a tty.
* Fills in io_fds[SFD_USERTTY], io_fds[SFD_MASTER], io_fds[SFD_SLAVE] * Fills in io_fds[SFD_USERTTY], io_fds[SFD_MASTER], io_fds[SFD_SLAVE]
* and slavename globals. * and ptyname globals.
*/ */
static bool static bool
pty_setup(struct command_details *details, const char *tty) pty_setup(struct command_details *details, const char *tty)
@@ -154,14 +154,17 @@ pty_setup(struct command_details *details, const char *tty)
} }
if (!get_pty(&io_fds[SFD_MASTER], &io_fds[SFD_SLAVE], 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")); 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? */ /* Add entry to utmp/utmpx? */
if (ISSET(details->flags, CD_SET_UTMP)) { if (ISSET(details->flags, CD_SET_UTMP)) {
utmp_user = utmp_user =
details->utmp_user ? details->utmp_user : user_details.username; 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, sudo_debug_printf(SUDO_DEBUG_INFO,
@@ -174,7 +177,7 @@ pty_setup(struct command_details *details, const char *tty)
/* /*
* Make the tty slave the controlling tty. * Make the tty slave the controlling tty.
* This is only used by the monitor but slavename[] is static. * This is only used by the monitor but ptyname[] is static.
*/ */
int int
pty_make_controlling(void) pty_make_controlling(void)
@@ -184,8 +187,8 @@ pty_make_controlling(void)
if (ioctl(io_fds[SFD_SLAVE], TIOCSCTTY, NULL) != 0) if (ioctl(io_fds[SFD_SLAVE], TIOCSCTTY, NULL) != 0)
return -1; return -1;
#else #else
/* Set controlling tty by reopening slave. */ /* Set controlling tty by reopening pty slave. */
int fd = open(slavename, O_RDWR); int fd = open(ptyname, O_RDWR);
if (fd == -1) if (fd == -1)
return -1; return -1;
close(fd); close(fd);
@@ -831,7 +834,7 @@ pty_finish(struct command_status *cstat)
/* Update utmp */ /* Update utmp */
if (utmp_user != NULL) if (utmp_user != NULL)
utmp_logout(slavename, cstat->type == CMD_WSTATUS ? cstat->val : 0); utmp_logout(ptyname, cstat->type == CMD_WSTATUS ? cstat->val : 0);
debug_return; debug_return;
} }

View File

@@ -130,10 +130,11 @@ selinux_restore_tty(void)
goto skip_relabel; 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_warnx(U_("%s changed labels"), se_state.ttyn);
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: tty label changed, skipping", sudo_debug_printf(SUDO_DEBUG_INFO,
__func__); "%s: not restoring tty label, expected %s, have %s",
__func__, se_state.new_tty_context, chk_tty_context);
goto skip_relabel; goto skip_relabel;
} }
@@ -180,6 +181,7 @@ relabel_tty(const char *ttyn, int ptyfd)
__func__); __func__);
debug_return_int(0); 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 sudo is not allocating a pty for the command, open current tty. */
if (ptyfd == -1) { if (ptyfd == -1) {
@@ -352,8 +354,9 @@ bad:
} }
/* /*
* Set the exec and tty contexts in preparation for fork/exec. * Determine the exec and tty contexts in preparation for fork/exec.
* Must run as root, before the uid change. * 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 * If ptyfd is not -1, it indicates we are running
* in a pty and do not need to reset std{in,out,err}. * in a pty and do not need to reset std{in,out,err}.
* Returns 0 on success and -1 on failure. * Returns 0 on success and -1 on failure.

View File

@@ -284,6 +284,7 @@ main(int argc, char *argv[], char *envp[])
} }
/* Setup command details and run command/edit. */ /* Setup command details and run command/edit. */
command_info_to_details(command_info, &command_details); command_info_to_details(command_info, &command_details);
command_details.tty = user_details.tty;
command_details.argv = argv_out; command_details.argv = argv_out;
command_details.envp = user_env_out; command_details.envp = user_env_out;
if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) if (ISSET(sudo_mode, MODE_LOGIN_SHELL))

View File

@@ -171,6 +171,7 @@ struct command_details {
const char *selinux_role; const char *selinux_role;
const char *selinux_type; const char *selinux_type;
const char *utmp_user; const char *utmp_user;
const char *tty;
char **argv; char **argv;
char **envp; char **envp;
#ifdef HAVE_PRIV_SET #ifdef HAVE_PRIV_SET