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.
*/
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
if (details->pw != NULL) {
#ifdef HAVE_PROJECT_H
set_project(details->pw);
@@ -144,7 +136,7 @@ exec_setup(struct command_details *details, const char *ptyname, int ptyfd)
#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;
}
@@ -265,7 +257,7 @@ exec_cmnd(struct command_details *details, int errfd)
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;

View File

@@ -610,10 +610,24 @@ exec_monitor(struct command_details *details, sigset_t *oset,
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();
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 */

View File

@@ -378,6 +378,17 @@ exec_nopty(struct command_details *details, struct command_status *cstat)
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:

View File

@@ -104,7 +104,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 int ttymode = TERM_COOKED;
@@ -131,7 +131,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;
}
@@ -139,7 +139,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)
@@ -154,14 +154,17 @@ pty_setup(struct command_details *details, const char *tty)
}
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,
@@ -174,7 +177,7 @@ pty_setup(struct command_details *details, const char *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
pty_make_controlling(void)
@@ -184,8 +187,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);
@@ -831,7 +834,7 @@ pty_finish(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);
debug_return;
}

View File

@@ -130,10 +130,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;
}
@@ -180,6 +181,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) {
@@ -352,8 +354,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.

View File

@@ -284,6 +284,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))

View File

@@ -171,6 +171,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