Sync with OpenBSD systrace 1.6d.
XXX: Some of the compat-linux systrace is disabled. From elad.
This commit is contained in:
parent
ba06ad7411
commit
ddbf1b0dd9
|
@ -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 $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
|
@ -30,7 +30,7 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#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/types.h>
|
||||
|
@ -400,6 +400,10 @@ filter_modifypolicy(int fd, int policynr, const char *emulation,
|
|||
{
|
||||
struct systrace_revalias *reverse = NULL;
|
||||
|
||||
/*
|
||||
* Check if we are dealing with a system call that really
|
||||
* is an alias for something else.
|
||||
*/
|
||||
if (!noalias)
|
||||
reverse = systrace_find_reverse(emulation, name);
|
||||
if (reverse == NULL) {
|
||||
|
@ -444,6 +448,11 @@ filter_quickpredicate(struct filter *filter)
|
|||
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
|
||||
filter_prepolicy(int fd, struct policy *policy)
|
||||
{
|
||||
|
|
|
@ -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 $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
|
@ -30,7 +30,7 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#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/param.h>
|
||||
|
@ -555,6 +555,9 @@ intercept_get_string(int fd, pid_t pid, void *addr)
|
|||
static char name[8192];
|
||||
int off = 0, done = 0, stride;
|
||||
|
||||
if (addr == NULL)
|
||||
return (NULL);
|
||||
|
||||
stride = 32;
|
||||
do {
|
||||
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;
|
||||
}
|
||||
|
||||
/* Need concatenated path for simplifypath */
|
||||
if (havecwd && name[0] != '/') {
|
||||
if (strlcat(cwd, "/", sizeof(cwd)) >= sizeof(cwd))
|
||||
return (NULL);
|
||||
|
@ -707,7 +709,7 @@ normalize_filename(int fd, pid_t pid, char *name, int userp)
|
|||
*/
|
||||
if (userp != ICLINK_NOLAST) {
|
||||
if (lstat(rcwd, &st) == -1 ||
|
||||
!(st.st_mode & S_IFDIR))
|
||||
!S_ISDIR(st.st_mode))
|
||||
failed = 1;
|
||||
}
|
||||
}
|
||||
|
@ -891,6 +893,12 @@ intercept_assignpolicy(int fd, pid_t pid, int 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
|
||||
intercept_modifypolicy(int fd, int policynr, const char *emulation,
|
||||
const char *name, short policy)
|
||||
|
@ -964,13 +972,28 @@ intercept_ugid(struct intercept_pid *icpid, uid_t uid, gid_t 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.
|
||||
* This is a very slow function.
|
||||
*/
|
||||
|
||||
int
|
||||
intercept_isvalidsystemcall(char *emulation, char *name)
|
||||
intercept_isvalidsystemcall(const char *emulation, const char *name)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
|
|
@ -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 $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
|
@ -111,6 +111,7 @@ struct intercept_pid {
|
|||
struct elevate *elevate; /* privilege elevation request */
|
||||
};
|
||||
|
||||
#define INTERCEPT_MAXSYSCALLNR 512
|
||||
#define INTERCEPT_MAXSYSCALLARGS 10
|
||||
|
||||
struct intercept_translate {
|
||||
|
@ -126,6 +127,7 @@ struct intercept_translate {
|
|||
size_t trans_size;
|
||||
char *trans_print;
|
||||
u_int trans_flags;
|
||||
void *user;
|
||||
TAILQ_ENTRY(intercept_translate) next;
|
||||
};
|
||||
|
||||
|
@ -149,6 +151,7 @@ int intercept_read(int);
|
|||
int intercept_newpolicy(int);
|
||||
int intercept_assignpolicy(int, pid_t, int);
|
||||
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_policy_free(int);
|
||||
|
||||
|
@ -197,12 +200,13 @@ void intercept_syscall(int, pid_t, u_int16_t, int, const char *, int,
|
|||
const char *, void *, int);
|
||||
void intercept_syscall_result(int, pid_t, u_int16_t, int, const char *, int,
|
||||
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 *,
|
||||
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 *);
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#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/param.h>
|
||||
|
@ -466,6 +466,8 @@ nbsd_replace(int fd, pid_t pid, u_int16_t seqnr,
|
|||
size_t len, off;
|
||||
int i, ret;
|
||||
|
||||
memset(&replace, 0, sizeof(replace));
|
||||
|
||||
for (i = 0, len = 0; i < repl->num; i++) {
|
||||
len += repl->len[i];
|
||||
}
|
||||
|
|
|
@ -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 $ */
|
||||
/*
|
||||
* 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;
|
||||
int i, ret;
|
||||
|
||||
memset(&replace, 0, sizeof(replace));
|
||||
|
||||
for (i = 0, len = 0; i < repl->num; i++) {
|
||||
len += repl->len[i];
|
||||
}
|
||||
|
|
|
@ -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 $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
|
@ -30,7 +30,7 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#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/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 <ctype.h>
|
||||
#include <err.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "intercept.h"
|
||||
#include "systrace.h"
|
||||
|
@ -132,7 +133,7 @@ systrace_setupdir(char *path)
|
|||
|
||||
|
||||
if (stat(policydir, &sb) != -1) {
|
||||
if (!(sb.st_mode & S_IFDIR))
|
||||
if (!S_ISDIR(sb.st_mode))
|
||||
errx(1, "Not a directory: \"%s\"", policydir);
|
||||
} else if (mkdir(policydir, 0700) == -1)
|
||||
err(1, "mkdir(%s)", policydir);
|
||||
|
@ -150,11 +151,39 @@ systrace_initpolicy(char *file, char *path)
|
|||
}
|
||||
|
||||
if (file != NULL)
|
||||
return (systrace_readpolicy(file));
|
||||
return (systrace_readpolicy(file) != NULL ? 0 : -1);
|
||||
|
||||
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 *
|
||||
systrace_findpolicy(const char *name)
|
||||
{
|
||||
|
@ -195,10 +224,14 @@ struct policy *
|
|||
systrace_newpolicy(const char *emulation, const char *name)
|
||||
{
|
||||
struct policy *tmp;
|
||||
int i;
|
||||
|
||||
if ((tmp = systrace_findpolicy(name)) != NULL)
|
||||
return (tmp);
|
||||
|
||||
if ((tmp = systrace_findpolicy_wildcard(name)) != NULL)
|
||||
return (tmp);
|
||||
|
||||
tmp = calloc(1, sizeof(struct policy));
|
||||
if (tmp == NULL)
|
||||
return (NULL);
|
||||
|
@ -215,20 +248,23 @@ systrace_newpolicy(const char *emulation, const char *name)
|
|||
TAILQ_INIT(&tmp->filters);
|
||||
TAILQ_INIT(&tmp->prefilters);
|
||||
|
||||
/* Set the default policy to ask */
|
||||
for (i = 0; i < INTERCEPT_MAXSYSCALLNR; i++)
|
||||
tmp->kerneltable[i] = ICPOLICY_ASK;
|
||||
|
||||
return (tmp);
|
||||
}
|
||||
|
||||
void
|
||||
systrace_freepolicy(struct policy *policy)
|
||||
systrace_cleanpolicy(struct policy *policy)
|
||||
{
|
||||
struct filter *filter;
|
||||
struct policy_syscall *pflq;
|
||||
int i;
|
||||
|
||||
if (policy->flags & POLICY_CHANGED) {
|
||||
if (systrace_writepolicy(policy) == -1)
|
||||
fprintf(stderr, "Failed to write policy for %s\n",
|
||||
policy->name);
|
||||
}
|
||||
/* Set the default policy to ask */
|
||||
for (i = 0; i < INTERCEPT_MAXSYSCALLNR; i++)
|
||||
policy->kerneltable[i] = ICPOLICY_ASK;
|
||||
|
||||
while ((filter = TAILQ_FIRST(&policy->prefilters)) != NULL) {
|
||||
TAILQ_REMOVE(&policy->prefilters, filter, policy_next);
|
||||
|
@ -250,6 +286,18 @@ systrace_freepolicy(struct policy *policy)
|
|||
|
||||
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);
|
||||
if (policy->policynr != -1)
|
||||
|
@ -289,7 +337,7 @@ int
|
|||
systrace_modifypolicy(int fd, int policynr, const char *name, short action)
|
||||
{
|
||||
struct policy *policy;
|
||||
int res;
|
||||
int res, nr;
|
||||
|
||||
if ((policy = systrace_findpolnr(policynr)) == NULL)
|
||||
return (-1);
|
||||
|
@ -297,20 +345,29 @@ systrace_modifypolicy(int fd, int policynr, const char *name, short action)
|
|||
res = intercept_modifypolicy(fd, policynr, policy->emulation,
|
||||
name, action);
|
||||
|
||||
/* Remember the kernel policy */
|
||||
if (res != -1 &&
|
||||
(nr = intercept_getsyscallnumber(policy->emulation, name)) != -1)
|
||||
policy->kerneltable[nr] = action;
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts an executable name into the corresponding filename that contains
|
||||
* the policy.
|
||||
*/
|
||||
char *
|
||||
systrace_policyfilename(const char *dirname, const char *name)
|
||||
systrace_policyfilename(const char *pdirname, const char *name)
|
||||
{
|
||||
static char file[2*MAXPATHLEN];
|
||||
const char *p;
|
||||
int i, plen;
|
||||
|
||||
if (strlen(name) + strlen(dirname) + 1 >= sizeof(file))
|
||||
if (strlen(name) + strlen(pdirname) + 1 >= sizeof(file))
|
||||
return (NULL);
|
||||
|
||||
strlcpy(file, dirname, sizeof(file));
|
||||
strlcpy(file, pdirname, sizeof(file));
|
||||
i = strlen(file);
|
||||
file[i++] = '/';
|
||||
plen = i;
|
||||
|
@ -331,7 +388,7 @@ systrace_policyfilename(const char *dirname, const char *name)
|
|||
}
|
||||
|
||||
char *
|
||||
systrace_getpolicyfilename(const char *name)
|
||||
systrace_getpolicyname(const char *name)
|
||||
{
|
||||
char *file = NULL;
|
||||
|
||||
|
@ -354,10 +411,10 @@ systrace_addpolicy(const char *name)
|
|||
{
|
||||
char *file = NULL;
|
||||
|
||||
if ((file = systrace_getpolicyfilename(name)) == NULL)
|
||||
if ((file = systrace_getpolicyname(name)) == NULL)
|
||||
return (-1);
|
||||
|
||||
return (systrace_readpolicy(file));
|
||||
return (systrace_readpolicy(file) != NULL ? 0 : -1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -387,7 +444,7 @@ systrace_templatedir(void)
|
|||
goto error;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
@ -395,7 +452,7 @@ systrace_templatedir(void)
|
|||
if (dir == NULL) {
|
||||
strlcpy(filename, POLICY_PATH, 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);
|
||||
if (dir == NULL)
|
||||
return (-1);
|
||||
|
@ -411,7 +468,7 @@ systrace_templatedir(void)
|
|||
sizeof(filename))
|
||||
goto error;
|
||||
|
||||
if (stat(filename, &sb) == -1 || !(sb.st_mode & S_IFREG))
|
||||
if (stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode))
|
||||
continue;
|
||||
|
||||
template = systrace_readtemplate(filename, NULL, NULL);
|
||||
|
@ -426,6 +483,8 @@ systrace_templatedir(void)
|
|||
|
||||
error:
|
||||
errx(1, "%s: template name too long", __func__);
|
||||
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
struct template *
|
||||
|
@ -507,8 +566,9 @@ systrace_readtemplate(char *filename, struct policy *policy,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Removes trailing whitespace and comments from the input line */
|
||||
|
||||
/*
|
||||
* Removes trailing whitespace and comments from the input line.
|
||||
*/
|
||||
static char *
|
||||
systrace_policyline(char *line)
|
||||
{
|
||||
|
@ -594,7 +654,8 @@ systrace_policyprocess(struct policy *policy, char *p)
|
|||
} else if (filter_parse_simple(rule, &action, &future) == 0)
|
||||
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
|
||||
* system supports it.
|
||||
*/
|
||||
|
@ -628,8 +689,13 @@ systrace_policyprocess(struct policy *policy, char *p)
|
|||
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;
|
||||
struct policy *policy;
|
||||
|
@ -639,7 +705,7 @@ systrace_readpolicy(char *filename)
|
|||
int res = -1;
|
||||
|
||||
if ((fp = fopen(filename, "r")) == NULL)
|
||||
return (-1);
|
||||
return (NULL);
|
||||
|
||||
policy = NULL;
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
|
@ -655,6 +721,8 @@ systrace_readpolicy(char *filename)
|
|||
continue;
|
||||
|
||||
if (!strncasecmp(p, "Policy: ", 8)) {
|
||||
struct timeval now;
|
||||
|
||||
p += 8;
|
||||
name = strsep(&p, ",");
|
||||
if (p == NULL)
|
||||
|
@ -667,6 +735,10 @@ systrace_readpolicy(char *filename)
|
|||
policy = systrace_newpolicy(emulation, name);
|
||||
if (policy == NULL)
|
||||
goto error;
|
||||
|
||||
/* Update access time */
|
||||
gettimeofday(&now, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&now, &policy->ts_last);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -686,13 +758,64 @@ systrace_readpolicy(char *filename)
|
|||
|
||||
out:
|
||||
fclose(fp);
|
||||
return (res);
|
||||
return (res == -1 ? NULL : policy);
|
||||
|
||||
error:
|
||||
fprintf(stderr, "%s:%d: syntax error.\n", filename, linenumber);
|
||||
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
|
||||
systrace_writepolicy(struct policy *policy)
|
||||
{
|
||||
|
@ -702,6 +825,7 @@ systrace_writepolicy(struct policy *policy)
|
|||
char tmpname[2*MAXPATHLEN];
|
||||
char finalname[2*MAXPATHLEN];
|
||||
struct filter *filter;
|
||||
struct timeval now;
|
||||
|
||||
if ((p = systrace_policyfilename(policydir, policy->name)) == NULL)
|
||||
return (-1);
|
||||
|
@ -741,11 +865,33 @@ systrace_writepolicy(struct policy *policy)
|
|||
return (-1);
|
||||
}
|
||||
|
||||
/* Update access time */
|
||||
gettimeofday(&now, NULL);
|
||||
TIMEVAL_TO_TIMESPEC(&now, &policy->ts_last);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -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 $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
|
@ -37,9 +37,13 @@
|
|||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <err.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "intercept.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) \
|
||||
err(1, "%s:%d: intercept failed", __func__, __LINE__)
|
||||
|
@ -425,7 +429,7 @@ systrace_initcb(void)
|
|||
intercept_register_translation("native", "seteuid", 0, &ic_uname);
|
||||
#endif
|
||||
|
||||
#if !(defined(__NetBSD__) && !defined(HAVE_LINUX_FCNTL_H))
|
||||
#if !(defined(__NetBSD__) || !defined(HAVE_LINUX_FCNTL_H))
|
||||
/* 5: open [fswrite] */
|
||||
X(intercept_register_sccb("linux", "open", trans_cb, NULL));
|
||||
tl = intercept_register_translink("linux", "open", 0);
|
||||
|
@ -459,6 +463,11 @@ systrace_initcb(void)
|
|||
alias = systrace_new_alias("linux", "access", "linux", "fsread");
|
||||
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 */
|
||||
X(intercept_register_sccb("linux", "rename", trans_cb, NULL));
|
||||
intercept_register_translink("linux", "rename", 0);
|
||||
|
@ -487,6 +496,20 @@ systrace_initcb(void)
|
|||
alias = systrace_new_alias("linux", "readlink", "linux", "fsread");
|
||||
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] */
|
||||
X(intercept_register_sccb("linux", "stat", trans_cb, NULL));
|
||||
tl = intercept_register_translink("linux", "stat", 0);
|
||||
|
|
|
@ -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 $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#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/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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "intercept.h"
|
||||
#include "systrace.h"
|
||||
|
|
|
@ -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 $ */
|
||||
/*
|
||||
* 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:
|
||||
what = "AF_INET6";
|
||||
break;
|
||||
case AF_IPX:
|
||||
what = "AF_IPX";
|
||||
break;
|
||||
case AF_ISO:
|
||||
what = "AF_ISO";
|
||||
break;
|
||||
case AF_NS:
|
||||
what = "AF_NS";
|
||||
break;
|
||||
case AF_IPX:
|
||||
what = "AF_IPX";
|
||||
break;
|
||||
case AF_IMPLINK:
|
||||
what = "AF_IMPLINK";
|
||||
break;
|
||||
|
@ -287,12 +287,18 @@ print_pidname(char *buf, size_t buflen, struct intercept_translate *tl)
|
|||
|
||||
if (pid != 0) {
|
||||
icpid = intercept_getpid(pid);
|
||||
strlcpy(buf, icpid->name != NULL ? icpid->name
|
||||
: "<unknown>", buflen);
|
||||
if (icpid->name == NULL)
|
||||
intercept_freepid(pid);
|
||||
} else
|
||||
strlcpy(buf, icpid != NULL ? icpid->name : "<unknown>", buflen);
|
||||
} else if (pid == 0) {
|
||||
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);
|
||||
}
|
||||
|
@ -443,6 +449,32 @@ print_fcntlcmd(char *buf, size_t buflen, struct intercept_translate *tl)
|
|||
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
|
||||
print_memprot(char *buf, size_t buflen, struct intercept_translate *tl)
|
||||
{
|
||||
|
@ -625,3 +657,8 @@ struct intercept_translate ic_memprot = {
|
|||
.translate = NULL,
|
||||
.print = print_memprot,
|
||||
};
|
||||
|
||||
struct intercept_translate ic_linux_memprot = {
|
||||
"prot",
|
||||
get_linux_memprot, print_memprot,
|
||||
};
|
||||
|
|
|
@ -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 $
|
||||
.\"
|
||||
.\" Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
|
@ -40,7 +40,7 @@
|
|||
.Sh SYNOPSIS
|
||||
.Nm systrace
|
||||
.Bk -words
|
||||
.Op Fl AaCitUu
|
||||
.Op Fl AaCitUuV
|
||||
.Op Fl c Ar user:group
|
||||
.Op Fl d Ar policydir
|
||||
.Op Fl f Ar file
|
||||
|
@ -104,12 +104,22 @@ root privilege.
|
|||
.It Fl d Ar policydir
|
||||
Specifies an alternative location for the user's directory from
|
||||
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
|
||||
The policies specified in
|
||||
.Ar file
|
||||
are added to the policies that
|
||||
.Nm
|
||||
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
|
||||
Specifies an alternative location for the notification user interface.
|
||||
.It Fl i
|
||||
|
@ -135,6 +145,9 @@ and
|
|||
.Fn access
|
||||
are translated to
|
||||
.Fn fsread .
|
||||
.It Fl V
|
||||
Prints the version number of
|
||||
.Nm .
|
||||
.El
|
||||
.Ss POLICY
|
||||
The policy is specified via the following grammar:
|
||||
|
|
|
@ -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 $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
|
@ -47,6 +47,8 @@
|
|||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <event.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "intercept.h"
|
||||
#include "systrace.h"
|
||||
|
@ -55,6 +57,8 @@
|
|||
#define CRADLE_SERVER "cradle_server"
|
||||
#define CRADLE_UI "cradle_ui"
|
||||
|
||||
#define VERSION "1.6d (NetBSD)"
|
||||
|
||||
pid_t trpid;
|
||||
int trfd;
|
||||
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 noalias = 0; /* Do not do system call aliasing */
|
||||
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 home[MAXPATHLEN]; /* Home directory of user */
|
||||
char username[LOGIN_NAME_MAX]; /* Username: predicate match and expansion */
|
||||
const char *guipath = _PATH_XSYSTRACE; /* Path to GUI executable */
|
||||
char dirpath[MAXPATHLEN];
|
||||
|
||||
static struct event ev_read;
|
||||
static struct event ev_timeout;
|
||||
|
||||
static void child_handler(int);
|
||||
static void log_msg(int, const char *, ...);
|
||||
static void usage(void);
|
||||
static void systrace_read(int, short, void *);
|
||||
static void systrace_timeout(int, short, void *);
|
||||
|
||||
void
|
||||
systrace_parameters(void)
|
||||
|
@ -162,7 +174,7 @@ trans_cb(int fd, pid_t pid, int policynr,
|
|||
const char *binname = NULL;
|
||||
char output[_POSIX2_LINE_MAX];
|
||||
pid_t ppid;
|
||||
int dolog = 0;
|
||||
int done = 0, dolog = 0;
|
||||
|
||||
ipid = NULL; /* XXXGCC -Wuninitialized [dreamcast] */
|
||||
|
||||
|
@ -181,48 +193,63 @@ trans_cb(int fd, pid_t pid, int policynr,
|
|||
ppid = ipid->ppid;
|
||||
|
||||
/* Required to set up replacements */
|
||||
make_output(output, sizeof(output), binname, pid, ppid, policynr,
|
||||
policy->name, policy->nfilters, emulation, name, code,
|
||||
tls, repl);
|
||||
do {
|
||||
make_output(output, sizeof(output), binname, pid, ppid,
|
||||
policynr, policy->name, policy->nfilters, emulation,
|
||||
name, code, tls, repl);
|
||||
|
||||
if ((pflq = systrace_policyflq(policy, emulation, name)) == NULL)
|
||||
errx(1, "%s:%d: no filter queue", __func__, __LINE__);
|
||||
/* Fast-path checking */
|
||||
if ((action = policy->kerneltable[code]) != ICPOLICY_ASK)
|
||||
goto out;
|
||||
|
||||
action = filter_evaluate(tls, pflq, ipid);
|
||||
if (action != ICPOLICY_ASK)
|
||||
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)
|
||||
pflq = systrace_policyflq(policy, emulation, name);
|
||||
if (pflq == 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);
|
||||
}
|
||||
/* 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__);
|
||||
|
||||
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) {
|
||||
action = ICPOLICY_NEVER;
|
||||
|
@ -251,7 +278,7 @@ trans_cb(int fd, pid_t pid, int policynr,
|
|||
|
||||
out:
|
||||
if (dolog)
|
||||
syslog(LOG_WARNING, "%s user: %s, prog: %s",
|
||||
log_msg(LOG_WARNING, "%s user: %s, prog: %s",
|
||||
action < ICPOLICY_NEVER ? "permit" : "deny",
|
||||
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;
|
||||
short action = ICPOLICY_PERMIT;
|
||||
short future;
|
||||
int len, off, dolog = 0;
|
||||
int off, done = 0, dolog = 0;
|
||||
size_t len;
|
||||
|
||||
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)
|
||||
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)
|
||||
dolog = 1;
|
||||
|
||||
if (action != ICPOLICY_ASK)
|
||||
goto out;
|
||||
action = filter_evaluate(NULL, pflq, ipid);
|
||||
|
||||
if (action != ICPOLICY_ASK)
|
||||
goto haveresult;
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
action = ICPOLICY_NEVER;
|
||||
dolog = 1;
|
||||
goto out;
|
||||
goto haveresult;
|
||||
}
|
||||
|
||||
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);
|
||||
return (ICPOLICY_NEVER);
|
||||
}
|
||||
out:
|
||||
haveresult:
|
||||
if (ipid->uflags & SYSCALL_LOG)
|
||||
dolog = 1;
|
||||
|
||||
if (dolog)
|
||||
syslog(LOG_WARNING, "%s user: %s, prog: %s",
|
||||
action < ICPOLICY_NEVER ? "permit" : "deny",
|
||||
ipid->username, output);
|
||||
|
||||
out:
|
||||
return (action);
|
||||
}
|
||||
|
||||
|
@ -414,17 +456,35 @@ child_handler(int sig)
|
|||
}
|
||||
|
||||
while (wait4(-1, &status, WNOHANG, NULL) > 0)
|
||||
;
|
||||
continue;
|
||||
|
||||
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
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: systrace [-AaCitUu] [-c uid:gid] [-d policydir] [-f file]\n"
|
||||
"\t [-g gui] [-p pid] command ...\n");
|
||||
"Usage: %s [-AaCeitUuV] [-c user:group] [-d policydir] "
|
||||
"[-E logfile]\n\t [-f file] [-g gui] [-p pid] command ...\n",
|
||||
getprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -560,6 +620,35 @@ get_uid_gid(const char *argument, uid_t *uid, gid_t *gid)
|
|||
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
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
@ -567,9 +656,9 @@ main(int argc, char **argv)
|
|||
char **args;
|
||||
char *filename = NULL;
|
||||
char *policypath = NULL;
|
||||
struct timeval tv, tv_wait;
|
||||
struct timeval tv;
|
||||
pid_t pidattach = 0;
|
||||
int usex11 = 1, count;
|
||||
int usex11 = 1;
|
||||
int background;
|
||||
int setcredentials = 0;
|
||||
uid_t cr_uid;
|
||||
|
@ -578,11 +667,11 @@ main(int argc, char **argv)
|
|||
cr_uid = 0; /* XXX gcc */
|
||||
cr_gid = 0; /* XXX gcc */
|
||||
|
||||
tv_wait.tv_sec = 60;
|
||||
tv_wait.tv_usec = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, "c:aAituUCd:g:f:p:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "Vc:aAeE:ituUCd:g:f:p:")) != -1) {
|
||||
switch (c) {
|
||||
case 'V':
|
||||
fprintf(stderr, "%s V%s\n", argv[0], VERSION);
|
||||
exit(0);
|
||||
case 'c':
|
||||
setcredentials = 1;
|
||||
if (get_uid_gid(optarg, &cr_uid, &cr_gid) == -1)
|
||||
|
@ -596,6 +685,16 @@ main(int argc, char **argv)
|
|||
case 'd':
|
||||
policypath = optarg;
|
||||
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':
|
||||
if (automatic)
|
||||
usage();
|
||||
|
@ -648,6 +747,10 @@ main(int argc, char **argv)
|
|||
usage();
|
||||
}
|
||||
|
||||
/* Initialize libevent but without kqueue because of systrace fd */
|
||||
setenv("EVENT_NOKQUEUE", "yes", 0);
|
||||
event_init();
|
||||
|
||||
/* Local initalization */
|
||||
systrace_initalias();
|
||||
systrace_initpolicy(filename, policypath);
|
||||
|
@ -696,6 +799,9 @@ main(int argc, char **argv)
|
|||
if (signal(SIGCHLD, child_handler) == SIG_ERR)
|
||||
err(1, "signal");
|
||||
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||
err(1, "signal");
|
||||
|
||||
/* Start the policy gui or cradle if necessary */
|
||||
if (usex11 && (!automatic && !allow)) {
|
||||
if (cradle)
|
||||
|
@ -705,34 +811,22 @@ main(int argc, char **argv)
|
|||
|
||||
}
|
||||
|
||||
/* Loop on requests */
|
||||
count = 0;
|
||||
while (intercept_read(trfd) != -1) {
|
||||
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);
|
||||
/* Register read events */
|
||||
event_set(&ev_read, trfd, EV_READ|EV_PERSIST, systrace_read, NULL);
|
||||
event_add(&ev_read, NULL);
|
||||
|
||||
count = 0;
|
||||
if (timercmp(&now, &tv, >)) {
|
||||
/* Dump policy and cause new time */
|
||||
systrace_dumppolicy();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (userpolicy || automatic) {
|
||||
evtimer_set(&ev_timeout, systrace_timeout, &ev_timeout);
|
||||
timerclear(&tv);
|
||||
tv.tv_sec = SYSTRACE_UPDATETIME;
|
||||
evtimer_add(&ev_timeout, &tv);
|
||||
}
|
||||
|
||||
/* Wait for events */
|
||||
event_dispatch();
|
||||
|
||||
if (userpolicy)
|
||||
systrace_dumppolicy();
|
||||
systrace_dumppolicies(trfd);
|
||||
|
||||
close(trfd);
|
||||
|
||||
|
|
|
@ -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 $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
|
@ -99,9 +99,12 @@ struct policy {
|
|||
const char *name;
|
||||
char emulation[16];
|
||||
|
||||
struct timespec ts_last;
|
||||
|
||||
SPLAY_HEAD(syscalltree, policy_syscall) pflqs;
|
||||
|
||||
int policynr;
|
||||
short kerneltable[INTERCEPT_MAXSYSCALLNR];
|
||||
int flags;
|
||||
|
||||
struct filterq filters;
|
||||
|
@ -132,6 +135,8 @@ TAILQ_HEAD(tmplqueue, template);
|
|||
#define SYSCALL_LOG 0x04 /* Log this system call */
|
||||
#define PROCESS_PROMPT 0x08 /* Prompt but nothing else */
|
||||
|
||||
#define SYSTRACE_UPDATETIME 30 /* update policies every 30 seconds */
|
||||
|
||||
void systrace_parameters(void);
|
||||
int systrace_initpolicy(char *, char *);
|
||||
void systrace_setupdir(char *);
|
||||
|
@ -139,20 +144,25 @@ struct template *systrace_readtemplate(char *, struct policy *,
|
|||
struct template *);
|
||||
void systrace_initcb(void);
|
||||
struct policy *systrace_newpolicy(const char *, const char *);
|
||||
void systrace_cleanpolicy(struct policy *);
|
||||
void systrace_freepolicy(struct policy *);
|
||||
int systrace_newpolicynr(int, struct policy *);
|
||||
int systrace_modifypolicy(int, int, const char *, short);
|
||||
struct policy *systrace_findpolicy(const char *);
|
||||
struct policy *systrace_findpolicy_wildcard(const char *);
|
||||
struct policy *systrace_findpolnr(int);
|
||||
int systrace_dumppolicy(void);
|
||||
int systrace_readpolicy(char *);
|
||||
int systrace_dumppolicies(int);
|
||||
int systrace_updatepolicies(int);
|
||||
struct policy *systrace_readpolicy(const char *);
|
||||
char *systrace_getpolicyfilename(const char *);
|
||||
int systrace_addpolicy(const char *);
|
||||
int systrace_updatepolicy(int, struct policy *);
|
||||
struct filterq *systrace_policyflq(struct policy *, const char *, const char *);
|
||||
char *systrace_getpolicyname(const char *);
|
||||
|
||||
int systrace_error_translate(char *);
|
||||
|
||||
#define SYSTRACE_MAXALIAS 5
|
||||
#define SYSTRACE_MAXALIAS 10
|
||||
|
||||
struct systrace_alias {
|
||||
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_fcntlcmd;
|
||||
extern struct intercept_translate ic_memprot;
|
||||
|
||||
#ifdef notyet
|
||||
extern struct intercept_translate ic_linux_memprot;
|
||||
extern struct intercept_translate ic_linux_oflags;
|
||||
#endif
|
||||
|
||||
int requestor_start(const char *, int);
|
||||
|
||||
|
|
Loading…
Reference in New Issue