Sync with OpenBSD systrace 1.6d.

XXX: Some of the compat-linux systrace is disabled.
From elad.
This commit is contained in:
christos 2006-12-10 01:22:02 +00:00
parent ba06ad7411
commit ddbf1b0dd9
12 changed files with 508 additions and 142 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: filter.c,v 1.31 2005/08/24 19:09:03 elad Exp $ */ /* $NetBSD: filter.c,v 1.32 2006/12/10 01:22:02 christos Exp $ */
/* $OpenBSD: filter.c,v 1.16 2002/08/08 21:18:20 provos Exp $ */ /* $OpenBSD: filter.c,v 1.16 2002/08/08 21:18:20 provos Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -30,7 +30,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: filter.c,v 1.31 2005/08/24 19:09:03 elad Exp $"); __RCSID("$NetBSD: filter.c,v 1.32 2006/12/10 01:22:02 christos Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/types.h> #include <sys/types.h>
@ -400,6 +400,10 @@ filter_modifypolicy(int fd, int policynr, const char *emulation,
{ {
struct systrace_revalias *reverse = NULL; struct systrace_revalias *reverse = NULL;
/*
* Check if we are dealing with a system call that really
* is an alias for something else.
*/
if (!noalias) if (!noalias)
reverse = systrace_find_reverse(emulation, name); reverse = systrace_find_reverse(emulation, name);
if (reverse == NULL) { if (reverse == NULL) {
@ -444,6 +448,11 @@ filter_quickpredicate(struct filter *filter)
return (1); return (1);
} }
/*
* Processes the filters for a policy that have not been applied yet.
* Pre-filters get installed when reading a policy. This function
* installs a fast-path in the kernel.
*/
int int
filter_prepolicy(int fd, struct policy *policy) filter_prepolicy(int fd, struct policy *policy)
{ {

View File

@ -1,4 +1,4 @@
/* $NetBSD: intercept.c,v 1.26 2005/12/31 12:33:41 elad Exp $ */ /* $NetBSD: intercept.c,v 1.27 2006/12/10 01:22:02 christos Exp $ */
/* $OpenBSD: intercept.c,v 1.29 2002/08/28 03:30:27 itojun Exp $ */ /* $OpenBSD: intercept.c,v 1.29 2002/08/28 03:30:27 itojun Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -30,7 +30,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: intercept.c,v 1.26 2005/12/31 12:33:41 elad Exp $"); __RCSID("$NetBSD: intercept.c,v 1.27 2006/12/10 01:22:02 christos Exp $");
#include <sys/types.h> #include <sys/types.h>
#include <sys/param.h> #include <sys/param.h>
@ -555,6 +555,9 @@ intercept_get_string(int fd, pid_t pid, void *addr)
static char name[8192]; static char name[8192];
int off = 0, done = 0, stride; int off = 0, done = 0, stride;
if (addr == NULL)
return (NULL);
stride = 32; stride = 32;
do { do {
if (intercept.io(fd, pid, INTERCEPT_READ, (char *)addr + off, if (intercept.io(fd, pid, INTERCEPT_READ, (char *)addr + off,
@ -642,7 +645,6 @@ normalize_filename(int fd, pid_t pid, char *name, int userp)
havecwd = 1; havecwd = 1;
} }
/* Need concatenated path for simplifypath */
if (havecwd && name[0] != '/') { if (havecwd && name[0] != '/') {
if (strlcat(cwd, "/", sizeof(cwd)) >= sizeof(cwd)) if (strlcat(cwd, "/", sizeof(cwd)) >= sizeof(cwd))
return (NULL); return (NULL);
@ -707,7 +709,7 @@ normalize_filename(int fd, pid_t pid, char *name, int userp)
*/ */
if (userp != ICLINK_NOLAST) { if (userp != ICLINK_NOLAST) {
if (lstat(rcwd, &st) == -1 || if (lstat(rcwd, &st) == -1 ||
!(st.st_mode & S_IFDIR)) !S_ISDIR(st.st_mode))
failed = 1; failed = 1;
} }
} }
@ -891,6 +893,12 @@ intercept_assignpolicy(int fd, pid_t pid, int policynr)
return (intercept.assignpolicy(fd, pid, policynr)); return (intercept.assignpolicy(fd, pid, policynr));
} }
int
intercept_modifypolicy_nr(int fd, int policynr, int code, short policy)
{
return (intercept.policy(fd, policynr, code, policy));
}
int int
intercept_modifypolicy(int fd, int policynr, const char *emulation, intercept_modifypolicy(int fd, int policynr, const char *emulation,
const char *name, short policy) const char *name, short policy)
@ -964,13 +972,28 @@ intercept_ugid(struct intercept_pid *icpid, uid_t uid, gid_t gid)
icpid->gid = gid; icpid->gid = gid;
} }
/*
* Returns the number of a system call
*/
int
intercept_getsyscallnumber(const char *emulation, const char *name)
{
int nr = intercept.getsyscallnumber(emulation, name);
if (nr >= INTERCEPT_MAXSYSCALLNR)
err(1, "%s: system call number too high: %d", __func__, nr);
return (nr);
}
/* /*
* Checks if the given emulation has a certain system call. * Checks if the given emulation has a certain system call.
* This is a very slow function. * This is a very slow function.
*/ */
int int
intercept_isvalidsystemcall(char *emulation, char *name) intercept_isvalidsystemcall(const char *emulation, const char *name)
{ {
int res; int res;

View File

@ -1,4 +1,4 @@
/* $NetBSD: intercept.h,v 1.19 2006/04/16 05:19:02 provos Exp $ */ /* $NetBSD: intercept.h,v 1.20 2006/12/10 01:22:02 christos Exp $ */
/* $OpenBSD: intercept.h,v 1.11 2002/08/04 04:15:50 provos Exp $ */ /* $OpenBSD: intercept.h,v 1.11 2002/08/04 04:15:50 provos Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -111,6 +111,7 @@ struct intercept_pid {
struct elevate *elevate; /* privilege elevation request */ struct elevate *elevate; /* privilege elevation request */
}; };
#define INTERCEPT_MAXSYSCALLNR 512
#define INTERCEPT_MAXSYSCALLARGS 10 #define INTERCEPT_MAXSYSCALLARGS 10
struct intercept_translate { struct intercept_translate {
@ -126,6 +127,7 @@ struct intercept_translate {
size_t trans_size; size_t trans_size;
char *trans_print; char *trans_print;
u_int trans_flags; u_int trans_flags;
void *user;
TAILQ_ENTRY(intercept_translate) next; TAILQ_ENTRY(intercept_translate) next;
}; };
@ -149,6 +151,7 @@ int intercept_read(int);
int intercept_newpolicy(int); int intercept_newpolicy(int);
int intercept_assignpolicy(int, pid_t, int); int intercept_assignpolicy(int, pid_t, int);
int intercept_modifypolicy(int, int, const char *, const char *, short); int intercept_modifypolicy(int, int, const char *, const char *, short);
int intercept_modifypolicy_nr(int, int, int, short);
void intercept_child_info(pid_t, pid_t); void intercept_child_info(pid_t, pid_t);
void intercept_policy_free(int); void intercept_policy_free(int);
@ -197,12 +200,13 @@ void intercept_syscall(int, pid_t, u_int16_t, int, const char *, int,
const char *, void *, int); const char *, void *, int);
void intercept_syscall_result(int, pid_t, u_int16_t, int, const char *, int, void intercept_syscall_result(int, pid_t, u_int16_t, int, const char *, int,
const char *, void *, int, int, void *); const char *, void *, int, int, void *);
void intercept_ugid(struct intercept_pid *, uid_t, gid_t);
void intercept_setpid(struct intercept_pid *, uid_t, gid_t);
void intercept_newimage(int, pid_t, int, const char *, char *, void intercept_newimage(int, pid_t, int, const char *, char *,
struct intercept_pid *); struct intercept_pid *);
void intercept_ugid(struct intercept_pid *, uid_t, gid_t);
void intercept_setpid(struct intercept_pid *, uid_t, gid_t);
int intercept_isvalidsystemcall(char *, char *); int intercept_getsyscallnumber(const char *, const char *);
int intercept_isvalidsystemcall(const char *, const char *);
char *intercept_realpath(const char *, char *); char *intercept_realpath(const char *, char *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: netbsd-syscalls.c,v 1.19 2005/06/27 17:11:20 elad Exp $ */ /* $NetBSD: netbsd-syscalls.c,v 1.20 2006/12/10 01:22:02 christos Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -31,7 +31,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: netbsd-syscalls.c,v 1.19 2005/06/27 17:11:20 elad Exp $"); __RCSID("$NetBSD: netbsd-syscalls.c,v 1.20 2006/12/10 01:22:02 christos Exp $");
#include <sys/types.h> #include <sys/types.h>
#include <sys/param.h> #include <sys/param.h>
@ -466,6 +466,8 @@ nbsd_replace(int fd, pid_t pid, u_int16_t seqnr,
size_t len, off; size_t len, off;
int i, ret; int i, ret;
memset(&replace, 0, sizeof(replace));
for (i = 0, len = 0; i < repl->num; i++) { for (i = 0, len = 0; i < repl->num; i++) {
len += repl->len[i]; len += repl->len[i];
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: openbsd-syscalls.c,v 1.9 2003/08/25 09:12:45 cb Exp $ */ /* $NetBSD: openbsd-syscalls.c,v 1.10 2006/12/10 01:22:02 christos Exp $ */
/* $OpenBSD: openbsd-syscalls.c,v 1.12 2002/08/28 03:30:27 itojun Exp $ */ /* $OpenBSD: openbsd-syscalls.c,v 1.12 2002/08/28 03:30:27 itojun Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -436,6 +436,8 @@ obsd_replace(int fd, pid_t pid, u_int16_t seqnr,
size_t len, off; size_t len, off;
int i, ret; int i, ret;
memset(&replace, 0, sizeof(replace));
for (i = 0, len = 0; i < repl->num; i++) { for (i = 0, len = 0; i < repl->num; i++) {
len += repl->len[i]; len += repl->len[i];
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: policy.c,v 1.21 2006/03/18 00:35:02 peter Exp $ */ /* $NetBSD: policy.c,v 1.22 2006/12/10 01:22:02 christos Exp $ */
/* $OpenBSD: policy.c,v 1.15 2002/08/07 00:34:17 vincent Exp $ */ /* $OpenBSD: policy.c,v 1.15 2002/08/07 00:34:17 vincent Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -30,7 +30,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: policy.c,v 1.21 2006/03/18 00:35:02 peter Exp $"); __RCSID("$NetBSD: policy.c,v 1.22 2006/12/10 01:22:02 christos Exp $");
#include <sys/types.h> #include <sys/types.h>
#include <sys/param.h> #include <sys/param.h>
@ -46,6 +46,7 @@ __RCSID("$NetBSD: policy.c,v 1.21 2006/03/18 00:35:02 peter Exp $");
#include <fcntl.h> #include <fcntl.h>
#include <ctype.h> #include <ctype.h>
#include <err.h> #include <err.h>
#include <libgen.h>
#include "intercept.h" #include "intercept.h"
#include "systrace.h" #include "systrace.h"
@ -132,7 +133,7 @@ systrace_setupdir(char *path)
if (stat(policydir, &sb) != -1) { if (stat(policydir, &sb) != -1) {
if (!(sb.st_mode & S_IFDIR)) if (!S_ISDIR(sb.st_mode))
errx(1, "Not a directory: \"%s\"", policydir); errx(1, "Not a directory: \"%s\"", policydir);
} else if (mkdir(policydir, 0700) == -1) } else if (mkdir(policydir, 0700) == -1)
err(1, "mkdir(%s)", policydir); err(1, "mkdir(%s)", policydir);
@ -150,11 +151,39 @@ systrace_initpolicy(char *file, char *path)
} }
if (file != NULL) if (file != NULL)
return (systrace_readpolicy(file)); return (systrace_readpolicy(file) != NULL ? 0 : -1);
return (0); return (0);
} }
struct policy *
systrace_findpolicy_wildcard(const char *name)
{
struct policy tmp, *res;
static char path[MAXPATHLEN], lookup[MAXPATHLEN];
if (strlcpy(path, name, sizeof(path)) >= sizeof(path))
errx(1, "%s: path name overflow", __func__);
strlcpy(lookup, "*/", sizeof(lookup));
strlcat(lookup, basename(path), sizeof(lookup));
tmp.name = lookup;
res = SPLAY_FIND(policytree, &policyroot, &tmp);
if (res == NULL)
return (NULL);
/* we found the wildcarded policy; now remove it and bind it */
SPLAY_REMOVE(policytree, &policyroot, res);
free(__UNCONST(res->name));
if ((res->name = strdup(name)) == NULL)
err(1, "%s: strdup", __func__);
SPLAY_INSERT(policytree, &policyroot, res);
return (res);
}
struct policy * struct policy *
systrace_findpolicy(const char *name) systrace_findpolicy(const char *name)
{ {
@ -195,10 +224,14 @@ struct policy *
systrace_newpolicy(const char *emulation, const char *name) systrace_newpolicy(const char *emulation, const char *name)
{ {
struct policy *tmp; struct policy *tmp;
int i;
if ((tmp = systrace_findpolicy(name)) != NULL) if ((tmp = systrace_findpolicy(name)) != NULL)
return (tmp); return (tmp);
if ((tmp = systrace_findpolicy_wildcard(name)) != NULL)
return (tmp);
tmp = calloc(1, sizeof(struct policy)); tmp = calloc(1, sizeof(struct policy));
if (tmp == NULL) if (tmp == NULL)
return (NULL); return (NULL);
@ -215,20 +248,23 @@ systrace_newpolicy(const char *emulation, const char *name)
TAILQ_INIT(&tmp->filters); TAILQ_INIT(&tmp->filters);
TAILQ_INIT(&tmp->prefilters); TAILQ_INIT(&tmp->prefilters);
/* Set the default policy to ask */
for (i = 0; i < INTERCEPT_MAXSYSCALLNR; i++)
tmp->kerneltable[i] = ICPOLICY_ASK;
return (tmp); return (tmp);
} }
void void
systrace_freepolicy(struct policy *policy) systrace_cleanpolicy(struct policy *policy)
{ {
struct filter *filter; struct filter *filter;
struct policy_syscall *pflq; struct policy_syscall *pflq;
int i;
if (policy->flags & POLICY_CHANGED) { /* Set the default policy to ask */
if (systrace_writepolicy(policy) == -1) for (i = 0; i < INTERCEPT_MAXSYSCALLNR; i++)
fprintf(stderr, "Failed to write policy for %s\n", policy->kerneltable[i] = ICPOLICY_ASK;
policy->name);
}
while ((filter = TAILQ_FIRST(&policy->prefilters)) != NULL) { while ((filter = TAILQ_FIRST(&policy->prefilters)) != NULL) {
TAILQ_REMOVE(&policy->prefilters, filter, policy_next); TAILQ_REMOVE(&policy->prefilters, filter, policy_next);
@ -250,6 +286,18 @@ systrace_freepolicy(struct policy *policy)
free(pflq); free(pflq);
} }
}
void
systrace_freepolicy(struct policy *policy)
{
if (policy->flags & POLICY_CHANGED) {
if (systrace_writepolicy(policy) == -1)
fprintf(stderr, "Failed to write policy for %s\n",
policy->name);
}
systrace_cleanpolicy(policy);
SPLAY_REMOVE(policytree, &policyroot, policy); SPLAY_REMOVE(policytree, &policyroot, policy);
if (policy->policynr != -1) if (policy->policynr != -1)
@ -289,7 +337,7 @@ int
systrace_modifypolicy(int fd, int policynr, const char *name, short action) systrace_modifypolicy(int fd, int policynr, const char *name, short action)
{ {
struct policy *policy; struct policy *policy;
int res; int res, nr;
if ((policy = systrace_findpolnr(policynr)) == NULL) if ((policy = systrace_findpolnr(policynr)) == NULL)
return (-1); return (-1);
@ -297,20 +345,29 @@ systrace_modifypolicy(int fd, int policynr, const char *name, short action)
res = intercept_modifypolicy(fd, policynr, policy->emulation, res = intercept_modifypolicy(fd, policynr, policy->emulation,
name, action); name, action);
/* Remember the kernel policy */
if (res != -1 &&
(nr = intercept_getsyscallnumber(policy->emulation, name)) != -1)
policy->kerneltable[nr] = action;
return (res); return (res);
} }
/*
* Converts an executable name into the corresponding filename that contains
* the policy.
*/
char * char *
systrace_policyfilename(const char *dirname, const char *name) systrace_policyfilename(const char *pdirname, const char *name)
{ {
static char file[2*MAXPATHLEN]; static char file[2*MAXPATHLEN];
const char *p; const char *p;
int i, plen; int i, plen;
if (strlen(name) + strlen(dirname) + 1 >= sizeof(file)) if (strlen(name) + strlen(pdirname) + 1 >= sizeof(file))
return (NULL); return (NULL);
strlcpy(file, dirname, sizeof(file)); strlcpy(file, pdirname, sizeof(file));
i = strlen(file); i = strlen(file);
file[i++] = '/'; file[i++] = '/';
plen = i; plen = i;
@ -331,7 +388,7 @@ systrace_policyfilename(const char *dirname, const char *name)
} }
char * char *
systrace_getpolicyfilename(const char *name) systrace_getpolicyname(const char *name)
{ {
char *file = NULL; char *file = NULL;
@ -354,10 +411,10 @@ systrace_addpolicy(const char *name)
{ {
char *file = NULL; char *file = NULL;
if ((file = systrace_getpolicyfilename(name)) == NULL) if ((file = systrace_getpolicyname(name)) == NULL)
return (-1); return (-1);
return (systrace_readpolicy(file)); return (systrace_readpolicy(file) != NULL ? 0 : -1);
} }
/* /*
@ -387,7 +444,7 @@ systrace_templatedir(void)
goto error; goto error;
/* Check if template directory exists */ /* Check if template directory exists */
if (stat(filename, &sb) != -1 && (sb.st_mode & S_IFDIR)) if (stat(filename, &sb) != -1 && S_ISDIR(sb.st_mode))
dir = opendir(filename); dir = opendir(filename);
} }
@ -395,7 +452,7 @@ systrace_templatedir(void)
if (dir == NULL) { if (dir == NULL) {
strlcpy(filename, POLICY_PATH, sizeof(filename)); strlcpy(filename, POLICY_PATH, sizeof(filename));
strlcat(filename, "/templates", sizeof(filename)); strlcat(filename, "/templates", sizeof(filename));
if (stat(filename, &sb) != -1 && (sb.st_mode & S_IFDIR)) if (stat(filename, &sb) != -1 && S_ISDIR(sb.st_mode))
dir = opendir(filename); dir = opendir(filename);
if (dir == NULL) if (dir == NULL)
return (-1); return (-1);
@ -411,7 +468,7 @@ systrace_templatedir(void)
sizeof(filename)) sizeof(filename))
goto error; goto error;
if (stat(filename, &sb) == -1 || !(sb.st_mode & S_IFREG)) if (stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode))
continue; continue;
template = systrace_readtemplate(filename, NULL, NULL); template = systrace_readtemplate(filename, NULL, NULL);
@ -426,6 +483,8 @@ systrace_templatedir(void)
error: error:
errx(1, "%s: template name too long", __func__); errx(1, "%s: template name too long", __func__);
/*NOTREACHED*/
} }
struct template * struct template *
@ -507,8 +566,9 @@ systrace_readtemplate(char *filename, struct policy *policy,
goto out; goto out;
} }
/* Removes trailing whitespace and comments from the input line */ /*
* Removes trailing whitespace and comments from the input line.
*/
static char * static char *
systrace_policyline(char *line) systrace_policyline(char *line)
{ {
@ -594,7 +654,8 @@ systrace_policyprocess(struct policy *policy, char *p)
} else if (filter_parse_simple(rule, &action, &future) == 0) } else if (filter_parse_simple(rule, &action, &future) == 0)
resolved = 1; resolved = 1;
/* For now, everything that does not seem to be a valid syscall /*
* For now, everything that does not seem to be a valid syscall
* does not get fast kernel policies even though the aliasing * does not get fast kernel policies even though the aliasing
* system supports it. * system supports it.
*/ */
@ -628,8 +689,13 @@ systrace_policyprocess(struct policy *policy, char *p)
return (0); return (0);
} }
int /*
systrace_readpolicy(char *filename) * Reads policy from specified file.
* If policy exists already, this function appends new statements from the
* file to the existing policy.
*/
struct policy *
systrace_readpolicy(const char *filename)
{ {
FILE *fp; FILE *fp;
struct policy *policy; struct policy *policy;
@ -639,7 +705,7 @@ systrace_readpolicy(char *filename)
int res = -1; int res = -1;
if ((fp = fopen(filename, "r")) == NULL) if ((fp = fopen(filename, "r")) == NULL)
return (-1); return (NULL);
policy = NULL; policy = NULL;
while (fgets(line, sizeof(line), fp)) { while (fgets(line, sizeof(line), fp)) {
@ -655,6 +721,8 @@ systrace_readpolicy(char *filename)
continue; continue;
if (!strncasecmp(p, "Policy: ", 8)) { if (!strncasecmp(p, "Policy: ", 8)) {
struct timeval now;
p += 8; p += 8;
name = strsep(&p, ","); name = strsep(&p, ",");
if (p == NULL) if (p == NULL)
@ -667,6 +735,10 @@ systrace_readpolicy(char *filename)
policy = systrace_newpolicy(emulation, name); policy = systrace_newpolicy(emulation, name);
if (policy == NULL) if (policy == NULL)
goto error; goto error;
/* Update access time */
gettimeofday(&now, NULL);
TIMEVAL_TO_TIMESPEC(&now, &policy->ts_last);
continue; continue;
} }
@ -686,13 +758,64 @@ systrace_readpolicy(char *filename)
out: out:
fclose(fp); fclose(fp);
return (res); return (res == -1 ? NULL : policy);
error: error:
fprintf(stderr, "%s:%d: syntax error.\n", filename, linenumber); fprintf(stderr, "%s:%d: syntax error.\n", filename, linenumber);
goto out; goto out;
} }
/*
* Appends new policy statements if the policy has been updated by
* another process. Assumes that policies are append-only.
*
* Returns:
* -1 if the policy could not be updated.
* 0 if the policy has been updated.
*/
int
systrace_updatepolicy(int fd, struct policy *policy)
{
struct stat sb;
struct timespec mtimespec;
int i, policynr = policy->policynr;
char *file;
if ((file = systrace_getpolicyname(policy->name)) == NULL)
return (-1);
if (stat(file, &sb) == -1)
return (-1);
mtimespec = sb.st_mtimespec;
/* Policy does not need updating */
if (timespeccmp(&mtimespec, &policy->ts_last, <=))
return (-1);
/* Reset the existing policy */
for (i = 0; i < INTERCEPT_MAXSYSCALLNR; i++) {
if (policy->kerneltable[i] == ICPOLICY_ASK)
continue;
if (intercept_modifypolicy_nr(fd, policynr, i,
ICPOLICY_ASK) == -1)
errx(1, "%s: failed to modify policy for %d",
__func__, i);
}
/* Now clean up all filter structures in this policy */
systrace_cleanpolicy(policy);
/* XXX - This does not deal with Detached and Automatic */
if (systrace_readpolicy(file) == NULL)
return (-1);
/* Resets the changed flag */
filter_prepolicy(fd, policy);
return (0);
}
int int
systrace_writepolicy(struct policy *policy) systrace_writepolicy(struct policy *policy)
{ {
@ -702,6 +825,7 @@ systrace_writepolicy(struct policy *policy)
char tmpname[2*MAXPATHLEN]; char tmpname[2*MAXPATHLEN];
char finalname[2*MAXPATHLEN]; char finalname[2*MAXPATHLEN];
struct filter *filter; struct filter *filter;
struct timeval now;
if ((p = systrace_policyfilename(policydir, policy->name)) == NULL) if ((p = systrace_policyfilename(policydir, policy->name)) == NULL)
return (-1); return (-1);
@ -741,11 +865,33 @@ systrace_writepolicy(struct policy *policy)
return (-1); return (-1);
} }
/* Update access time */
gettimeofday(&now, NULL);
TIMEVAL_TO_TIMESPEC(&now, &policy->ts_last);
return (0); return (0);
} }
int int
systrace_dumppolicy(void) systrace_updatepolicies(int fd)
{
struct policy *policy;
SPLAY_FOREACH(policy, policytree, &policyroot) {
/* Check if the policy has been updated */
systrace_updatepolicy(fd, policy);
}
return (0);
}
/*
* Write policy to disk if it has been changed. We need to
* call systrace_updatepolicies() before this, so that we
* don't clobber changes.
*/
int
systrace_dumppolicies(int fd)
{ {
struct policy *policy; struct policy *policy;

View File

@ -1,4 +1,4 @@
/* $NetBSD: register.c,v 1.19 2006/08/21 01:35:11 christos Exp $ */ /* $NetBSD: register.c,v 1.20 2006/12/10 01:22:02 christos Exp $ */
/* $OpenBSD: register.c,v 1.11 2002/08/05 14:49:27 provos Exp $ */ /* $OpenBSD: register.c,v 1.11 2002/08/05 14:49:27 provos Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -37,9 +37,13 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <err.h> #include <err.h>
#include <time.h>
#include "intercept.h" #include "intercept.h"
#include "systrace.h" #include "systrace.h"
#ifdef notyet /* XXX we don't have the required headers for this */
#include "linux_socketcall.h"
#endif
#define X(x) if ((x) == -1) \ #define X(x) if ((x) == -1) \
err(1, "%s:%d: intercept failed", __func__, __LINE__) err(1, "%s:%d: intercept failed", __func__, __LINE__)
@ -425,7 +429,7 @@ systrace_initcb(void)
intercept_register_translation("native", "seteuid", 0, &ic_uname); intercept_register_translation("native", "seteuid", 0, &ic_uname);
#endif #endif
#if !(defined(__NetBSD__) && !defined(HAVE_LINUX_FCNTL_H)) #if !(defined(__NetBSD__) || !defined(HAVE_LINUX_FCNTL_H))
/* 5: open [fswrite] */ /* 5: open [fswrite] */
X(intercept_register_sccb("linux", "open", trans_cb, NULL)); X(intercept_register_sccb("linux", "open", trans_cb, NULL));
tl = intercept_register_translink("linux", "open", 0); tl = intercept_register_translink("linux", "open", 0);
@ -459,6 +463,11 @@ systrace_initcb(void)
alias = systrace_new_alias("linux", "access", "linux", "fsread"); alias = systrace_new_alias("linux", "access", "linux", "fsread");
systrace_alias_add_trans(alias, tl); systrace_alias_add_trans(alias, tl);
/* 37: kill */
X(intercept_register_sccb("linux", "kill", trans_cb, NULL));
intercept_register_translation("linux", "kill", 0, &ic_pidname);
intercept_register_translation("linux", "kill", 1, &ic_signame);
/* 38: rename */ /* 38: rename */
X(intercept_register_sccb("linux", "rename", trans_cb, NULL)); X(intercept_register_sccb("linux", "rename", trans_cb, NULL));
intercept_register_translink("linux", "rename", 0); intercept_register_translink("linux", "rename", 0);
@ -487,6 +496,20 @@ systrace_initcb(void)
alias = systrace_new_alias("linux", "readlink", "linux", "fsread"); alias = systrace_new_alias("linux", "readlink", "linux", "fsread");
systrace_alias_add_trans(alias, tl); systrace_alias_add_trans(alias, tl);
/* 102: socketcall */
X(intercept_register_sccb("linux", "socketcall", trans_cb, NULL));
alias = systrace_new_alias("linux", "socketcall", "linux", "_socketcall");
tl = intercept_register_translation("linux", "socketcall", 1, &ic_linux_socket_sockdom);
systrace_alias_add_trans(alias, tl);
tl = intercept_register_translation("linux", "socketcall", 1, &ic_linux_socket_socktype);
systrace_alias_add_trans(alias, tl);
tl = intercept_register_translation("linux", "socketcall", 1, &ic_linux_connect_sockaddr);
systrace_alias_add_trans(alias, tl);
tl = intercept_register_translation("linux", "socketcall", 1, &ic_linux_bind_sockaddr);
systrace_alias_add_trans(alias, tl);
tl = intercept_register_translation("linux", "socketcall", 0, &ic_linux_socketcall_catchall);
systrace_alias_add_trans(alias, tl);
/* 106: stat [fsread] */ /* 106: stat [fsread] */
X(intercept_register_sccb("linux", "stat", trans_cb, NULL)); X(intercept_register_sccb("linux", "stat", trans_cb, NULL));
tl = intercept_register_translink("linux", "stat", 0); tl = intercept_register_translink("linux", "stat", 0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: systrace-error.c,v 1.3 2005/06/24 23:21:09 christos Exp $ */ /* $NetBSD: systrace-error.c,v 1.4 2006/12/10 01:22:02 christos Exp $ */
/* $OpenBSD: systrace-error.c,v 1.1 2002/06/04 17:20:04 provos Exp $ */ /* $OpenBSD: systrace-error.c,v 1.1 2002/06/04 17:20:04 provos Exp $ */
/* /*
@ -31,7 +31,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__RCSID("$NetBSD: systrace-error.c,v 1.3 2005/06/24 23:21:09 christos Exp $"); __RCSID("$NetBSD: systrace-error.c,v 1.4 2006/12/10 01:22:02 christos Exp $");
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -40,6 +40,7 @@ __RCSID("$NetBSD: systrace-error.c,v 1.3 2005/06/24 23:21:09 christos Exp $");
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <time.h>
#include "intercept.h" #include "intercept.h"
#include "systrace.h" #include "systrace.h"

View File

@ -1,4 +1,4 @@
/* $NetBSD: systrace-translate.c,v 1.18 2006/11/12 23:29:37 cbiere Exp $ */ /* $NetBSD: systrace-translate.c,v 1.19 2006/12/10 01:22:02 christos Exp $ */
/* $OpenBSD: systrace-translate.c,v 1.10 2002/08/01 20:50:17 provos Exp $ */ /* $OpenBSD: systrace-translate.c,v 1.10 2002/08/01 20:50:17 provos Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -211,15 +211,15 @@ print_sockdom(char *buf, size_t buflen, struct intercept_translate *tl)
case AF_INET6: case AF_INET6:
what = "AF_INET6"; what = "AF_INET6";
break; break;
case AF_IPX:
what = "AF_IPX";
break;
case AF_ISO: case AF_ISO:
what = "AF_ISO"; what = "AF_ISO";
break; break;
case AF_NS: case AF_NS:
what = "AF_NS"; what = "AF_NS";
break; break;
case AF_IPX:
what = "AF_IPX";
break;
case AF_IMPLINK: case AF_IMPLINK:
what = "AF_IMPLINK"; what = "AF_IMPLINK";
break; break;
@ -287,12 +287,18 @@ print_pidname(char *buf, size_t buflen, struct intercept_translate *tl)
if (pid != 0) { if (pid != 0) {
icpid = intercept_getpid(pid); icpid = intercept_getpid(pid);
strlcpy(buf, icpid->name != NULL ? icpid->name strlcpy(buf, icpid != NULL ? icpid->name : "<unknown>", buflen);
: "<unknown>", buflen); } else if (pid == 0) {
if (icpid->name == NULL)
intercept_freepid(pid);
} else
strlcpy(buf, "<own process group>", buflen); strlcpy(buf, "<own process group>", buflen);
} else if (pid == -1) {
strlcpy(buf, "<every process: -1>", buflen);
} else {
/* pid is negative but not -1 - trying to signal pgroup */
pid = -pid;
icpid = intercept_findpid(pid);
strlcpy(buf, "pg:", buflen);
strlcat(buf, icpid != NULL ? icpid->name : "unknown", buflen);
}
return (0); return (0);
} }
@ -443,6 +449,32 @@ print_fcntlcmd(char *buf, size_t buflen, struct intercept_translate *tl)
return (0); return (0);
} }
struct linux_i386_mmap_arg_struct {
unsigned long addr;
unsigned long len;
unsigned long prot;
unsigned long flags;
unsigned long fd;
unsigned long offset;
};
static int
get_linux_memprot(struct intercept_translate *trans, int fd, pid_t pid,
void *addr)
{
struct linux_i386_mmap_arg_struct arg;
size_t len = sizeof(arg);
extern struct intercept_system intercept;
if (intercept.io(fd, pid, INTERCEPT_READ, addr,
(void *)&arg, len) == -1)
return (-1);
trans->trans_addr = (void *)arg.prot;
return (0);
}
static int static int
print_memprot(char *buf, size_t buflen, struct intercept_translate *tl) print_memprot(char *buf, size_t buflen, struct intercept_translate *tl)
{ {
@ -625,3 +657,8 @@ struct intercept_translate ic_memprot = {
.translate = NULL, .translate = NULL,
.print = print_memprot, .print = print_memprot,
}; };
struct intercept_translate ic_linux_memprot = {
"prot",
get_linux_memprot, print_memprot,
};

View File

@ -1,4 +1,4 @@
.\" $NetBSD: systrace.1,v 1.33 2005/09/03 11:44:45 elad Exp $ .\" $NetBSD: systrace.1,v 1.34 2006/12/10 01:22:02 christos Exp $
.\" $OpenBSD: systrace.1,v 1.27 2002/08/05 23:27:53 provos Exp $ .\" $OpenBSD: systrace.1,v 1.27 2002/08/05 23:27:53 provos Exp $
.\" .\"
.\" Copyright 2002 Niels Provos <provos@citi.umich.edu> .\" Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -40,7 +40,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm systrace .Nm systrace
.Bk -words .Bk -words
.Op Fl AaCitUu .Op Fl AaCitUuV
.Op Fl c Ar user:group .Op Fl c Ar user:group
.Op Fl d Ar policydir .Op Fl d Ar policydir
.Op Fl f Ar file .Op Fl f Ar file
@ -104,12 +104,22 @@ root privilege.
.It Fl d Ar policydir .It Fl d Ar policydir
Specifies an alternative location for the user's directory from Specifies an alternative location for the user's directory from
which policies are loaded and to which changed policies are stored. which policies are loaded and to which changed policies are stored.
.It Fl E Ar logfile
Logs all policy violations or specifically logged system calls to
.Ar logfile .
.It Fl f Ar file .It Fl f Ar file
The policies specified in The policies specified in
.Ar file .Ar file
are added to the policies that are added to the policies that
.Nm .Nm
knows about. knows about.
The
.Dq dirname
inthe policy may contain a
.Sq \*
to match any possible pathname.
The wildcard is removed from the policy database the first time that a
filename matches.
.It Fl g Ar gui .It Fl g Ar gui
Specifies an alternative location for the notification user interface. Specifies an alternative location for the notification user interface.
.It Fl i .It Fl i
@ -135,6 +145,9 @@ and
.Fn access .Fn access
are translated to are translated to
.Fn fsread . .Fn fsread .
.It Fl V
Prints the version number of
.Nm .
.El .El
.Ss POLICY .Ss POLICY
The policy is specified via the following grammar: The policy is specified via the following grammar:

View File

@ -1,4 +1,4 @@
/* $NetBSD: systrace.c,v 1.33 2006/05/10 21:53:14 mrg Exp $ */ /* $NetBSD: systrace.c,v 1.34 2006/12/10 01:22:02 christos Exp $ */
/* $OpenBSD: systrace.c,v 1.32 2002/08/05 23:27:53 provos Exp $ */ /* $OpenBSD: systrace.c,v 1.32 2002/08/05 23:27:53 provos Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -47,6 +47,8 @@
#include <errno.h> #include <errno.h>
#include <grp.h> #include <grp.h>
#include <pwd.h> #include <pwd.h>
#include <event.h>
#include <stdarg.h>
#include "intercept.h" #include "intercept.h"
#include "systrace.h" #include "systrace.h"
@ -55,6 +57,8 @@
#define CRADLE_SERVER "cradle_server" #define CRADLE_SERVER "cradle_server"
#define CRADLE_UI "cradle_ui" #define CRADLE_UI "cradle_ui"
#define VERSION "1.6d (NetBSD)"
pid_t trpid; pid_t trpid;
int trfd; int trfd;
int connected = 0; /* Connected to GUI */ int connected = 0; /* Connected to GUI */
@ -64,15 +68,23 @@ int allow = 0; /* Allow all and generate */
int userpolicy = 1; /* Permit user defined policies */ int userpolicy = 1; /* Permit user defined policies */
int noalias = 0; /* Do not do system call aliasing */ int noalias = 0; /* Do not do system call aliasing */
int iamroot = 0; /* Set if we are running as root */ int iamroot = 0; /* Set if we are running as root */
int cradle = 0; /* Set if we are running in cradle mode */ int cradle = 0; /* Set if we are running in cradle mode */
int logtofile = 0; /* Log to file instead of syslog */
FILE *logfile; /* Default logfile to send to if enabeld */
char cwd[MAXPATHLEN]; /* Current working directory */ char cwd[MAXPATHLEN]; /* Current working directory */
char home[MAXPATHLEN]; /* Home directory of user */ char home[MAXPATHLEN]; /* Home directory of user */
char username[LOGIN_NAME_MAX]; /* Username: predicate match and expansion */ char username[LOGIN_NAME_MAX]; /* Username: predicate match and expansion */
const char *guipath = _PATH_XSYSTRACE; /* Path to GUI executable */ const char *guipath = _PATH_XSYSTRACE; /* Path to GUI executable */
char dirpath[MAXPATHLEN]; char dirpath[MAXPATHLEN];
static struct event ev_read;
static struct event ev_timeout;
static void child_handler(int); static void child_handler(int);
static void log_msg(int, const char *, ...);
static void usage(void); static void usage(void);
static void systrace_read(int, short, void *);
static void systrace_timeout(int, short, void *);
void void
systrace_parameters(void) systrace_parameters(void)
@ -162,7 +174,7 @@ trans_cb(int fd, pid_t pid, int policynr,
const char *binname = NULL; const char *binname = NULL;
char output[_POSIX2_LINE_MAX]; char output[_POSIX2_LINE_MAX];
pid_t ppid; pid_t ppid;
int dolog = 0; int done = 0, dolog = 0;
ipid = NULL; /* XXXGCC -Wuninitialized [dreamcast] */ ipid = NULL; /* XXXGCC -Wuninitialized [dreamcast] */
@ -181,48 +193,63 @@ trans_cb(int fd, pid_t pid, int policynr,
ppid = ipid->ppid; ppid = ipid->ppid;
/* Required to set up replacements */ /* Required to set up replacements */
make_output(output, sizeof(output), binname, pid, ppid, policynr, do {
policy->name, policy->nfilters, emulation, name, code, make_output(output, sizeof(output), binname, pid, ppid,
tls, repl); policynr, policy->name, policy->nfilters, emulation,
name, code, tls, repl);
if ((pflq = systrace_policyflq(policy, emulation, name)) == NULL) /* Fast-path checking */
errx(1, "%s:%d: no filter queue", __func__, __LINE__); if ((action = policy->kerneltable[code]) != ICPOLICY_ASK)
goto out;
action = filter_evaluate(tls, pflq, ipid); pflq = systrace_policyflq(policy, emulation, name);
if (action != ICPOLICY_ASK) if (pflq == NULL)
goto done;
/* Do aliasing here */
if (!noalias)
alias = systrace_find_alias(emulation, name);
if (alias != NULL) {
int i;
/* Set up variables for further filter actions */
tls = &alitls;
emulation = alias->aemul;
name = alias->aname;
/* Create an aliased list for filter_evaluate */
TAILQ_INIT(tls);
for (i = 0; i < alias->nargs; i++) {
memcpy(&alitl[i], alias->arguments[i],
sizeof(struct intercept_translate));
TAILQ_INSERT_TAIL(tls, &alitl[i], next);
}
if ((pflq = systrace_policyflq(policy,
alias->aemul, alias->aname)) == NULL)
errx(1, "%s:%d: no filter queue", __func__, __LINE__); errx(1, "%s:%d: no filter queue", __func__, __LINE__);
action = filter_evaluate(tls, pflq, ipid); action = filter_evaluate(tls, pflq, ipid);
if (action != ICPOLICY_ASK) if (action != ICPOLICY_ASK)
goto done; goto done;
make_output(output, sizeof(output), binname, pid, ppid, /* Do aliasing here */
policynr, policy->name, policy->nfilters, if (!noalias)
alias->aemul, alias->aname, code, tls, NULL); alias = systrace_find_alias(emulation, name);
} if (alias != NULL) {
int i;
/* Set up variables for further filter actions */
tls = &alitls;
emulation = alias->aemul;
name = alias->aname;
/* Create an aliased list for filter_evaluate */
TAILQ_INIT(tls);
for (i = 0; i < alias->nargs; i++) {
memcpy(&alitl[i], alias->arguments[i],
sizeof(struct intercept_translate));
TAILQ_INSERT_TAIL(tls, &alitl[i], next);
}
if ((pflq = systrace_policyflq(policy,
alias->aemul, alias->aname)) == NULL)
errx(1, "%s:%d: no filter queue",
__func__, __LINE__);
action = filter_evaluate(tls, pflq, ipid);
if (action != ICPOLICY_ASK)
goto done;
make_output(output, sizeof(output), binname, pid, ppid,
policynr, policy->name, policy->nfilters,
alias->aemul, alias->aname, code, tls, NULL);
}
/*
* At this point, we have to ask the user, but we may check
* if the policy has been updated in the meanwhile.
*/
if (systrace_updatepolicy(fd, policy) == -1)
done = 1;
} while (!done);
if (policy->flags & POLICY_UNSUPERVISED) { if (policy->flags & POLICY_UNSUPERVISED) {
action = ICPOLICY_NEVER; action = ICPOLICY_NEVER;
@ -251,7 +278,7 @@ trans_cb(int fd, pid_t pid, int policynr,
out: out:
if (dolog) if (dolog)
syslog(LOG_WARNING, "%s user: %s, prog: %s", log_msg(LOG_WARNING, "%s user: %s, prog: %s",
action < ICPOLICY_NEVER ? "permit" : "deny", action < ICPOLICY_NEVER ? "permit" : "deny",
ipid->username, output); ipid->username, output);
@ -270,7 +297,8 @@ gen_cb(int fd, pid_t pid, int policynr, const char *name, int code,
struct filterq *pflq = NULL; struct filterq *pflq = NULL;
short action = ICPOLICY_PERMIT; short action = ICPOLICY_PERMIT;
short future; short future;
int len, off, dolog = 0; int off, done = 0, dolog = 0;
size_t len;
ipid = NULL; /* XXXGCC -Wuninitialized [dreamcast] */ ipid = NULL; /* XXXGCC -Wuninitialized [dreamcast] */
@ -298,18 +326,28 @@ gen_cb(int fd, pid_t pid, int policynr, const char *name, int code,
if ((pflq = systrace_policyflq(policy, emulation, name)) == NULL) if ((pflq = systrace_policyflq(policy, emulation, name)) == NULL)
errx(1, "%s:%d: no filter queue", __func__, __LINE__); errx(1, "%s:%d: no filter queue", __func__, __LINE__);
action = filter_evaluate(NULL, pflq, ipid); do {
/* Fast-path checking */
if ((action = policy->kerneltable[code]) != ICPOLICY_ASK)
goto out;
if (ipid->uflags & SYSCALL_LOG) action = filter_evaluate(NULL, pflq, ipid);
dolog = 1;
if (action != ICPOLICY_ASK)
if (action != ICPOLICY_ASK) goto haveresult;
goto out;
/*
* At this point, we have to ask the user, but we may check
* if the policy has been updated in the meanwhile.
*/
if (systrace_updatepolicy(fd, policy) == -1)
done = 1;
} while (!done);
if (policy->flags & POLICY_UNSUPERVISED) { if (policy->flags & POLICY_UNSUPERVISED) {
action = ICPOLICY_NEVER; action = ICPOLICY_NEVER;
dolog = 1; dolog = 1;
goto out; goto haveresult;
} }
action = filter_ask(fd, NULL, pflq, policynr, emulation, name, action = filter_ask(fd, NULL, pflq, policynr, emulation, name,
@ -324,12 +362,16 @@ gen_cb(int fd, pid_t pid, int policynr, const char *name, int code,
kill(pid, SIGKILL); kill(pid, SIGKILL);
return (ICPOLICY_NEVER); return (ICPOLICY_NEVER);
} }
out: haveresult:
if (ipid->uflags & SYSCALL_LOG)
dolog = 1;
if (dolog) if (dolog)
syslog(LOG_WARNING, "%s user: %s, prog: %s", syslog(LOG_WARNING, "%s user: %s, prog: %s",
action < ICPOLICY_NEVER ? "permit" : "deny", action < ICPOLICY_NEVER ? "permit" : "deny",
ipid->username, output); ipid->username, output);
out:
return (action); return (action);
} }
@ -414,17 +456,35 @@ child_handler(int sig)
} }
while (wait4(-1, &status, WNOHANG, NULL) > 0) while (wait4(-1, &status, WNOHANG, NULL) > 0)
; continue;
errno = s; errno = s;
} }
static void
log_msg(int priority, const char *fmt, ...)
{
char buf[_POSIX2_LINE_MAX];
va_list ap;
va_start(ap, fmt);
if (logtofile) {
vsnprintf(buf, sizeof(buf), fmt, ap);
fprintf(logfile, "%s: %s\n", getprogname(), buf);
} else
vsyslog(priority, fmt, ap);
va_end(ap);
}
static void static void
usage(void) usage(void)
{ {
fprintf(stderr, fprintf(stderr,
"usage: systrace [-AaCitUu] [-c uid:gid] [-d policydir] [-f file]\n" "Usage: %s [-AaCeitUuV] [-c user:group] [-d policydir] "
"\t [-g gui] [-p pid] command ...\n"); "[-E logfile]\n\t [-f file] [-g gui] [-p pid] command ...\n",
getprogname());
exit(1); exit(1);
} }
@ -560,6 +620,35 @@ get_uid_gid(const char *argument, uid_t *uid, gid_t *gid)
return (0); return (0);
} }
static void
systrace_timeout(int fd, short what, void *arg)
{
struct timeval tv;
/* Reschedule timeout */
timerclear(&tv);
tv.tv_sec = SYSTRACE_UPDATETIME;
evtimer_add(&ev_timeout, &tv);
systrace_updatepolicies(trfd);
if (userpolicy)
systrace_dumppolicies(trfd);
}
/*
* Read from the kernel if something happened.
*/
static void
systrace_read(int fd, short what, void *arg)
{
intercept_read(fd);
if (!intercept_existpids()) {
event_del(&ev_read);
event_del(&ev_timeout);
}
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
@ -567,9 +656,9 @@ main(int argc, char **argv)
char **args; char **args;
char *filename = NULL; char *filename = NULL;
char *policypath = NULL; char *policypath = NULL;
struct timeval tv, tv_wait; struct timeval tv;
pid_t pidattach = 0; pid_t pidattach = 0;
int usex11 = 1, count; int usex11 = 1;
int background; int background;
int setcredentials = 0; int setcredentials = 0;
uid_t cr_uid; uid_t cr_uid;
@ -578,11 +667,11 @@ main(int argc, char **argv)
cr_uid = 0; /* XXX gcc */ cr_uid = 0; /* XXX gcc */
cr_gid = 0; /* XXX gcc */ cr_gid = 0; /* XXX gcc */
tv_wait.tv_sec = 60; while ((c = getopt(argc, argv, "Vc:aAeE:ituUCd:g:f:p:")) != -1) {
tv_wait.tv_usec = 0;
while ((c = getopt(argc, argv, "c:aAituUCd:g:f:p:")) != -1) {
switch (c) { switch (c) {
case 'V':
fprintf(stderr, "%s V%s\n", argv[0], VERSION);
exit(0);
case 'c': case 'c':
setcredentials = 1; setcredentials = 1;
if (get_uid_gid(optarg, &cr_uid, &cr_gid) == -1) if (get_uid_gid(optarg, &cr_uid, &cr_gid) == -1)
@ -596,6 +685,16 @@ main(int argc, char **argv)
case 'd': case 'd':
policypath = optarg; policypath = optarg;
break; break;
case 'e':
logtofile = 1;
logfile = stderr;
break;
case 'E':
logtofile = 1;
logfile = fopen(optarg, "a");
if (logfile == NULL)
err(1, "Cannot open `%s' for writing", optarg);
break;
case 'A': case 'A':
if (automatic) if (automatic)
usage(); usage();
@ -648,6 +747,10 @@ main(int argc, char **argv)
usage(); usage();
} }
/* Initialize libevent but without kqueue because of systrace fd */
setenv("EVENT_NOKQUEUE", "yes", 0);
event_init();
/* Local initalization */ /* Local initalization */
systrace_initalias(); systrace_initalias();
systrace_initpolicy(filename, policypath); systrace_initpolicy(filename, policypath);
@ -696,6 +799,9 @@ main(int argc, char **argv)
if (signal(SIGCHLD, child_handler) == SIG_ERR) if (signal(SIGCHLD, child_handler) == SIG_ERR)
err(1, "signal"); err(1, "signal");
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
err(1, "signal");
/* Start the policy gui or cradle if necessary */ /* Start the policy gui or cradle if necessary */
if (usex11 && (!automatic && !allow)) { if (usex11 && (!automatic && !allow)) {
if (cradle) if (cradle)
@ -705,34 +811,22 @@ main(int argc, char **argv)
} }
/* Loop on requests */ /* Register read events */
count = 0; event_set(&ev_read, trfd, EV_READ|EV_PERSIST, systrace_read, NULL);
while (intercept_read(trfd) != -1) { event_add(&ev_read, NULL);
if (!intercept_existpids())
break;
if (userpolicy) {
/* Periodically save modified policies */
if (count == 0) {
/* Set new wait time */
gettimeofday(&tv, NULL);
timeradd(&tv, &tv_wait, &tv);
} else if (count > 10) {
struct timeval now;
gettimeofday(&now, NULL);
count = 0; if (userpolicy || automatic) {
if (timercmp(&now, &tv, >)) { evtimer_set(&ev_timeout, systrace_timeout, &ev_timeout);
/* Dump policy and cause new time */ timerclear(&tv);
systrace_dumppolicy(); tv.tv_sec = SYSTRACE_UPDATETIME;
continue; evtimer_add(&ev_timeout, &tv);
}
}
count++;
}
} }
/* Wait for events */
event_dispatch();
if (userpolicy) if (userpolicy)
systrace_dumppolicy(); systrace_dumppolicies(trfd);
close(trfd); close(trfd);

View File

@ -1,4 +1,4 @@
/* $NetBSD: systrace.h,v 1.21 2005/08/10 18:19:21 elad Exp $ */ /* $NetBSD: systrace.h,v 1.22 2006/12/10 01:22:02 christos Exp $ */
/* $OpenBSD: systrace.h,v 1.14 2002/08/05 23:27:53 provos Exp $ */ /* $OpenBSD: systrace.h,v 1.14 2002/08/05 23:27:53 provos Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -99,9 +99,12 @@ struct policy {
const char *name; const char *name;
char emulation[16]; char emulation[16];
struct timespec ts_last;
SPLAY_HEAD(syscalltree, policy_syscall) pflqs; SPLAY_HEAD(syscalltree, policy_syscall) pflqs;
int policynr; int policynr;
short kerneltable[INTERCEPT_MAXSYSCALLNR];
int flags; int flags;
struct filterq filters; struct filterq filters;
@ -132,6 +135,8 @@ TAILQ_HEAD(tmplqueue, template);
#define SYSCALL_LOG 0x04 /* Log this system call */ #define SYSCALL_LOG 0x04 /* Log this system call */
#define PROCESS_PROMPT 0x08 /* Prompt but nothing else */ #define PROCESS_PROMPT 0x08 /* Prompt but nothing else */
#define SYSTRACE_UPDATETIME 30 /* update policies every 30 seconds */
void systrace_parameters(void); void systrace_parameters(void);
int systrace_initpolicy(char *, char *); int systrace_initpolicy(char *, char *);
void systrace_setupdir(char *); void systrace_setupdir(char *);
@ -139,20 +144,25 @@ struct template *systrace_readtemplate(char *, struct policy *,
struct template *); struct template *);
void systrace_initcb(void); void systrace_initcb(void);
struct policy *systrace_newpolicy(const char *, const char *); struct policy *systrace_newpolicy(const char *, const char *);
void systrace_cleanpolicy(struct policy *);
void systrace_freepolicy(struct policy *); void systrace_freepolicy(struct policy *);
int systrace_newpolicynr(int, struct policy *); int systrace_newpolicynr(int, struct policy *);
int systrace_modifypolicy(int, int, const char *, short); int systrace_modifypolicy(int, int, const char *, short);
struct policy *systrace_findpolicy(const char *); struct policy *systrace_findpolicy(const char *);
struct policy *systrace_findpolicy_wildcard(const char *);
struct policy *systrace_findpolnr(int); struct policy *systrace_findpolnr(int);
int systrace_dumppolicy(void); int systrace_dumppolicies(int);
int systrace_readpolicy(char *); int systrace_updatepolicies(int);
struct policy *systrace_readpolicy(const char *);
char *systrace_getpolicyfilename(const char *); char *systrace_getpolicyfilename(const char *);
int systrace_addpolicy(const char *); int systrace_addpolicy(const char *);
int systrace_updatepolicy(int, struct policy *);
struct filterq *systrace_policyflq(struct policy *, const char *, const char *); struct filterq *systrace_policyflq(struct policy *, const char *, const char *);
char *systrace_getpolicyname(const char *);
int systrace_error_translate(char *); int systrace_error_translate(char *);
#define SYSTRACE_MAXALIAS 5 #define SYSTRACE_MAXALIAS 10
struct systrace_alias { struct systrace_alias {
SPLAY_ENTRY(systrace_alias) node; SPLAY_ENTRY(systrace_alias) node;
@ -235,8 +245,10 @@ extern struct intercept_translate ic_pidname;
extern struct intercept_translate ic_signame; extern struct intercept_translate ic_signame;
extern struct intercept_translate ic_fcntlcmd; extern struct intercept_translate ic_fcntlcmd;
extern struct intercept_translate ic_memprot; extern struct intercept_translate ic_memprot;
#ifdef notyet
extern struct intercept_translate ic_linux_memprot;
extern struct intercept_translate ic_linux_oflags; extern struct intercept_translate ic_linux_oflags;
#endif
int requestor_start(const char *, int); int requestor_start(const char *, int);