Run the editor in its own process group.
This fixes suspending the editor on GNU Hurd which doesn't seem to have proper process group signal handling.
This commit is contained in:
5
MANIFEST
5
MANIFEST
@@ -360,6 +360,7 @@ lib/util/strtonum.c
|
|||||||
lib/util/sudo_conf.c
|
lib/util/sudo_conf.c
|
||||||
lib/util/sudo_debug.c
|
lib/util/sudo_debug.c
|
||||||
lib/util/sudo_dso.c
|
lib/util/sudo_dso.c
|
||||||
|
lib/util/suspend_parent.c
|
||||||
lib/util/sys_siglist.h
|
lib/util/sys_siglist.h
|
||||||
lib/util/sys_signame.h
|
lib/util/sys_signame.h
|
||||||
lib/util/term.c
|
lib/util/term.c
|
||||||
@@ -599,6 +600,7 @@ plugins/sudoers/b64_encode.c
|
|||||||
plugins/sudoers/boottime.c
|
plugins/sudoers/boottime.c
|
||||||
plugins/sudoers/bsm_audit.c
|
plugins/sudoers/bsm_audit.c
|
||||||
plugins/sudoers/bsm_audit.h
|
plugins/sudoers/bsm_audit.h
|
||||||
|
plugins/sudoers/canon_path.c
|
||||||
plugins/sudoers/check.c
|
plugins/sudoers/check.c
|
||||||
plugins/sudoers/check.h
|
plugins/sudoers/check.h
|
||||||
plugins/sudoers/check_aliases.c
|
plugins/sudoers/check_aliases.c
|
||||||
@@ -740,7 +742,6 @@ plugins/sudoers/prompt.c
|
|||||||
plugins/sudoers/pwutil.c
|
plugins/sudoers/pwutil.c
|
||||||
plugins/sudoers/pwutil.h
|
plugins/sudoers/pwutil.h
|
||||||
plugins/sudoers/pwutil_impl.c
|
plugins/sudoers/pwutil_impl.c
|
||||||
plugins/sudoers/canon_path.c
|
|
||||||
plugins/sudoers/redblack.c
|
plugins/sudoers/redblack.c
|
||||||
plugins/sudoers/redblack.h
|
plugins/sudoers/redblack.h
|
||||||
plugins/sudoers/regress/check_symbols/check_symbols.c
|
plugins/sudoers/regress/check_symbols/check_symbols.c
|
||||||
@@ -1269,8 +1270,6 @@ src/sudo_intercept_common.c
|
|||||||
src/sudo_noexec.c
|
src/sudo_noexec.c
|
||||||
src/sudo_plugin_int.h
|
src/sudo_plugin_int.h
|
||||||
src/sudo_usage.h.in
|
src/sudo_usage.h.in
|
||||||
src/suspend_nopty.c
|
|
||||||
src/tcsetpgrp_nobg.c
|
|
||||||
src/tgetpass.c
|
src/tgetpass.c
|
||||||
src/ttyname.c
|
src/ttyname.c
|
||||||
src/utmp.c
|
src/utmp.c
|
||||||
|
@@ -344,6 +344,10 @@ sudo_dso_public int sudo_strtomode_v1(const char *cp, const char **errstr);
|
|||||||
/* sudo_printf.c */
|
/* sudo_printf.c */
|
||||||
extern int (*sudo_printf)(int msg_type, const char *fmt, ...);
|
extern int (*sudo_printf)(int msg_type, const char *fmt, ...);
|
||||||
|
|
||||||
|
/* suspend_parent.c */
|
||||||
|
sudo_dso_public void sudo_suspend_parent_v1(int signo, pid_t my_pid, pid_t my_pgrp, pid_t cmnd_pid, void *closure, void (*callback)(void *, int));
|
||||||
|
#define sudo_suspend_parent(_a, _b, _c, _d, _e, _f) sudo_suspend_parent_v1((_a), (_b), (_c), (_d), (_e), (_f))
|
||||||
|
|
||||||
/* term.c */
|
/* term.c */
|
||||||
sudo_dso_public bool sudo_term_cbreak_v1(int fd);
|
sudo_dso_public bool sudo_term_cbreak_v1(int fd);
|
||||||
#define sudo_term_cbreak(_a) sudo_term_cbreak_v1((_a))
|
#define sudo_term_cbreak(_a) sudo_term_cbreak_v1((_a))
|
||||||
|
@@ -150,7 +150,7 @@ LTOBJS = basename.lo @DIGEST@ event.lo fatal.lo key_val.lo gethostname.lo \
|
|||||||
multiarch.lo parseln.lo progname.lo rcstr.lo regex.lo roundup.lo \
|
multiarch.lo parseln.lo progname.lo rcstr.lo regex.lo roundup.lo \
|
||||||
secure_path.lo setgroups.lo strsplit.lo strtobool.lo strtoid.lo \
|
secure_path.lo setgroups.lo strsplit.lo strtobool.lo strtoid.lo \
|
||||||
strtomode.lo strtonum.lo sudo_conf.lo sudo_debug.lo sudo_dso.lo \
|
strtomode.lo strtonum.lo sudo_conf.lo sudo_debug.lo sudo_dso.lo \
|
||||||
term.lo ttyname_dev.lo ttysize.lo uuid.lo \
|
suspend_parent.lo term.lo ttyname_dev.lo ttysize.lo uuid.lo \
|
||||||
@COMMON_OBJS@ @LTLIBOBJS@
|
@COMMON_OBJS@ @LTLIBOBJS@
|
||||||
|
|
||||||
IOBJS = $(LTOBJS:.lo=.i)
|
IOBJS = $(LTOBJS:.lo=.i)
|
||||||
@@ -1629,6 +1629,12 @@ sudo_dso.i: $(srcdir)/sudo_dso.c $(incdir)/compat/stdbool.h \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
sudo_dso.plog: sudo_dso.i
|
sudo_dso.plog: sudo_dso.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_dso.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_dso.c --i-file $< --output-file $@
|
||||||
|
suspend_parent.lo: $(srcdir)/suspend_parent.c $(top_builddir)/config.h
|
||||||
|
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/suspend_parent.c
|
||||||
|
suspend_parent.i: $(srcdir)/suspend_parent.c $(top_builddir)/config.h
|
||||||
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
|
suspend_parent.plog: suspend_parent.i
|
||||||
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/suspend_parent.c --i-file $< --output-file $@
|
||||||
term.lo: $(srcdir)/term.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
term.lo: $(srcdir)/term.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||||
$(incdir)/sudo_debug.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
|
$(incdir)/sudo_debug.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
|
||||||
$(top_builddir)/config.h
|
$(top_builddir)/config.h
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: ISC
|
* SPDX-License-Identifier: ISC
|
||||||
*
|
*
|
||||||
* Copyright (c) 2009-2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
* Copyright (c) 2009-2023 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -30,17 +30,66 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "sudo.h"
|
#include "pathnames.h"
|
||||||
#include "sudo_exec.h"
|
#include "sudo_debug.h"
|
||||||
|
#include "sudo_fatal.h"
|
||||||
|
#include "sudo_gettext.h"
|
||||||
|
#include "sudo_util.h"
|
||||||
|
|
||||||
|
static volatile sig_atomic_t got_sigttou;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SIGTTOU signal handler for term_restore that just sets a flag.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sigttou(int signo)
|
||||||
|
{
|
||||||
|
got_sigttou = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like tcsetpgrp() but restarts on EINTR _except_ for SIGTTOU.
|
||||||
|
* Returns 0 on success or -1 on failure, setting errno.
|
||||||
|
* Sets got_sigttou on failure if interrupted by SIGTTOU.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
tcsetpgrp_nobg(int fd, pid_t pgrp_id)
|
||||||
|
{
|
||||||
|
struct sigaction sa, osa;
|
||||||
|
int rc;
|
||||||
|
debug_decl(tcsetpgrp_nobg, SUDO_DEBUG_UTIL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we receive SIGTTOU from tcsetpgrp() it means we are
|
||||||
|
* not in the foreground process group.
|
||||||
|
* This avoid a TOCTOU race compared to using tcgetpgrp().
|
||||||
|
*/
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = 0; /* do not restart syscalls */
|
||||||
|
sa.sa_handler = sigttou;
|
||||||
|
got_sigttou = 0;
|
||||||
|
(void)sigaction(SIGTTOU, &sa, &osa);
|
||||||
|
do {
|
||||||
|
rc = tcsetpgrp(fd, pgrp_id);
|
||||||
|
} while (rc != 0 && errno == EINTR && !got_sigttou);
|
||||||
|
(void)sigaction(SIGTTOU, &osa, NULL);
|
||||||
|
|
||||||
|
debug_return_int(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Suspend the main process in response to an interactive child process
|
||||||
|
* being suspended.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
suspend_sudo_nopty(struct exec_closure *ec, int signo, pid_t my_pid,
|
sudo_suspend_parent_v1(int signo, pid_t my_pid, pid_t my_pgrp, pid_t cmnd_pid,
|
||||||
pid_t my_pgrp, pid_t cmnd_pid)
|
void *closure, void (*callback)(void *, int))
|
||||||
{
|
{
|
||||||
struct sigaction sa, osa;
|
struct sigaction sa, osa;
|
||||||
pid_t saved_pgrp = -1;
|
pid_t saved_pgrp = -1;
|
||||||
int fd;
|
int fd;
|
||||||
debug_decl(suspend_sudo_nopty, SUDO_DEBUG_EXEC);
|
debug_decl(sudo_suspend_parent, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save the controlling terminal's process group so we can restore
|
* Save the controlling terminal's process group so we can restore
|
||||||
@@ -81,26 +130,28 @@ suspend_sudo_nopty(struct exec_closure *ec, int signo, pid_t my_pid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Log the suspend event. */
|
/* Run callback before we suspend. */
|
||||||
log_suspend(ec, signo);
|
if (callback != NULL)
|
||||||
|
callback(callback, signo);
|
||||||
|
|
||||||
if (signo == SIGTSTP) {
|
if (signo == SIGTSTP) {
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sa.sa_flags = SA_RESTART;
|
sa.sa_flags = SA_RESTART;
|
||||||
sa.sa_handler = SIG_DFL;
|
sa.sa_handler = SIG_DFL;
|
||||||
if (sudo_sigaction(SIGTSTP, &sa, &osa) != 0)
|
if (sigaction(SIGTSTP, &sa, &osa) != 0)
|
||||||
sudo_warn(U_("unable to set handler for signal %d"), SIGTSTP);
|
sudo_warn(U_("unable to set handler for signal %d"), SIGTSTP);
|
||||||
}
|
}
|
||||||
if (kill(my_pid, signo) != 0)
|
if (kill(my_pid, signo) != 0)
|
||||||
sudo_warn("kill(%d, %d)", (int)my_pid, signo);
|
sudo_warn("kill(%d, %d)", (int)my_pid, signo);
|
||||||
if (signo == SIGTSTP) {
|
if (signo == SIGTSTP) {
|
||||||
if (sudo_sigaction(SIGTSTP, &osa, NULL) != 0)
|
if (sigaction(SIGTSTP, &osa, NULL) != 0)
|
||||||
sudo_warn(U_("unable to restore handler for signal %d"), SIGTSTP);
|
sudo_warn(U_("unable to restore handler for signal %d"), SIGTSTP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Log the resume event. */
|
/* Run callback on resume. */
|
||||||
log_suspend(ec, SIGCONT);
|
if (callback != NULL)
|
||||||
|
callback(callback, SIGCONT);
|
||||||
|
|
||||||
if (saved_pgrp != -1) {
|
if (saved_pgrp != -1) {
|
||||||
/*
|
/*
|
@@ -144,6 +144,7 @@ sudo_strtoid_v2
|
|||||||
sudo_strtoidx_v1
|
sudo_strtoidx_v1
|
||||||
sudo_strtomode_v1
|
sudo_strtomode_v1
|
||||||
sudo_strtonum
|
sudo_strtonum
|
||||||
|
sudo_suspend_parent_v1
|
||||||
sudo_term_cbreak_v1
|
sudo_term_cbreak_v1
|
||||||
sudo_term_copy_v1
|
sudo_term_copy_v1
|
||||||
sudo_term_eof
|
sudo_term_eof
|
||||||
|
@@ -93,7 +93,7 @@ static bool install_sudoers(struct sudoersfile *, bool, bool);
|
|||||||
static bool visudo_track_error(const char *file, int line, int column, const char *fmt, va_list args) sudo_printf0like(4, 0);
|
static bool visudo_track_error(const char *file, int line, int column, const char *fmt, va_list args) sudo_printf0like(4, 0);
|
||||||
static int print_unused(struct sudoers_parse_tree *, struct alias *, void *);
|
static int print_unused(struct sudoers_parse_tree *, struct alias *, void *);
|
||||||
static bool reparse_sudoers(char *, int, char **, bool, bool);
|
static bool reparse_sudoers(char *, int, char **, bool, bool);
|
||||||
static int run_command(const char *, char *const *);
|
static int run_command(const char *, char *const *, bool);
|
||||||
static void parse_sudoers_options(void);
|
static void parse_sudoers_options(void);
|
||||||
static void setup_signals(void);
|
static void setup_signals(void);
|
||||||
static void visudo_cleanup(void);
|
static void visudo_cleanup(void);
|
||||||
@@ -557,7 +557,7 @@ edit_sudoers(struct sudoersfile *sp, char *editor, int editor_argc,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run_command(editor, editor_argv) != -1) {
|
if (run_command(editor, editor_argv, true) != -1) {
|
||||||
if (sudo_gettime_real(×[1]) == -1) {
|
if (sudo_gettime_real(×[1]) == -1) {
|
||||||
sudo_warn("%s", U_("unable to read the clock"));
|
sudo_warn("%s", U_("unable to read the clock"));
|
||||||
goto done;
|
goto done;
|
||||||
@@ -820,7 +820,7 @@ install_sudoers(struct sudoersfile *sp, bool set_owner, bool set_mode)
|
|||||||
av[3] = NULL;
|
av[3] = NULL;
|
||||||
|
|
||||||
/* And run it... */
|
/* And run it... */
|
||||||
if (run_command(_PATH_MV, av) != 0) {
|
if (run_command(_PATH_MV, av, false) != 0) {
|
||||||
sudo_warnx(U_("command failed: '%s %s %s', %s unchanged"),
|
sudo_warnx(U_("command failed: '%s %s %s', %s unchanged"),
|
||||||
_PATH_MV, sp->tpath, sp->path, sp->path);
|
_PATH_MV, sp->tpath, sp->path, sp->path);
|
||||||
goto done;
|
goto done;
|
||||||
@@ -895,9 +895,9 @@ setup_signals(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
run_command(const char *path, char *const *argv)
|
run_command(const char *path, char *const *argv, bool foreground)
|
||||||
{
|
{
|
||||||
int status;
|
int fd, status;
|
||||||
pid_t pid, rv;
|
pid_t pid, rv;
|
||||||
debug_decl(run_command, SUDOERS_DEBUG_UTIL);
|
debug_decl(run_command, SUDOERS_DEBUG_UTIL);
|
||||||
|
|
||||||
@@ -906,6 +906,14 @@ run_command(const char *path, char *const *argv)
|
|||||||
sudo_fatal(U_("unable to execute %s"), path);
|
sudo_fatal(U_("unable to execute %s"), path);
|
||||||
break; /* NOTREACHED */
|
break; /* NOTREACHED */
|
||||||
case 0:
|
case 0:
|
||||||
|
/* Run command as the foreground process of a new process group. */
|
||||||
|
if (foreground) {
|
||||||
|
pid = getpid();
|
||||||
|
setpgid(0, pid);
|
||||||
|
fd = open(_PATH_TTY, O_RDWR);
|
||||||
|
if (fd != -1)
|
||||||
|
tcsetpgrp(fd, pid);
|
||||||
|
}
|
||||||
closefrom(STDERR_FILENO + 1);
|
closefrom(STDERR_FILENO + 1);
|
||||||
execv(path, argv);
|
execv(path, argv);
|
||||||
sudo_warn(U_("unable to run %s"), path);
|
sudo_warn(U_("unable to run %s"), path);
|
||||||
@@ -914,11 +922,19 @@ run_command(const char *path, char *const *argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
rv = waitpid(pid, &status, 0);
|
rv = waitpid(pid, &status, WUNTRACED);
|
||||||
if (rv == -1 && errno != EINTR)
|
if (rv == -1) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
break;
|
break;
|
||||||
if (rv != -1 && !WIFSTOPPED(status))
|
}
|
||||||
|
if (!WIFSTOPPED(status))
|
||||||
break;
|
break;
|
||||||
|
if (foreground) {
|
||||||
|
sudo_suspend_parent(WSTOPSIG(status), getpid(), getpgrp(),
|
||||||
|
pid, NULL, NULL);
|
||||||
|
killpg(pid, SIGCONT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rv != -1)
|
if (rv != -1)
|
||||||
|
@@ -145,8 +145,7 @@ OBJS = conversation.o copy_file.o edit_open.o env_hooks.o exec.o \
|
|||||||
exec_common.o exec_intercept.o exec_iolog.o exec_monitor.o \
|
exec_common.o exec_intercept.o exec_iolog.o exec_monitor.o \
|
||||||
exec_nopty.o exec_preload.o exec_ptrace.o exec_pty.o get_pty.o \
|
exec_nopty.o exec_preload.o exec_ptrace.o exec_pty.o get_pty.o \
|
||||||
hooks.o limits.o load_plugins.o net_ifs.o parse_args.o preserve_fds.o \
|
hooks.o limits.o load_plugins.o net_ifs.o parse_args.o preserve_fds.o \
|
||||||
signal.o sudo.o sudo_edit.o suspend_nopty.o tcsetpgrp_nobg.o \
|
signal.o sudo.o sudo_edit.o tgetpass.o ttyname.o utmp.o @SUDO_OBJS@
|
||||||
tgetpass.o ttyname.o utmp.o @SUDO_OBJS@
|
|
||||||
|
|
||||||
IOBJS = $(OBJS:.o=.i) sesh.i sudo_intercept.i sudo_intercept_common.i
|
IOBJS = $(OBJS:.o=.i) sesh.i sudo_intercept.i sudo_intercept_common.i
|
||||||
|
|
||||||
@@ -163,7 +162,7 @@ CHECK_NOEXEC_OBJS = check_noexec.o exec_common.o exec_preload.o
|
|||||||
|
|
||||||
CHECK_TTYNAME_OBJS = check_ttyname.o ttyname.o
|
CHECK_TTYNAME_OBJS = check_ttyname.o ttyname.o
|
||||||
|
|
||||||
TEST_PTRACE_OBJS = suspend_nopty.o tcsetpgrp_nobg.o test_ptrace.o
|
TEST_PTRACE_OBJS = test_ptrace.o
|
||||||
|
|
||||||
LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
|
LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/
|
||||||
|
|
||||||
@@ -1005,42 +1004,6 @@ sudo_intercept_common.i: $(srcdir)/sudo_intercept_common.c \
|
|||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||||
sudo_intercept_common.plog: sudo_intercept_common.i
|
sudo_intercept_common.plog: sudo_intercept_common.i
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_intercept_common.c --i-file $< --output-file $@
|
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudo_intercept_common.c --i-file $< --output-file $@
|
||||||
suspend_nopty.o: $(srcdir)/suspend_nopty.c $(incdir)/compat/stdbool.h \
|
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
|
||||||
$(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
|
|
||||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
|
||||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
|
||||||
$(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
|
|
||||||
$(top_builddir)/config.h $(top_builddir)/pathnames.h
|
|
||||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/suspend_nopty.c
|
|
||||||
suspend_nopty.i: $(srcdir)/suspend_nopty.c $(incdir)/compat/stdbool.h \
|
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
|
||||||
$(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
|
|
||||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
|
||||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
|
||||||
$(incdir)/sudo_util.h $(srcdir)/sudo.h $(srcdir)/sudo_exec.h \
|
|
||||||
$(top_builddir)/config.h $(top_builddir)/pathnames.h
|
|
||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
|
||||||
suspend_nopty.plog: suspend_nopty.i
|
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/suspend_nopty.c --i-file $< --output-file $@
|
|
||||||
tcsetpgrp_nobg.o: $(srcdir)/tcsetpgrp_nobg.c $(incdir)/compat/stdbool.h \
|
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
|
||||||
$(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
|
|
||||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
|
||||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
|
||||||
$(incdir)/sudo_util.h $(srcdir)/sudo.h \
|
|
||||||
$(top_builddir)/config.h $(top_builddir)/pathnames.h
|
|
||||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(HARDENING_CFLAGS) $(srcdir)/tcsetpgrp_nobg.c
|
|
||||||
tcsetpgrp_nobg.i: $(srcdir)/tcsetpgrp_nobg.c $(incdir)/compat/stdbool.h \
|
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
|
||||||
$(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
|
|
||||||
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
|
|
||||||
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
|
|
||||||
$(incdir)/sudo_util.h $(srcdir)/sudo.h \
|
|
||||||
$(top_builddir)/config.h $(top_builddir)/pathnames.h
|
|
||||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
|
||||||
tcsetpgrp_nobg.plog: tcsetpgrp_nobg.i
|
|
||||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/tcsetpgrp_nobg.c --i-file $< --output-file $@
|
|
||||||
test_ptrace.o: $(srcdir)/regress/intercept/test_ptrace.c \
|
test_ptrace.o: $(srcdir)/regress/intercept/test_ptrace.c \
|
||||||
$(incdir)/compat/endian.h $(incdir)/compat/stdbool.h \
|
$(incdir)/compat/endian.h $(incdir)/compat/stdbool.h \
|
||||||
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
|
||||||
|
@@ -533,8 +533,9 @@ log_stderr(const char *buf, unsigned int n, struct io_buffer *iob)
|
|||||||
|
|
||||||
/* Call I/O plugin suspend log method. */
|
/* Call I/O plugin suspend log method. */
|
||||||
void
|
void
|
||||||
log_suspend(struct exec_closure *ec, int signo)
|
log_suspend(void *v, int signo)
|
||||||
{
|
{
|
||||||
|
struct exec_closure *ec = v;
|
||||||
struct plugin_container *plugin;
|
struct plugin_container *plugin;
|
||||||
const char *errstr = NULL;
|
const char *errstr = NULL;
|
||||||
sigset_t omask;
|
sigset_t omask;
|
||||||
|
@@ -758,8 +758,8 @@ handle_sigchld_nopty(struct exec_closure *ec)
|
|||||||
|
|
||||||
/* If the main command is suspended, suspend sudo too. */
|
/* If the main command is suspended, suspend sudo too. */
|
||||||
if (pid == ec->cmnd_pid) {
|
if (pid == ec->cmnd_pid) {
|
||||||
suspend_sudo_nopty(ec, signo, ec->sudo_pid, ec->ppgrp,
|
sudo_suspend_parent(signo, ec->sudo_pid, ec->ppgrp,
|
||||||
ec->cmnd_pid);
|
ec->cmnd_pid, ec, log_suspend);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (WIFSIGNALED(status)) {
|
if (WIFSIGNALED(status)) {
|
||||||
|
@@ -104,13 +104,6 @@ sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa)
|
|||||||
return sigaction(signo, sa, osa);
|
return sigaction(signo, sa, osa);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* STUB */
|
|
||||||
void
|
|
||||||
log_suspend(struct exec_closure *ec, int signo)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -228,8 +221,8 @@ main(int argc, char *argv[])
|
|||||||
} else if (WIFSTOPPED(status)) {
|
} else if (WIFSTOPPED(status)) {
|
||||||
if (exec_ptrace_stopped(pid, status, &closure)) {
|
if (exec_ptrace_stopped(pid, status, &closure)) {
|
||||||
if (pid == child) {
|
if (pid == child) {
|
||||||
suspend_sudo_nopty(NULL, WSTOPSIG(status), my_pid,
|
sudo_suspend_parent(WSTOPSIG(status), my_pid,
|
||||||
my_pgrp, child);
|
my_pgrp, child, NULL, NULL);
|
||||||
if (kill(child, SIGCONT) != 0)
|
if (kill(child, SIGCONT) != 0)
|
||||||
sudo_warn("kill(%d, SIGCONT)", (int)child);
|
sudo_warn("kill(%d, SIGCONT)", (int)child);
|
||||||
}
|
}
|
||||||
|
@@ -336,9 +336,6 @@ int add_preserved_fd(struct preserved_fd_list *pfds, int fd);
|
|||||||
void closefrom_except(int startfd, struct preserved_fd_list *pfds);
|
void closefrom_except(int startfd, struct preserved_fd_list *pfds);
|
||||||
void parse_preserved_fds(struct preserved_fd_list *pfds, const char *fdstr);
|
void parse_preserved_fds(struct preserved_fd_list *pfds, const char *fdstr);
|
||||||
|
|
||||||
/* setpgrp_nobg.c */
|
|
||||||
int tcsetpgrp_nobg(int fd, pid_t pgrp_id);
|
|
||||||
|
|
||||||
/* limits.c */
|
/* limits.c */
|
||||||
void disable_coredump(void);
|
void disable_coredump(void);
|
||||||
void restore_limits(void);
|
void restore_limits(void);
|
||||||
|
@@ -194,7 +194,7 @@ bool log_stdin(const char *buf, unsigned int n, struct io_buffer *iob);
|
|||||||
bool log_ttyout(const char *buf, unsigned int n, struct io_buffer *iob);
|
bool log_ttyout(const char *buf, unsigned int n, struct io_buffer *iob);
|
||||||
bool log_stdout(const char *buf, unsigned int n, struct io_buffer *iob);
|
bool log_stdout(const char *buf, unsigned int n, struct io_buffer *iob);
|
||||||
bool log_stderr(const char *buf, unsigned int n, struct io_buffer *iob);
|
bool log_stderr(const char *buf, unsigned int n, struct io_buffer *iob);
|
||||||
void log_suspend(struct exec_closure *ec, int signo);
|
void log_suspend(void *v, int signo);
|
||||||
void log_winchange(struct exec_closure *ec, unsigned int rows, unsigned int cols);
|
void log_winchange(struct exec_closure *ec, unsigned int rows, unsigned int cols);
|
||||||
void io_buf_new(int rfd, int wfd, bool (*action)(const char *, unsigned int, struct io_buffer *), void (*read_cb)(int fd, int what, void *v), void (*write_cb)(int fd, int what, void *v), struct exec_closure *ec, struct io_buffer_list *head);
|
void io_buf_new(int rfd, int wfd, bool (*action)(const char *, unsigned int, struct io_buffer *), void (*read_cb)(int fd, int what, void *v), void (*write_cb)(int fd, int what, void *v), struct exec_closure *ec, struct io_buffer_list *head);
|
||||||
int safe_close(int fd);
|
int safe_close(int fd);
|
||||||
@@ -232,7 +232,4 @@ bool exec_ptrace_stopped(pid_t pid, int status, void *intercept);
|
|||||||
bool set_exec_filter(void);
|
bool set_exec_filter(void);
|
||||||
int exec_ptrace_seize(pid_t child);
|
int exec_ptrace_seize(pid_t child);
|
||||||
|
|
||||||
/* suspend_nopty.c */
|
|
||||||
void suspend_sudo_nopty(struct exec_closure *ec, int signo, pid_t my_pid, pid_t my_pgrp, pid_t cmnd_pid);
|
|
||||||
|
|
||||||
#endif /* SUDO_EXEC_H */
|
#endif /* SUDO_EXEC_H */
|
||||||
|
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-License-Identifier: ISC
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017 Todd C. Miller <Todd.Miller@sudo.ws>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
||||||
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "sudo.h"
|
|
||||||
|
|
||||||
static volatile sig_atomic_t got_sigttou;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SIGTTOU signal handler for tcsetpgrp_nobg() that just sets a flag.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
sigttou(int signo)
|
|
||||||
{
|
|
||||||
got_sigttou = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Like tcsetpgrp() but restarts on EINTR _except_ for SIGTTOU.
|
|
||||||
* Returns 0 on success or -1 on failure, setting errno.
|
|
||||||
* Sets got_sigttou on failure if interrupted by SIGTTOU.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
tcsetpgrp_nobg(int fd, pid_t pgrp_id)
|
|
||||||
{
|
|
||||||
struct sigaction sa, osa;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we receive SIGTTOU from tcsetpgrp() it means we are
|
|
||||||
* not in the foreground process group.
|
|
||||||
* This avoid a TOCTOU race compared to using tcgetpgrp().
|
|
||||||
*/
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
|
||||||
sigemptyset(&sa.sa_mask);
|
|
||||||
sa.sa_flags = 0; /* do not restart syscalls */
|
|
||||||
sa.sa_handler = sigttou;
|
|
||||||
got_sigttou = 0;
|
|
||||||
(void)sigaction(SIGTTOU, &sa, &osa);
|
|
||||||
do {
|
|
||||||
rc = tcsetpgrp(fd, pgrp_id);
|
|
||||||
} while (rc != 0 && errno == EINTR && !got_sigttou);
|
|
||||||
(void)sigaction(SIGTTOU, &osa, NULL);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
Reference in New Issue
Block a user