diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2002-10-16 15:01:09 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2002-10-16 15:01:09 +0000 |
commit | 53b5fc5bded7381e9b2c1867c9ac08b7d77b944f (patch) | |
tree | 27171f6bdd77dd43fb3237b94729e02800c7fb4d /bin | |
parent | e0a16d26d6e3fd1b83b87e2e312caed5b59a3258 (diff) |
support for privilege elevation.
with privilege elevation no suid or sgid binaries are necessary any
longer. Applications can be executed completely
unprivileged. Systrace raises the privileges for a single system call
depending on the configured policy.
Idea from discussions with Perry Metzger, Dug Song and Marcus Watts.
from provos
Diffstat (limited to 'bin')
-rw-r--r-- | bin/systrace/Makefile | 3 | ||||
-rw-r--r-- | bin/systrace/filter.c | 8 | ||||
-rw-r--r-- | bin/systrace/intercept.c | 60 | ||||
-rw-r--r-- | bin/systrace/intercept.h | 20 | ||||
-rw-r--r-- | bin/systrace/lex.l | 4 | ||||
-rw-r--r-- | bin/systrace/openbsd-syscalls.c | 23 | ||||
-rw-r--r-- | bin/systrace/parse.y | 113 | ||||
-rw-r--r-- | bin/systrace/systrace.1 | 81 | ||||
-rw-r--r-- | bin/systrace/systrace.c | 40 | ||||
-rw-r--r-- | bin/systrace/systrace.h | 4 |
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); |