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:
14
src/exec.c
14
src/exec.c
@@ -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;
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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:
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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.
|
||||||
|
@@ -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))
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user