diff options
author | Niels Provos <provos@cvs.openbsd.org> | 2002-07-09 20:46:19 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 2002-07-09 20:46:19 +0000 |
commit | 7d6384b333a9b97f4d8ec808751d55c8ebc67672 (patch) | |
tree | 6c54ae2cb928042544779296ae2638c6a09f0a82 /bin/systrace | |
parent | 4629f922a7143c45adec6584532b3a1444b97da8 (diff) |
allow systrace to run in the background if possible so that the executed
process gets the terminal correctly and exit status reporting works;
based on a diff from atatat@atatdot.net from netbsd.
Diffstat (limited to 'bin/systrace')
-rw-r--r-- | bin/systrace/intercept.c | 83 | ||||
-rw-r--r-- | bin/systrace/intercept.h | 4 | ||||
-rw-r--r-- | bin/systrace/systrace.c | 24 |
3 files changed, 92 insertions, 19 deletions
diff --git a/bin/systrace/intercept.c b/bin/systrace/intercept.c index c39fc673e01..3580167fe04 100644 --- a/bin/systrace/intercept.c +++ b/bin/systrace/intercept.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intercept.c,v 1.11 2002/07/09 15:22:27 provos Exp $ */ +/* $OpenBSD: intercept.c,v 1.12 2002/07/09 20:46:18 provos Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -213,20 +213,65 @@ intercept_register_execcb(void (*cb)(int, pid_t, int, char *, char *, void *), v return (0); } +static void +sigusr1_handler(int signum) +{ + /* all we need to do is pretend to handle it */ +} + pid_t -intercept_run(int fd, char *path, char *const argv[]) +intercept_run(int bg, int fd, char *path, char *const argv[]) { - pid_t pid; - - pid = fork(); - if (pid == -1) + sigset_t none, set, oset; + sig_t ohandler; + pid_t pid, cpid; + int status; + + /* Block signals so that timeing on signal delivery does not matter */ + sigemptyset(&none); + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) + err(1, "sigprocmask"); + ohandler = signal(SIGUSR1, sigusr1_handler); + if (ohandler == SIG_ERR) + err(1, "signal"); + + pid = getpid(); + cpid = fork(); + if (cpid == -1) return (-1); - if (pid == 0) { + + /* + * If the systrace process should be in the background and we're + * the parent, or vice versa. + */ + if ((!bg && cpid == 0) || (bg && cpid != 0)) { /* Needs to be closed */ close(fd); - /* Stop myself */ - raise(SIGSTOP); + if (bg) { + /* Wait for child to "detach" */ + cpid = wait(&status); + if (cpid == -1) + err(1, "wait"); + if (status != 0) + errx(1, "wait: child gave up"); + } + + /* Sleep */ + sigsuspend(&none); + + /* + * Woken up, restore signal handling state. + * + * Note that there is either no child or we have no idea + * what pid it might have at this point. If we fail. + */ + if (signal(SIGUSR1, ohandler) == SIG_ERR) + err(1, "signal"); + if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) + err(1, "sigprocmask"); execvp(path, argv); @@ -234,7 +279,25 @@ intercept_run(int fd, char *path, char *const argv[]) err(1, "execvp"); } - sleep(1); /* XXX */ + /* Choose the pid of the systraced process */ + pid = bg ? pid : cpid; + + /* Setup done, restore signal handling state */ + if (signal(SIGUSR1, ohandler) == SIG_ERR) { + kill(pid, SIGKILL); + err(1, "signal"); + } + if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) { + kill(pid, SIGKILL); + err(1, "sigprocmask"); + } + + if (bg) { + if (daemon(0, 0) == -1) { + kill(pid, SIGKILL); + err(1, "daemon"); + } + } return (pid); } diff --git a/bin/systrace/intercept.h b/bin/systrace/intercept.h index d1bd4cc3ab8..029ac2b026f 100644 --- a/bin/systrace/intercept.h +++ b/bin/systrace/intercept.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intercept.h,v 1.4 2002/07/09 15:22:27 provos Exp $ */ +/* $OpenBSD: intercept.h,v 1.5 2002/07/09 20:46:18 provos Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -110,7 +110,7 @@ struct intercept_replace { TAILQ_HEAD(intercept_tlq, intercept_translate); int intercept_init(void); -pid_t intercept_run(int, char *, char * const *); +pid_t intercept_run(int, int, char *, char * const *); int intercept_open(void); int intercept_attach(int, pid_t); int intercept_attachpid(int, pid_t, char *); diff --git a/bin/systrace/systrace.c b/bin/systrace/systrace.c index 1a0d4de8b05..f3224220093 100644 --- a/bin/systrace/systrace.c +++ b/bin/systrace/systrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: systrace.c,v 1.21 2002/07/09 15:22:27 provos Exp $ */ +/* $OpenBSD: systrace.c,v 1.22 2002/07/09 20:46:18 provos Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -512,6 +512,7 @@ main(int argc, char **argv) char *guipath = _PATH_XSYSTRACE; pid_t pidattach = 0; int usex11 = 1; + int background; while ((c = getopt(argc, argv, "aAituUg:f:p:")) != -1) { switch (c) { @@ -563,9 +564,6 @@ main(int argc, char **argv) if (getcwd(cwd, sizeof(cwd)) == NULL) err(1, "getcwd"); - if (signal(SIGCHLD, child_handler) == SIG_ERR) - err(1, "signal"); - /* Local initalization */ systrace_initalias(); systrace_initpolicy(filename); @@ -574,6 +572,9 @@ main(int argc, char **argv) if ((fd = intercept_open()) == -1) exit(1); + /* See if we can run the systrace process in the background */ + background = usex11 || automatic || allow; + if (pidattach == 0) { /* Run a command and attach to it */ if ((args = malloc((argc + 1) * sizeof(char *))) == NULL) @@ -583,22 +584,31 @@ main(int argc, char **argv) args[i] = argv[i]; args[i] = NULL; - pid = intercept_run(fd, args[0], args); + pid = intercept_run(background, fd, args[0], args); if (pid == -1) err(1, "fork"); if (intercept_attach(fd, pid) == -1) err(1, "attach"); - if (kill(pid, SIGCONT) == -1) + if (kill(pid, SIGUSR1) == -1) err(1, "kill"); } else { - /* Attach to a running command */ + pid_t cpid; + /* Attach to a running command */ if (intercept_attachpid(fd, pidattach, argv[0]) == -1) err(1, "attachpid"); + + if (background) { + if (daemon(0, 0) == -1) + err(1, "daemon"); + } } + if (signal(SIGCHLD, child_handler) == SIG_ERR) + err(1, "signal"); + /* Start the policy gui if necessary */ if (usex11 && !automatic && !allow) requestor_start(guipath); |