569 lines
18 KiB
C
569 lines
18 KiB
C
/* $NetBSD: systrace.c,v 1.3 2002/07/03 22:54:38 atatat Exp $ */
|
|
/* $OpenBSD: systrace.c,v 1.16 2002/06/12 22:14:51 provos Exp $ */
|
|
|
|
/*
|
|
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Niels Provos.
|
|
* 4. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include <sys/cdefs.h>
|
|
__RCSID("$NetBSD: systrace.c,v 1.3 2002/07/03 22:54:38 atatat Exp $");
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/param.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/tree.h>
|
|
#include <sys/socket.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <syslog.h>
|
|
#include <err.h>
|
|
#include <errno.h>
|
|
|
|
#include "intercept.h"
|
|
#include "systrace.h"
|
|
#include "util.h"
|
|
|
|
pid_t trpid;
|
|
int trfd;
|
|
int connected = 0; /* Connected to GUI */
|
|
int inherit = 0; /* Inherit policy to childs */
|
|
int automatic = 0; /* Do not run interactively */
|
|
int allow = 0; /* Allow all and generate */
|
|
int userpolicy = 1; /* Permit user defined policies */
|
|
char *username = NULL; /* Username in automatic mode */
|
|
char cwd[MAXPATHLEN]; /* Current working directory of process */
|
|
|
|
static short trans_cb(int, pid_t, int, const char *, int, const char *, void *,
|
|
int, struct intercept_tlq *, void *);
|
|
static short gen_cb(int, pid_t, int, const char *, int, const char *, void *,
|
|
int, void *);
|
|
static void execres_cb(int, pid_t, int, const char *, const char *, void *);
|
|
static void systrace_initcb(void);
|
|
static void usage(void);
|
|
static int requestor_start(char *);
|
|
|
|
static short
|
|
trans_cb(int fd, pid_t pid, int policynr,
|
|
const char *name, int code, const char *emulation,
|
|
void *args, int argsize, struct intercept_tlq *tls, void *cbarg)
|
|
{
|
|
short action, future;
|
|
struct policy *policy;
|
|
struct intercept_translate *tl;
|
|
struct intercept_pid *ipid;
|
|
struct filterq *pflq = NULL;
|
|
char output[1024], *p, *line;
|
|
int size;
|
|
|
|
action = ICPOLICY_PERMIT;
|
|
|
|
if (policynr == -1)
|
|
goto out;
|
|
|
|
if ((policy = systrace_findpolnr(policynr)) == NULL)
|
|
errx(1, "%s:%d: find %d", __func__, __LINE__,
|
|
policynr);
|
|
|
|
if ((pflq = systrace_policyflq(policy, emulation, name)) == NULL)
|
|
errx(1, "%s:%d: no filter queue", __func__, __LINE__);
|
|
|
|
ipid = intercept_getpid(pid);
|
|
ipid->uflags = 0;
|
|
snprintf(output, sizeof(output),
|
|
"%s, pid: %d(%d), policy: %s, filters: %d, syscall: %s-%s(%d)",
|
|
ipid->name != NULL ? ipid->name : policy->name, pid, policynr,
|
|
policy->name, policy->nfilters, emulation, name, code);
|
|
p = output + strlen(output);
|
|
size = sizeof(output) - strlen(output);
|
|
|
|
TAILQ_FOREACH(tl, tls, next) {
|
|
if (!tl->trans_valid)
|
|
break;
|
|
line = intercept_translate_print(tl);
|
|
if (line != NULL) {
|
|
snprintf(p, size, ", %s: %s", tl->name, line);
|
|
p = output + strlen(output);
|
|
size = sizeof(output) - strlen(output);
|
|
}
|
|
}
|
|
|
|
action = filter_evaluate(tls, pflq, &ipid->uflags);
|
|
if (action != ICPOLICY_ASK)
|
|
goto out;
|
|
if (policy->flags & POLICY_UNSUPERVISED) {
|
|
action = ICPOLICY_NEVER;
|
|
syslog(LOG_WARNING, "user: %s, prog: %s", username, output);
|
|
goto out;
|
|
}
|
|
|
|
action = filter_ask(tls, pflq, policynr, emulation, name,
|
|
output, &future, &ipid->uflags);
|
|
if (future != ICPOLICY_ASK)
|
|
systrace_modifypolicy(fd, policynr, name, future);
|
|
|
|
if (policy->flags & POLICY_DETACHED) {
|
|
if (intercept_detach(fd, pid) == -1)
|
|
err(1, "intercept_detach");
|
|
} else if (action == ICPOLICY_KILL) {
|
|
kill(pid, SIGKILL);
|
|
action = ICPOLICY_NEVER;
|
|
}
|
|
out:
|
|
return (action);
|
|
}
|
|
|
|
static short
|
|
gen_cb(int fd, pid_t pid, int policynr, const char *name, int code,
|
|
const char *emulation, void *args, int argsize, void *cbarg)
|
|
{
|
|
char output[1024];
|
|
struct policy *policy;
|
|
struct intercept_pid *ipid;
|
|
short action = ICPOLICY_PERMIT;
|
|
short future;
|
|
|
|
if (policynr == -1)
|
|
goto out;
|
|
|
|
if ((policy = systrace_findpolnr(policynr)) == NULL)
|
|
errx(1, "%s:%d: find %d", __func__, __LINE__,
|
|
policynr);
|
|
|
|
ipid = intercept_getpid(pid);
|
|
ipid->uflags = 0;
|
|
snprintf(output, sizeof(output),
|
|
"%s, pid: %d(%d), policy: %s, filters: %d, syscall: %s-%s(%d), args: %d",
|
|
ipid->name != NULL ? ipid->name : policy->name, pid, policynr,
|
|
policy->name, policy->nfilters, emulation, name, code, argsize);
|
|
|
|
if (policy->flags & POLICY_UNSUPERVISED) {
|
|
action = ICPOLICY_NEVER;
|
|
syslog(LOG_WARNING, "user: %s, prog: %s", username, output);
|
|
goto out;
|
|
}
|
|
|
|
action = filter_ask(NULL, NULL, policynr, emulation, name,
|
|
output, &future, &ipid->uflags);
|
|
if (future != ICPOLICY_ASK)
|
|
systrace_modifypolicy(fd, policynr, name, future);
|
|
|
|
if (policy->flags & POLICY_DETACHED) {
|
|
if (intercept_detach(fd, pid) == -1)
|
|
err(1, "intercept_detach");
|
|
} else if (action == ICPOLICY_KILL) {
|
|
kill(pid, SIGKILL);
|
|
action = ICPOLICY_NEVER;
|
|
}
|
|
out:
|
|
return (action);
|
|
}
|
|
|
|
static void
|
|
execres_cb(int fd, pid_t pid, int policynr, const char *emulation,
|
|
const char *name, void *arg)
|
|
{
|
|
struct policy *policy;
|
|
|
|
if (policynr != -1) {
|
|
struct intercept_pid *ipid;
|
|
|
|
if (inherit)
|
|
return;
|
|
|
|
ipid = intercept_getpid(pid);
|
|
if (ipid->uflags & PROCESS_INHERIT_POLICY)
|
|
return;
|
|
}
|
|
if ((policy = systrace_newpolicy(emulation, name)) == NULL)
|
|
goto error;
|
|
|
|
/* See if this policies runs without interactive feedback */
|
|
if (automatic)
|
|
policy->flags |= POLICY_UNSUPERVISED;
|
|
|
|
policynr = policy->policynr;
|
|
|
|
/* Try to find existing policy in file system */
|
|
if (policynr == -1 && TAILQ_FIRST(&policy->prefilters) == NULL)
|
|
systrace_addpolicy(name);
|
|
|
|
if (policy->flags & POLICY_DETACHED) {
|
|
if (intercept_detach(fd, pid) == -1)
|
|
err(1, "intercept_detach");
|
|
return;
|
|
}
|
|
|
|
if (policynr == -1) {
|
|
policynr = systrace_newpolicynr(fd, policy);
|
|
if (policynr == -1)
|
|
goto error;
|
|
}
|
|
|
|
if (intercept_assignpolicy(fd, pid, policynr) == -1)
|
|
goto error;
|
|
|
|
if (TAILQ_FIRST(&policy->prefilters) != NULL)
|
|
filter_prepolicy(fd, policy);
|
|
|
|
return;
|
|
|
|
error:
|
|
kill(pid, SIGKILL);
|
|
fprintf(stderr, "Terminating %d: %s\n", pid, name);
|
|
}
|
|
|
|
#define X(x) if ((x) == -1) \
|
|
err(1, "%s:%d: intercept failed", __func__, __LINE__)
|
|
|
|
static void
|
|
systrace_initcb(void)
|
|
{
|
|
X(intercept_init());
|
|
|
|
X(intercept_register_gencb(gen_cb, NULL));
|
|
#ifdef __NetBSD__
|
|
X(intercept_register_sccb("netbsd", "open", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "open", 0));
|
|
X(intercept_register_translation("netbsd", "open", 1, &oflags));
|
|
|
|
X(intercept_register_sccb("netbsd", "connect", trans_cb, NULL));
|
|
X(intercept_register_translation("netbsd", "connect", 1,
|
|
&ic_translate_connect));
|
|
X(intercept_register_sccb("netbsd", "sendto", trans_cb, NULL));
|
|
X(intercept_register_translation("netbsd", "sendto", 4,
|
|
&ic_translate_connect));
|
|
X(intercept_register_sccb("netbsd", "bind", trans_cb, NULL));
|
|
X(intercept_register_translation("netbsd", "bind", 1,
|
|
&ic_translate_connect));
|
|
X(intercept_register_sccb("netbsd", "execve", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "execve", 0));
|
|
|
|
X(intercept_register_sccb("netbsd", "__stat13", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "__stat13", 0));
|
|
X(intercept_register_sccb("netbsd", "__lstat13", trans_cb, NULL));
|
|
X(intercept_register_translink("netbsd", "__lstat13", 0));
|
|
X(intercept_register_sccb("netbsd", "unlink", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "unlink", 0));
|
|
|
|
X(intercept_register_sccb("netbsd", "chown", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "chown", 0));
|
|
X(intercept_register_translation("netbsd", "chown", 1, &uidt));
|
|
X(intercept_register_translation("netbsd", "chown", 2, &gidt));
|
|
|
|
X(intercept_register_sccb("netbsd", "__posix_chown", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "__posix_chown", 0));
|
|
X(intercept_register_translation("netbsd", "__posix_chown", 1, &uidt));
|
|
X(intercept_register_translation("netbsd", "__posix_chown", 2, &gidt));
|
|
|
|
X(intercept_register_sccb("netbsd", "fchown", trans_cb, NULL));
|
|
X(intercept_register_translation("netbsd", "fchown", 0, &fdt));
|
|
X(intercept_register_translation("netbsd", "fchown", 1, &uidt));
|
|
X(intercept_register_translation("netbsd", "fchown", 2, &gidt));
|
|
|
|
X(intercept_register_sccb("netbsd", "__posix_fchown", trans_cb, NULL));
|
|
X(intercept_register_translation("netbsd", "__posix_fchown", 0, &fdt));
|
|
X(intercept_register_translation("netbsd", "__posix_fchown", 1, &uidt));
|
|
X(intercept_register_translation("netbsd", "__posix_fchown", 2, &gidt));
|
|
|
|
X(intercept_register_sccb("netbsd", "chmod", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "chmod", 0));
|
|
X(intercept_register_translation("netbsd", "chmod", 1, &modeflags));
|
|
X(intercept_register_sccb("netbsd", "readlink", trans_cb, NULL));
|
|
X(intercept_register_translink("netbsd", "readlink", 0));
|
|
X(intercept_register_sccb("netbsd", "chdir", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "chdir", 0));
|
|
X(intercept_register_sccb("netbsd", "access", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "access", 0));
|
|
X(intercept_register_sccb("netbsd", "mkdir", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "mkdir", 0));
|
|
X(intercept_register_sccb("netbsd", "rmdir", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "rmdir", 0));
|
|
X(intercept_register_sccb("netbsd", "rename", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "rename", 0));
|
|
X(intercept_register_transfn("netbsd", "rename", 1));
|
|
|
|
X(intercept_register_sccb("netbsd", "__posix_rename", trans_cb, NULL));
|
|
X(intercept_register_transfn("netbsd", "__posix_rename", 0));
|
|
X(intercept_register_transfn("netbsd", "__posix_rename", 1));
|
|
|
|
X(intercept_register_sccb("netbsd", "symlink", trans_cb, NULL));
|
|
X(intercept_register_transstring("netbsd", "symlink", 0));
|
|
X(intercept_register_translink("netbsd", "symlink", 1));
|
|
#else
|
|
X(intercept_register_sccb("native", "open", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "open", 0));
|
|
X(intercept_register_translation("native", "open", 1, &oflags));
|
|
|
|
X(intercept_register_sccb("native", "connect", trans_cb, NULL));
|
|
X(intercept_register_translation("native", "connect", 1,
|
|
&ic_translate_connect));
|
|
X(intercept_register_sccb("native", "sendto", trans_cb, NULL));
|
|
X(intercept_register_translation("native", "sendto", 4,
|
|
&ic_translate_connect));
|
|
X(intercept_register_sccb("native", "bind", trans_cb, NULL));
|
|
X(intercept_register_translation("native", "bind", 1,
|
|
&ic_translate_connect));
|
|
X(intercept_register_sccb("native", "execve", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "execve", 0));
|
|
X(intercept_register_sccb("native", "stat", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "stat", 0));
|
|
X(intercept_register_sccb("native", "lstat", trans_cb, NULL));
|
|
X(intercept_register_translink("native", "lstat", 0));
|
|
X(intercept_register_sccb("native", "unlink", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "unlink", 0));
|
|
X(intercept_register_sccb("native", "chown", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "chown", 0));
|
|
X(intercept_register_translation("native", "chown", 1, &uidt));
|
|
X(intercept_register_translation("native", "chown", 2, &gidt));
|
|
X(intercept_register_sccb("native", "fchown", trans_cb, NULL));
|
|
X(intercept_register_translation("native", "fchown", 0, &fdt));
|
|
X(intercept_register_translation("native", "fchown", 1, &uidt));
|
|
X(intercept_register_translation("native", "fchown", 2, &gidt));
|
|
X(intercept_register_sccb("native", "chmod", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "chmod", 0));
|
|
X(intercept_register_translation("native", "chmod", 1, &modeflags));
|
|
X(intercept_register_sccb("native", "readlink", trans_cb, NULL));
|
|
X(intercept_register_translink("native", "readlink", 0));
|
|
X(intercept_register_sccb("native", "chdir", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "chdir", 0));
|
|
X(intercept_register_sccb("native", "access", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "access", 0));
|
|
X(intercept_register_sccb("native", "mkdir", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "mkdir", 0));
|
|
X(intercept_register_sccb("native", "rmdir", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "rmdir", 0));
|
|
X(intercept_register_sccb("native", "rename", trans_cb, NULL));
|
|
X(intercept_register_transfn("native", "rename", 0));
|
|
X(intercept_register_transfn("native", "rename", 1));
|
|
X(intercept_register_sccb("native", "symlink", trans_cb, NULL));
|
|
X(intercept_register_transstring("native", "symlink", 0));
|
|
X(intercept_register_translink("native", "symlink", 1));
|
|
|
|
X(intercept_register_sccb("linux", "open", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "open", 0));
|
|
X(intercept_register_translation("linux", "open", 1, &linux_oflags));
|
|
X(intercept_register_sccb("linux", "stat", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "stat", 0));
|
|
X(intercept_register_sccb("linux", "lstat", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "lstat", 0));
|
|
X(intercept_register_sccb("linux", "execve", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "execve", 0));
|
|
X(intercept_register_sccb("linux", "access", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "access", 0));
|
|
X(intercept_register_sccb("linux", "symlink", trans_cb, NULL));
|
|
X(intercept_register_transstring("linux", "symlink", 0));
|
|
X(intercept_register_translink("linux", "symlink", 1));
|
|
X(intercept_register_sccb("linux", "readlink", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "readlink", 0));
|
|
X(intercept_register_sccb("linux", "rename", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "rename", 0));
|
|
X(intercept_register_translink("linux", "rename", 1));
|
|
X(intercept_register_sccb("linux", "mkdir", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "mkdir", 0));
|
|
X(intercept_register_sccb("linux", "rmdir", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "rmdir", 0));
|
|
X(intercept_register_sccb("linux", "unlink", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "unlink", 0));
|
|
X(intercept_register_sccb("linux", "chmod", trans_cb, NULL));
|
|
X(intercept_register_translink("linux", "chmod", 0));
|
|
X(intercept_register_translation("linux", "chmod", 1, &modeflags));
|
|
#endif
|
|
|
|
X(intercept_register_execcb(execres_cb, NULL));
|
|
}
|
|
|
|
static void
|
|
usage(void)
|
|
{
|
|
(void)fprintf(stderr,
|
|
"Usage: %s [-ait] [-g gui] [-f policy] [-p pid] command ...\n",
|
|
getprogname());
|
|
exit(1);
|
|
}
|
|
|
|
static int
|
|
requestor_start(char *path)
|
|
{
|
|
char *argv[2];
|
|
int pair[2];
|
|
pid_t pid;
|
|
|
|
argv[0] = path;
|
|
argv[1] = NULL;
|
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
|
|
err(1, "socketpair");
|
|
|
|
pid = fork();
|
|
if (pid == -1)
|
|
err(1, "fork");
|
|
if (pid == 0) {
|
|
close(pair[0]);
|
|
if (dup2(pair[1], fileno(stdin)) == -1)
|
|
err(1, "dup2");
|
|
if (dup2(pair[1], fileno(stdout)) == -1)
|
|
err(1, "dup2");
|
|
setlinebuf(stdout);
|
|
|
|
close(pair[1]);
|
|
|
|
execvp(path, argv);
|
|
|
|
err(1, "execvp: %s", path);
|
|
}
|
|
|
|
close(pair[1]);
|
|
if (dup2(pair[0], fileno(stdin)) == -1)
|
|
err(1, "dup2");
|
|
|
|
if (dup2(pair[0], fileno(stdout)) == -1)
|
|
err(1, "dup2");
|
|
|
|
close(pair[0]);
|
|
|
|
setlinebuf(stdout);
|
|
|
|
connected = 1;
|
|
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int i, c;
|
|
char **args;
|
|
char *filename = NULL;
|
|
char *guipath = _PATH_XSYSTRACE;
|
|
pid_t pidattach = 0;
|
|
int usex11 = 1;
|
|
|
|
while ((c = getopt(argc, argv, "aAitUg:f:p:")) != -1) {
|
|
switch (c) {
|
|
case 'a':
|
|
automatic = 1;
|
|
break;
|
|
case 'A':
|
|
allow = 1;
|
|
break;
|
|
case 'i':
|
|
inherit = 1;
|
|
break;
|
|
case 'g':
|
|
guipath = optarg;
|
|
break;
|
|
case 'f':
|
|
filename = optarg;
|
|
break;
|
|
case 'p':
|
|
if ((pidattach = atoi(optarg)) == 0) {
|
|
warnx("bad pid: %s", optarg);
|
|
usage();
|
|
}
|
|
break;
|
|
case 't':
|
|
usex11 = 0;
|
|
break;
|
|
case 'U':
|
|
userpolicy = 0;
|
|
break;
|
|
default:
|
|
usage();
|
|
break;
|
|
}
|
|
}
|
|
argc -= optind;
|
|
argv += optind;
|
|
|
|
if (argc == 0 || (pidattach && *argv[0] != '/'))
|
|
usage();
|
|
|
|
/* Username for automatic mode, and policy predicates */
|
|
username = uid_to_name(getuid());
|
|
|
|
/* Determine current working directory for filtering */
|
|
if (getcwd(cwd, sizeof(cwd)) == NULL)
|
|
err(1, "getcwd");
|
|
|
|
/* Local initalization */
|
|
systrace_initpolicy(filename);
|
|
systrace_initcb();
|
|
|
|
if ((trfd = intercept_open()) == -1)
|
|
exit(1);
|
|
|
|
if (pidattach == 0) {
|
|
/* Run a command and attach to it */
|
|
if ((args = malloc((argc + 1) * sizeof(char *))) == NULL)
|
|
err(1, "malloc");
|
|
|
|
for (i = 0; i < argc; i++)
|
|
args[i] = argv[i];
|
|
args[i] = NULL;
|
|
|
|
/*
|
|
* We will run in the background if using X11, or
|
|
* doing fixed policy enforcement, or doing automatic
|
|
* policy generation.
|
|
*/
|
|
trpid = intercept_run(usex11 || automatic || allow,
|
|
args[0], args);
|
|
if (trpid == -1)
|
|
err(1, "fork");
|
|
|
|
if (intercept_attach(trfd, trpid) == -1)
|
|
err(1, "attach");
|
|
|
|
if (kill(trpid, SIGUSR1) == -1)
|
|
err(1, "kill");
|
|
} else {
|
|
/* Attach to a running command */
|
|
if (intercept_attachpid(trfd, pidattach, argv[0]) == -1)
|
|
err(1, "attachpid");
|
|
}
|
|
|
|
/* Start the policy gui if necessary */
|
|
if (usex11 && !automatic && !allow)
|
|
requestor_start(guipath);
|
|
|
|
while (intercept_read(trfd) != -1)
|
|
if (!intercept_existpids())
|
|
break;
|
|
|
|
if (userpolicy)
|
|
systrace_dumppolicy();
|
|
|
|
close(trfd);
|
|
|
|
exit(0);
|
|
}
|