summaryrefslogtreecommitdiff
path: root/bin/systrace
diff options
context:
space:
mode:
Diffstat (limited to 'bin/systrace')
-rw-r--r--bin/systrace/Makefile3
-rw-r--r--bin/systrace/filter.c8
-rw-r--r--bin/systrace/intercept.c60
-rw-r--r--bin/systrace/intercept.h20
-rw-r--r--bin/systrace/lex.l4
-rw-r--r--bin/systrace/openbsd-syscalls.c23
-rw-r--r--bin/systrace/parse.y113
-rw-r--r--bin/systrace/systrace.181
-rw-r--r--bin/systrace/systrace.c40
-rw-r--r--bin/systrace/systrace.h4
10 files changed, 270 insertions, 86 deletions
diff --git a/bin/systrace/Makefile b/bin/systrace/Makefile
index 91c0b1e805e..6be464cda25 100644
--- a/bin/systrace/Makefile
+++ b/bin/systrace/Makefile
@@ -1,6 +1,7 @@
-# $OpenBSD: Makefile,v 1.7 2002/07/19 14:38:57 itojun Exp $
+# $OpenBSD: Makefile,v 1.8 2002/10/16 15:01:08 itojun Exp $
PROG= systrace
+BINDIR?= /bin
CFLAGS+=-I.
CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith \
-Wno-uninitialized -Werror
diff --git a/bin/systrace/filter.c b/bin/systrace/filter.c
index 8069ec29ca9..d402d97a749 100644
--- a/bin/systrace/filter.c
+++ b/bin/systrace/filter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: filter.c,v 1.20 2002/10/16 14:41:52 itojun Exp $ */
+/* $OpenBSD: filter.c,v 1.21 2002/10/16 15:01:08 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -171,6 +171,10 @@ filter_evaluate(struct intercept_tlq *tls, struct filterq *fls,
if (action == ICPOLICY_NEVER)
action = filter->match_error;
icpid->uflags = filter->match_flags;
+
+ /* Policy requests privilege elevation */
+ if (filter->elevate.e_flags)
+ icpid->elevate = &filter->elevate;
return (action);
}
@@ -405,7 +409,7 @@ filter_quickpredicate(struct filter *filter)
if (!pdc->p_flags)
return (1);
- intercept_setpid(&icpid);
+ intercept_setpid(&icpid, getuid(), getgid());
if (!filter_predicate(&icpid, pdc))
return (0);
diff --git a/bin/systrace/intercept.c b/bin/systrace/intercept.c
index ed5ad4882c4..34070400b67 100644
--- a/bin/systrace/intercept.c
+++ b/bin/systrace/intercept.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intercept.c,v 1.32 2002/10/09 03:52:10 itojun Exp $ */
+/* $OpenBSD: intercept.c,v 1.33 2002/10/16 15:01:08 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -232,22 +232,27 @@ sigusr1_handler(int signum)
}
void
-intercept_setpid(struct intercept_pid *icpid)
+intercept_setpid(struct intercept_pid *icpid, uid_t uid, gid_t gid)
{
struct passwd *pw;
- icpid->uid = getuid();
- icpid->gid = getgid();
+ icpid->uid = uid;
+ icpid->gid = gid;
if (getcwd(icpid->cwd, sizeof(icpid->cwd)) == NULL)
err(1, "getcwd");
- if ((pw = getpwuid(icpid->uid)) == NULL)
- err(1, "getpwuid");
- strlcpy(icpid->username, pw->pw_name, sizeof(icpid->username));
- strlcpy(icpid->home, pw->pw_dir, sizeof(icpid->home));
+ if ((pw = getpwuid(icpid->uid)) == NULL) {
+ snprintf(icpid->username, sizeof(icpid->username),
+ "unknown(%d)", icpid->uid);
+ strlcpy(icpid->home, "/var/empty", sizeof(icpid->home));
+ } else {
+ strlcpy(icpid->username, pw->pw_name, sizeof(icpid->username));
+ strlcpy(icpid->home, pw->pw_dir, sizeof(icpid->home));
+ }
}
pid_t
-intercept_run(int bg, int fd, char *path, char *const argv[])
+intercept_run(int bg, int fd, uid_t uid, gid_t gid,
+ char *path, char *const argv[])
{
struct intercept_pid *icpid;
sigset_t none, set, oset;
@@ -301,6 +306,19 @@ intercept_run(int bg, int fd, char *path, char *const argv[])
if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1)
err(1, "sigprocmask");
+ /* Change to different user */
+ if (uid || gid) {
+ if (setgroups(1, &gid) == -1)
+ err(1, "setgroups");
+ if (setgid(gid) == -1)
+ err(1, "setgid");
+ if (setegid(gid) == -1)
+ err(1, "setegid");
+ if (setuid(uid) == -1)
+ err(1, "setuid");
+ if (seteuid(uid) == -1)
+ err(1, "seteuid");
+ }
execvp(path, argv);
/* Error */
@@ -314,7 +332,11 @@ intercept_run(int bg, int fd, char *path, char *const argv[])
err(1, "intercept_getpid");
/* Set up user related information */
- intercept_setpid(icpid);
+ if (!uid && !gid) {
+ uid = getuid();
+ gid = getgid();
+ }
+ intercept_setpid(icpid, uid, gid);
/* Setup done, restore signal handling state */
if (signal(SIGUSR1, ohandler) == SIG_ERR) {
@@ -658,20 +680,20 @@ intercept_syscall(int fd, pid_t pid, u_int16_t seqnr, int policynr,
{
short action, flags = 0;
struct intercept_syscall *sc;
+ struct intercept_pid *icpid;
+ struct elevate *elevate = NULL;
int error = 0;
action = ICPOLICY_PERMIT;
flags = 0;
+ icpid = intercept_getpid(pid);
+
/* Special handling for the exec call */
if (!strcmp(name, "execve")) {
- struct intercept_pid *icpid;
void *addr;
char *argname;
- if ((icpid = intercept_getpid(pid)) == NULL)
- err(1, "intercept_getpid");
-
icpid->execve_code = code;
icpid->policynr = policynr;
@@ -691,6 +713,8 @@ intercept_syscall(int fd, pid_t pid, u_int16_t seqnr, int policynr,
flags = ICFLAGS_RESULT;
}
+ icpid->elevate = NULL;
+
sc = intercept_sccb_find(emulation, name);
if (sc != NULL) {
struct intercept_translate *tl;
@@ -714,10 +738,12 @@ intercept_syscall(int fd, pid_t pid, u_int16_t seqnr, int policynr,
if (action > 0) {
error = action;
action = ICPOLICY_NEVER;
- }
+ } else
+ elevate = icpid->elevate;
+
/* Resume execution of the process */
- intercept.answer(fd, pid, seqnr, action, error, flags);
+ intercept.answer(fd, pid, seqnr, action, error, flags, elevate);
}
void
@@ -747,7 +773,7 @@ intercept_syscall_result(int fd, pid_t pid, u_int16_t seqnr, int policynr,
out:
/* Resume execution of the process */
- intercept.answer(fd, pid, seqnr, 0, 0, 0);
+ intercept.answer(fd, pid, seqnr, 0, 0, 0, NULL);
}
int
diff --git a/bin/systrace/intercept.h b/bin/systrace/intercept.h
index f5987f10d7c..0edf0cfa1c8 100644
--- a/bin/systrace/intercept.h
+++ b/bin/systrace/intercept.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intercept.h,v 1.12 2002/10/09 03:52:10 itojun Exp $ */
+/* $OpenBSD: intercept.h,v 1.13 2002/10/16 15:01:08 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -36,6 +36,7 @@
struct intercept_pid;
struct intercept_replace;
+struct elevate;
struct intercept_system {
char *name;
@@ -50,7 +51,8 @@ struct intercept_system {
int (*restcwd)(int);
int (*io)(int, pid_t, int, void *, u_char *, size_t);
int (*getarg)(int, void *, int, void **);
- int (*answer)(int, pid_t, u_int32_t, short, int, short);
+ int (*answer)(int, pid_t, u_int32_t, short, int, short,
+ struct elevate *);
int (*newpolicy)(int);
int (*assignpolicy)(int, pid_t, int);
int (*policy)(int, int, int, short);
@@ -73,6 +75,15 @@ struct intercept_system {
#define ICFLAGS_RESULT 1
+/* Privilege elevation */
+struct elevate {
+#define ELEVATE_UID 0x01
+#define ELEVATE_GID 0x02
+ int e_flags;
+ uid_t e_uid;
+ gid_t e_gid;
+};
+
struct intercept_pid {
SPLAY_ENTRY(intercept_pid) next;
pid_t pid;
@@ -94,6 +105,7 @@ struct intercept_pid {
void *data;
int uflags; /* Flags that can be used by external application */
+ struct elevate *elevate; /* privilege elevation request */
};
#define INTERCEPT_MAXSYSCALLARGS 10
@@ -123,7 +135,7 @@ struct intercept_replace {
TAILQ_HEAD(intercept_tlq, intercept_translate);
int intercept_init(void);
-pid_t intercept_run(int, int, char *, char * const *);
+pid_t intercept_run(int, int, uid_t, gid_t, char *, char * const *);
int intercept_open(void);
int intercept_attach(int, pid_t);
int intercept_attachpid(int, pid_t, char *);
@@ -176,6 +188,6 @@ void intercept_syscall(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 *);
void intercept_ugid(struct intercept_pid *, uid_t, gid_t);
-void intercept_setpid(struct intercept_pid *);
+void intercept_setpid(struct intercept_pid *, uid_t, gid_t);
#endif /* _INTERCEPT_H_ */
diff --git a/bin/systrace/lex.l b/bin/systrace/lex.l
index 6370fd373a0..1a1cff1e780 100644
--- a/bin/systrace/lex.l
+++ b/bin/systrace/lex.l
@@ -1,4 +1,4 @@
-/* $OpenBSD: lex.l,v 1.10 2002/10/09 03:52:10 itojun Exp $ */
+/* $OpenBSD: lex.l,v 1.11 2002/10/16 15:01:08 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -89,6 +89,8 @@ true { return TRUE; }
if { return IF; }
user { return USER; }
group { return GROUP; }
+as { return AS; }
+":" { return COLON; }
"," { return COMMA; }
"=" { return EQUAL; }
"!=" { return NEQUAL; }
diff --git a/bin/systrace/openbsd-syscalls.c b/bin/systrace/openbsd-syscalls.c
index b2eb36eae64..f70bb85286d 100644
--- a/bin/systrace/openbsd-syscalls.c
+++ b/bin/systrace/openbsd-syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: openbsd-syscalls.c,v 1.14 2002/10/09 03:52:10 itojun Exp $ */
+/* $OpenBSD: openbsd-syscalls.c,v 1.15 2002/10/16 15:01:08 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -127,7 +127,8 @@ static int obsd_syscall_number(const char *, const char *);
static short obsd_translate_policy(short);
static short obsd_translate_flags(short);
static int obsd_translate_errno(int);
-static int obsd_answer(int, pid_t, u_int32_t, short, int, short);
+static int obsd_answer(int, pid_t, u_int32_t, short, int, short,
+ struct elevate *);
static int obsd_newpolicy(int);
static int obsd_assignpolicy(int, pid_t, int);
static int obsd_modifypolicy(int, int, int, short);
@@ -352,16 +353,28 @@ obsd_translate_errno(int nerrno)
static int
obsd_answer(int fd, pid_t pid, u_int32_t seqnr, short policy, int nerrno,
- short flags)
+ short flags, struct elevate *elevate)
{
struct systrace_answer ans;
+ memset(&ans, 0, sizeof(ans));
ans.stra_pid = pid;
ans.stra_seqnr = seqnr;
ans.stra_policy = obsd_translate_policy(policy);
ans.stra_flags = obsd_translate_flags(flags);
ans.stra_error = obsd_translate_errno(nerrno);
+ if (elevate != NULL) {
+ if (elevate->e_flags & ELEVATE_UID) {
+ ans.stra_flags |= SYSTR_FLAGS_SETEUID;
+ ans.stra_seteuid = elevate->e_uid;
+ }
+ if (elevate->e_flags & ELEVATE_GID) {
+ ans.stra_flags |= SYSTR_FLAGS_SETEGID;
+ ans.stra_setegid = elevate->e_gid;
+ }
+ }
+
if (ioctl(fd, STRIOCANSWER, &ans) == -1)
return (-1);
@@ -591,7 +604,7 @@ obsd_read(int fd)
break;
}
- if (obsd_answer(fd, pid, seqnr, 0, 0, 0) == -1)
+ if (obsd_answer(fd, pid, seqnr, 0, 0, 0, NULL) == -1)
err(1, "%s:%d: answer", __func__, __LINE__);
break;
@@ -602,7 +615,7 @@ obsd_read(int fd)
intercept_ugid(icpid, msg_ugid->uid, msg_ugid->uid);
- if (obsd_answer(fd, pid, seqnr, 0, 0, 0) == -1)
+ if (obsd_answer(fd, pid, seqnr, 0, 0, 0, NULL) == -1)
err(1, "%s:%d: answer", __func__, __LINE__);
break;
}
diff --git a/bin/systrace/parse.y b/bin/systrace/parse.y
index b18c3204293..c7fcd90aeb5 100644
--- a/bin/systrace/parse.y
+++ b/bin/systrace/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.10 2002/10/09 03:52:10 itojun Exp $ */
+/* $OpenBSD: parse.y,v 1.11 2002/10/16 15:01:08 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -61,11 +61,13 @@ int errors = 0;
struct filter *myfilter;
extern char *mystring;
extern int myoff;
+extern int iamroot;
%}
%token AND OR NOT LBRACE RBRACE LSQBRACE RSQBRACE THEN MATCH PERMIT DENY
-%token EQ NEQ TRUE SUB NSUB INPATH LOG COMMA IF USER GROUP EQUAL NEQUAL
+%token EQ NEQ TRUE SUB NSUB INPATH LOG COMMA IF USER GROUP EQUAL NEQUAL AS
+%token COLON
%token <string> STRING
%token <string> CMDSTRING
%token <number> NUMBER
@@ -74,18 +76,24 @@ extern int myoff;
%type <action> action
%type <number> typeoff
%type <number> logcode
+%type <uid> uid
+%type <gid> gid
%type <string> errorcode
%type <predicate> predicate
+%type <elevate> elevate;
%union {
int number;
char *string;
short action;
struct logic *logic;
struct predicate predicate;
+ struct elevate elevate;
+ uid_t uid;
+ gid_t gid;
}
%%
-fullexpression : expression THEN action errorcode logcode predicate
+fullexpression : expression THEN action errorcode logcode elevate predicate
{
int flags = 0, errorcode = SYSTRACE_EPERM;
@@ -124,7 +132,8 @@ fullexpression : expression THEN action errorcode logcode predicate
myfilter->match_action = $3;
myfilter->match_error = errorcode;
myfilter->match_flags = flags;
- myfilter->match_predicate = $6;
+ myfilter->match_predicate = $7;
+ myfilter->elevate = $6;
}
;
@@ -148,56 +157,91 @@ logcode : /* Empty */
}
;
-predicate : /* Empty */
+
+uid: STRING
{
- memset(&$$, 0, sizeof($$));
+ struct passwd *pw;
+ if ((pw = getpwnam($1)) == NULL) {
+ yyerror("Unknown user %s", $1);
+ break;
+ }
+
+ $$ = pw->pw_uid;
}
- | COMMA IF USER EQUAL STRING
+
+gid: STRING
{
- struct passwd *pw;
+ struct group *gr;
+ if ((gr = getgrnam($1)) == NULL) {
+ yyerror("Unknown group %s", $1);
+ break;
+ }
+ $$ = gr->gr_gid;
+}
+
+elevate: /* Empty */
+{
memset(&$$, 0, sizeof($$));
- if ((pw = getpwnam($5)) == NULL) {
- yyerror("Unknown user %s", $5);
+}
+ | AS uid
+{
+ if (!iamroot) {
+ yyerror("Privilege elevation not allowed.");
break;
}
- $$.p_uid = pw->pw_uid;
- $$.p_flags = PREDIC_UID;
+
+ $$.e_flags = ELEVATE_UID;
+ $$.e_uid = $2;
}
- | COMMA IF USER NEQUAL STRING
+ | AS uid COLON gid
{
- struct passwd *pw;
+ if (!iamroot) {
+ yyerror("Privilege elevation not allowed.");
+ break;
+ }
- memset(&$$, 0, sizeof($$));
- if ((pw = getpwnam($5)) == NULL) {
- yyerror("Unknown user %s", $5);
+ $$.e_flags = ELEVATE_UID|ELEVATE_GID;
+ $$.e_uid = $2;
+ $$.e_gid = $4;
+}
+ | AS COLON gid
+{
+ if (!iamroot) {
+ yyerror("Privilege elevation not allowed.");
break;
}
- $$.p_uid = pw->pw_uid;
+
+ $$.e_flags = ELEVATE_GID;
+ $$.e_gid = $3;
+}
+
+predicate : /* Empty */
+{
+ memset(&$$, 0, sizeof($$));
+}
+ | COMMA IF USER EQUAL uid
+{
+ memset(&$$, 0, sizeof($$));
+ $$.p_uid = $5;
+ $$.p_flags = PREDIC_UID;
+}
+ | COMMA IF USER NEQUAL uid
+{
+ memset(&$$, 0, sizeof($$));
+ $$.p_uid = $5;
$$.p_flags = PREDIC_UID | PREDIC_NEGATIVE;
}
- | COMMA IF GROUP EQUAL STRING
+ | COMMA IF GROUP EQUAL gid
{
- struct group *gr;
-
memset(&$$, 0, sizeof($$));
- if ((gr = getgrnam($5)) == NULL) {
- yyerror("Unknown group %s", $5);
- break;
- }
- $$.p_gid = gr->gr_gid;
+ $$.p_gid = $5;
$$.p_flags = PREDIC_GID;
}
- | COMMA IF GROUP NEQUAL STRING
+ | COMMA IF GROUP NEQUAL gid
{
- struct group *gr;
-
memset(&$$, 0, sizeof($$));
- if ((gr = getgrnam($5)) == NULL) {
- yyerror("Unknown group %s", $5);
- break;
- }
- $$.p_gid = gr->gr_gid;
+ $$.p_gid = $5;
$$.p_flags = PREDIC_GID | PREDIC_NEGATIVE;
}
@@ -361,7 +405,6 @@ struct logic *
parse_newsymbol(char *type, int typeoff, char *data)
{
struct logic *node;
- int iamroot = getuid() == 0;
node = calloc(1, sizeof(struct logic));
diff --git a/bin/systrace/systrace.1 b/bin/systrace/systrace.1
index 15d940ef9e6..8c34e3297c7 100644
--- a/bin/systrace/systrace.1
+++ b/bin/systrace/systrace.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: systrace.1,v 1.27 2002/08/05 23:27:53 provos Exp $
+.\" $OpenBSD: systrace.1,v 1.28 2002/10/16 15:01:08 itojun Exp $
.\"
.\" Copyright 2002 Niels Provos <provos@citi.umich.edu>
.\" All rights reserved.
@@ -42,21 +42,25 @@
.Op Fl d Ar policydir
.Op Fl g Ar gui
.Op Fl f Ar file
+.Op Fl c Ar uid:gid
.Op Fl p Ar pid
.Ar command ...
.Sh DESCRIPTION
The
.Nm
utility monitors and controls an application's access to the system by
-enforcing access policies for system calls. The
+enforcing access policies for system calls.
+The
.Nm
utility might be used to trace an untrusted application's access to
-the system. Alternatively, it might be used to protect the system
+the system.
+Alternatively, it might be used to protect the system
from software bugs (such as buffer overflows) by constraining a
daemon's access to the system.
.Pp
The access policy can be generated interactively or obtained from a
-policy file. Operations not covered by the policy raise an alarm and
+policy file.
+Operations not covered by the policy raise an alarm and
allow an user to refine the currently configured policy.
.Pp
The options are as follows:
@@ -70,9 +74,10 @@ Automatically generate a policy that allows every operation the
application executes.
The created policy functions as a base that can be refined.
.It Fl u
-Do not perform aliasing on system call names. Aliasing is enabled
-by default to group similar system calls into a single compound
-name. For example, system calls that read from the file system
+Do not perform aliasing on system call names.
+Aliasing is enabled by default to group similar system calls into a
+single compound name.
+For example, system calls that read from the file system
like
.Fn lstat
and
@@ -90,6 +95,14 @@ Specifies an alternative location for the user's directory from
which policies are loaded and to which changed policies are stored.
.It Fl g Ar gui
Specifies an alternative location for the notification user interface.
+.It Fl c Ar uid:gid
+Specifies the
+.Va uid
+and
+.Va gid
+that the monitored application should be executed with.
+This is useful in conjunction with privilege elevation and requires
+root privileges.
.It Fl f Ar file
The policies specified in
.Ar file
@@ -129,7 +142,8 @@ is used to return an
.Xr errno 2
value to the system call when using a
.Va deny
-action. The values
+action.
+The values
.Do
inherit
.Dc
@@ -198,6 +212,43 @@ Predicates have the following format:
.Pp
A rule is added to the configured policy only if its predicate
evaluates to true.
+.Sh PRIVILEGE ELEVATION
+With
+.Nm
+it is possible to remove setuid or setgid binaries, and use the
+privilege elevation feature instead.
+Single system calls can be executed with higher privileges if
+specified by the policy.
+For example,
+.Bd -literal -offset 4
+native-bind: sockaddr eq "inet-[0.0.0.0]:22" then permit as root
+.Ed
+.Pp
+allows an unprivileged application to bind to a reserved port.
+Privilege elevation requires that the
+.Nm
+process is executed as root.
+.Pp
+The following statements can be appended after the
+.Va permit
+in a policy to elevate the privileges for the matching system call:
+.Bd -literal -offset 4
+as user
+as user:group
+as group
+.Ed
+.Pp
+The effective
+.Va uid
+and
+.Va gid
+are elevated only for the duration of the system call, and are restored
+to the old values afterwards.
+The only exception are the
+.Va seteuid
+or
+.Va setegid
+system calls.
.Sh FILES
.Bl -tag -width xHOME/xsystrace -compact
.It Pa /dev/systrace
@@ -214,15 +265,15 @@ policy might look as follows:
.Bd -literal -offset AAA
Policy: /bin/ls, Emulation: native
[...]
- native-open: filename eq "$HOME" and oflags sub "ro" then permit
- native-fchdir: permit
+ native-fsread: filename eq "$HOME" then permit
+ native-fchdir: permit
[...]
- native-open: filename eq "/tmp" and oflags sub "ro" then permit
- native-stat: permit
- native-open: filename match "$HOME/*" and oflags sub "ro" then permit
- native-open: filename eq "/etc/pwd.db" and oflags sub "ro" then permit
+ native-fsread: filename eq "/tmp" then permit
+ native-stat: permit
+ native-fsread: filename match "$HOME/*" then permit
+ native-fsread: filename eq "/etc/pwd.db" then permit
[...]
- native-open: filename eq "/etc" then deny[eperm], if group != wheel
+ native-fsread: filename eq "/etc" then deny[eperm], if group != wheel
.Ed
.Sh SEE ALSO
.Xr systrace 4
diff --git a/bin/systrace/systrace.c b/bin/systrace/systrace.c
index 8913ce7fe79..5d52cb1c06e 100644
--- a/bin/systrace/systrace.c
+++ b/bin/systrace/systrace.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: systrace.c,v 1.37 2002/10/09 03:52:10 itojun Exp $ */
+/* $OpenBSD: systrace.c,v 1.38 2002/10/16 15:01:08 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -392,7 +392,8 @@ static void
usage(void)
{
fprintf(stderr,
- "Usage: systrace [-aituU] [-d poldir] [-g gui] [-f policy] [-p pid] command ...\n");
+ "Usage: systrace [-aAituU] [-d poldir] [-g gui] [-f policy]\n"
+ "\t [-c uid:gid] [-p pid] command ...\n");
exit(1);
}
@@ -450,21 +451,38 @@ main(int argc, char **argv)
char **args;
char *filename = NULL;
char *policypath = NULL;
- char *guipath = _PATH_XSYSTRACE;
+ char *guipath = _PATH_XSYSTRACE, *p;
struct timeval tv, tv_wait = {60, 0};
pid_t pidattach = 0;
int usex11 = 1, count;
int background;
+ int setcredentials = 0;
+ uid_t cr_uid;
+ gid_t cr_gid;
- while ((c = getopt(argc, argv, "aAituUd:g:f:p:")) != -1) {
+ while ((c = getopt(argc, argv, "c:aAituUd:g:f:p:")) != -1) {
switch (c) {
+ case 'c':
+ p = strsep(&optarg, ":");
+ if (optarg == NULL || *optarg == '\0')
+ usage();
+ setcredentials = 1;
+ cr_uid = atoi(p);
+ cr_gid = atoi(optarg);
+
+ if (cr_uid <= 0 || cr_gid <= 0)
+ usage();
case 'a':
+ if (allow)
+ usage();
automatic = 1;
break;
case 'd':
policypath = optarg;
break;
case 'A':
+ if (automatic)
+ usage();
allow = 1;
break;
case 'u':
@@ -480,6 +498,8 @@ main(int argc, char **argv)
filename = optarg;
break;
case 'p':
+ if (setcredentials)
+ usage();
if ((pidattach = atoi(optarg)) == 0) {
warnx("bad pid: %s", optarg);
usage();
@@ -504,6 +524,11 @@ main(int argc, char **argv)
systrace_parameters();
+ if (setcredentials && !iamroot) {
+ fprintf(stderr, "Need to be root to change credentials.\n");
+ usage();
+ }
+
/* Local initalization */
systrace_initalias();
systrace_initpolicy(filename, policypath);
@@ -524,7 +549,12 @@ main(int argc, char **argv)
args[i] = argv[i];
args[i] = NULL;
- trpid = intercept_run(background, trfd, args[0], args);
+ if (setcredentials)
+ trpid = intercept_run(background, trfd,
+ cr_uid, cr_gid, args[0], args);
+ else
+ trpid = intercept_run(background, trfd, 0, 0,
+ args[0], args);
if (trpid == -1)
err(1, "fork");
diff --git a/bin/systrace/systrace.h b/bin/systrace/systrace.h
index bba1ae1d710..7d4fc199130 100644
--- a/bin/systrace/systrace.h
+++ b/bin/systrace/systrace.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: systrace.h,v 1.17 2002/10/16 14:43:33 itojun Exp $ */
+/* $OpenBSD: systrace.h,v 1.18 2002/10/16 15:01:08 itojun Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -72,6 +72,8 @@ struct filter {
uid_t p_uid;
gid_t p_gid;
} match_predicate;
+
+ struct elevate elevate;
};
TAILQ_HEAD(filterq, filter);