From: Todd C. Miller Date: Fri, 1 Oct 2004 18:30:20 +0000 (+0000) Subject: No need to include syscall.h, use 1024 as the max # of entries (the X-Git-Tag: SUDO_1_7_0~903 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e173a07c85e9f36d5965d5d0d61ed250efe60d0e;p=sudo No need to include syscall.h, use 1024 as the max # of entries (the max that systrace(4) allows). Only need to use SYSTR_POLICY_ASSIGN once Change check_syscall() -> find_handler() and have it return the handler instead of just running it. We need this since handler now have two parts: one part that generates and answer and another that gets called after the answer is accepted (to do logging). Add some missing check_exec for emul execv --- diff --git a/mon_systrace.c b/mon_systrace.c index 83059c2c2..fd1ee143c 100644 --- a/mon_systrace.c +++ b/mon_systrace.c @@ -17,17 +17,7 @@ #include "config.h" #include -#include #include -#ifdef HAVE_DEV_SYSTRACE_H -# include -#else -# ifdef HAVE_SYS_SYSTRACE_H -# include -# else -# include -# endif -#endif #include #include #include @@ -42,6 +32,19 @@ #else # include "emul/err.h" #endif /* HAVE_ERR_H */ +#ifdef HAVE_DEV_SYSTRACE_H +# include +#else +# ifdef HAVE_SYS_SYSTRACE_H +# include +# else +# ifdef HAVE_LINUX_SYSTRACE_H +# include +# else +# include +# endif +# endif +#endif #include "sudo.h" #include "trace_systrace.h" @@ -100,12 +103,13 @@ void systrace_attach(pid) pid_t pid; { + schandler_t handler; struct systrace_answer ans; struct str_message msg; sigaction_t sa, osa; sigset_t set, oset; ssize_t nread; - int fd; + int fd, cookie; if ((fd = systrace_open()) == -1) err(1, "unable to open systrace"); @@ -144,8 +148,10 @@ systrace_attach(pid) /* reset signal state for tracer */ if (sigaction(SIGUSR1, &osa, NULL) != 0 || - sigprocmask(SIG_SETMASK, &oset, NULL) != 0) + sigprocmask(SIG_SETMASK, &oset, NULL) != 0) { + warn("unable to setup signals for %s", user_cmnd); goto fail; + } /* become a daemon */ if (setsid() == -1) { @@ -165,12 +171,15 @@ systrace_attach(pid) (void) kill(pid, SIGUSR1); _exit(0); } + warn("unable to systrace %s", user_cmnd); goto fail; } new_child(-1, pid); - if (set_policy(fd, children.first) != 0) + if (set_policy(fd, children.first) != 0) { + warn("failed to set policy for %s", user_cmnd); goto fail; + } if (kill(pid, SIGUSR1) != 0) { warn("unable to wake up sleeping child"); @@ -201,25 +210,33 @@ systrace_attach(pid) case SYSTR_MSG_UGID: /* uid/gid change */ -#ifdef DEBUG - warnx("new uid %d for %d", msg.msg_data.msg_ugid.uid, msg.msg_pid); -#endif - update_child(msg.msg_pid, msg.msg_data.msg_ugid.uid); memset(&ans, 0, sizeof(ans)); ans.stra_pid = msg.msg_pid; ans.stra_seqnr = msg.msg_seqnr; ans.stra_policy = SYSTR_POLICY_PERMIT; - if ((ioctl(fd, STRIOCANSWER, &ans)) == -1) - goto fail; + if ((ioctl(fd, STRIOCANSWER, &ans)) == 0) + update_child(msg.msg_pid, msg.msg_data.msg_ugid.uid); break; case SYSTR_MSG_ASK: memset(&ans, 0, sizeof(ans)); ans.stra_pid = msg.msg_pid; ans.stra_seqnr = msg.msg_seqnr; - check_syscall(fd, &msg.msg_data.msg_ask, &ans); - if ((ioctl(fd, STRIOCANSWER, &ans)) == -1) - goto fail; + ans.stra_policy = SYSTR_POLICY_PERMIT; + handler = find_handler(msg.msg_pid, msg.msg_data.msg_ask.code); + if (handler != NULL) { + /* + * handler is run twice, once before we answer and once + * after. We only want to log attempts when our answer + * is accepted; otherwise we can get dupes. + */ + cookie = handler(fd, msg.msg_pid, &msg.msg_data.msg_ask, -1, + &ans.stra_policy, &ans.stra_error); + if (ioctl(fd, STRIOCANSWER, &ans) == 0) + handler(fd, msg.msg_pid, &msg.msg_data.msg_ask, + cookie, &ans.stra_policy, &ans.stra_error); + } else + (void) ioctl(fd, STRIOCANSWER, &ans); break; case SYSTR_MSG_EMUL: @@ -234,12 +251,13 @@ systrace_attach(pid) msg.msg_data.msg_emul.emul); ans.stra_policy = SYSTR_POLICY_NEVER; } - if ((ioctl(fd, STRIOCANSWER, &ans)) == -1) - goto fail; + (void) ioctl(fd, STRIOCANSWER, &ans); break; +#ifdef SYSTR_MSG_POLICYFREE case SYSTR_MSG_POLICYFREE: break; +#endif default: #ifdef SUDO_DEVEL @@ -249,14 +267,12 @@ systrace_attach(pid) ans.stra_pid = msg.msg_pid; ans.stra_seqnr = msg.msg_seqnr; ans.stra_policy = SYSTR_POLICY_PERMIT; - if ((ioctl(fd, STRIOCANSWER, &ans)) == -1) - goto fail; + (void) ioctl(fd, STRIOCANSWER, &ans); break; } } fail: - warn("unable to systrace %s", user_cmnd); kill(pid, SIGKILL); /* XXX - kill all pids in list */ _exit(1); } @@ -394,16 +410,16 @@ set_policy(fd, child) pol.strp_op = SYSTR_POLICY_NEW; pol.strp_num = -1; - pol.strp_maxents = SYS_MAXSYSCALL; + pol.strp_maxents = SYSTRACE_MAXENTS; if (ioctl(fd, STRIOCPOLICY, &pol) == -1) return(-1); - for (i = 0; i < SYS_MAXSYSCALL; i++) { - pol.strp_op = SYSTR_POLICY_ASSIGN; - pol.strp_pid = child->pid; - if (ioctl(fd, STRIOCPOLICY, &pol) == -1) - return(-1); + pol.strp_op = SYSTR_POLICY_ASSIGN; + pol.strp_pid = child->pid; + if (ioctl(fd, STRIOCPOLICY, &pol) == -1) + return(-1); + for (i = 0; i < SYSTRACE_MAXENTS; i++) { pol.strp_op = SYSTR_POLICY_MODIFY; pol.strp_policy = SYSTR_POLICY_PERMIT; pol.strp_code = i; @@ -479,28 +495,23 @@ read_string(fd, pid, addr, buf, bufsiz) return(cp - buf); } -static void -check_syscall(fd, askp, ansp) - int fd; - struct str_msg_ask *askp; - struct systrace_answer *ansp; +static schandler_t +find_handler(pid, code) + pid_t pid; + int code; { struct syscallaction *sca; struct childinfo *child; - if ((child = find_child(ansp->stra_pid)) == NULL) { - warnx("unable to find child with pid %d", ansp->stra_pid); - ansp->stra_policy = SYSTR_POLICY_NEVER; - return; + if ((child = find_child(pid)) == NULL) { + warnx("unable to find child with pid %d", pid); + return(NULL); } - ansp->stra_policy = SYSTR_POLICY_PERMIT; /* accept by default */ for (sca = child->action; sca->code != -1; sca++) { - if (sca->code == askp->code) { - if (sca->handler != NULL) - sca->handler(fd, askp, ansp); - break; - } + if (sca->code == code) + return(sca->handler); } + return(NULL); } /* @@ -559,39 +570,49 @@ decode_args(fd, pid, askp) /* * Decode the args to exec and check the command in sudoers. */ -static void -check_exec(fd, askp, ansp) +static int +check_exec(fd, pid, askp, cookie, policyp, errorp) int fd; + pid_t pid; struct str_msg_ask *askp; - struct systrace_answer *ansp; + int cookie; + int *policyp; + int *errorp; { int validated; struct childinfo *info; + /* If we have a cookie we take special action. */ + if (cookie != -1) { + if (cookie != 0) + log_auth(cookie, 1); + return(0); + } + /* We're not really initialized until the first exec finishes. */ if (initialized == 0) { initialized = 1; - ansp->stra_policy = SYSTR_POLICY_PERMIT; - return; + *policyp = SYSTR_POLICY_PERMIT; + return(0); } /* Failure should not be possible. */ - if ((info = find_child(ansp->stra_pid)) == NULL) { - ansp->stra_policy = SYSTR_POLICY_NEVER; - ansp->stra_error = ECHILD; - return; + if ((info = find_child(pid)) == NULL) { + *policyp = SYSTR_POLICY_NEVER; + *errorp = ECHILD; + return(0); } /* Fill in user_cmnd, user_base, user_args and user_stat. */ - decode_args(fd, ansp->stra_pid, askp); + decode_args(fd, pid, askp); if (user_cmnd[0] != '/' || !sudo_goodpath(user_cmnd, user_stat)) { - ansp->stra_policy = SYSTR_POLICY_NEVER; - ansp->stra_error = EACCES; - return; + *policyp = SYSTR_POLICY_NEVER; + *errorp = EACCES; + return(0); } /* Get processes's cwd. */ - if (ioctl(fd, STRIOCGETCWD, &ansp->stra_pid) == -1 || + if (ioctl(fd, STRIOCGETCWD, &pid) == -1 || !getcwd(user_cwd, sizeof(user_cwd))) { warnx("cannot get working directory"); (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd)); @@ -605,14 +626,11 @@ check_exec(fd, askp, ansp) user_runas = &info->pw->pw_name; rewind(sudoers_fp); validated = sudoers_lookup(0); -#ifdef DEBUG - warnx("intercepted: %s %s in %s -> 0x%x", user_cmnd, user_args, user_cwd, validated); -#endif - log_auth(validated, 1); if (ISSET(validated, VALIDATE_OK)) { - ansp->stra_policy = SYSTR_POLICY_PERMIT; + *policyp = SYSTR_POLICY_PERMIT; } else { - ansp->stra_policy = SYSTR_POLICY_NEVER; - ansp->stra_error = EACCES; + *policyp = SYSTR_POLICY_NEVER; + *errorp = EACCES; } + return(validated); } diff --git a/mon_systrace.h b/mon_systrace.h index a96d42ae4..aa7f4fdaa 100644 --- a/mon_systrace.h +++ b/mon_systrace.h @@ -14,16 +14,19 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define SYSTRACE_MAXENTS 1024 + +typedef int (*schandler_t) + __P((int, pid_t, struct str_msg_ask *, int, int *, int *)); struct childinfo; extern struct passwd *sudo_pwdup __P((const struct passwd *, int)); extern struct passwd *sudo_getpwuid __P((uid_t)); -static void check_exec __P((int, struct str_msg_ask *, - struct systrace_answer *)); -static void check_syscall __P((int, struct str_msg_ask *, - struct systrace_answer *)); +static int check_exec __P((int, pid_t, struct str_msg_ask *, int, + int *, int *)); +static schandler_t find_handler __P((pid_t, int)); static int decode_args __P((int, pid_t, struct str_msg_ask *)); static int set_policy __P((int, struct childinfo *)); static int systrace_open __P((void)); @@ -55,7 +58,7 @@ struct childinfo { struct syscallaction { int code; int policy; - void (*handler) __P((int, struct str_msg_ask *, struct systrace_answer *)); + schandler_t handler; }; static struct syscallaction syscalls_openbsd[] = { @@ -93,7 +96,7 @@ static struct syscallaction syscalls_netbsd[] = { }; static struct syscallaction syscalls_hpux[] = { - { 11, SYSTR_POLICY_ASK, NULL}, /* HPUX_SYS_execv */ + { 11, SYSTR_POLICY_ASK, check_exec}, /* HPUX_SYS_execv */ { 23, SYSTR_POLICY_ASK, NULL}, /* HPUX_SYS_setuid */ { 59, SYSTR_POLICY_ASK, check_exec}, /* HPUX_SYS_execve */ { 126, SYSTR_POLICY_ASK, NULL}, /* HPUX_SYS_setresuid */ @@ -101,12 +104,13 @@ static struct syscallaction syscalls_hpux[] = { }; static struct syscallaction syscalls_ibsc2[] = { - { 11, SYSTR_POLICY_ASK, NULL}, /* ISCS2_SYS_execv */ + { 11, SYSTR_POLICY_ASK, check_exec}, /* ISCS2_SYS_execv */ { 23, SYSTR_POLICY_ASK, NULL}, /* ISCS2_SYS_setuid */ { 59, SYSTR_POLICY_ASK, check_exec}, /* ISCS2_SYS_execve */ { -1, -1, NULL} }; +/* XXX - deny fexecve */ static struct syscallaction syscalls_linux[] = { { 11, SYSTR_POLICY_ASK, check_exec}, /* LINUX_SYS_execve */ { 23, SYSTR_POLICY_ASK, NULL}, /* LINUX_SYS_setuid16 */ @@ -128,7 +132,7 @@ static struct syscallaction syscalls_osf1[] = { }; static struct syscallaction syscalls_sunos[] = { - { 11, SYSTR_POLICY_ASK, NULL}, /* SUNOS_SYS_execv */ + { 11, SYSTR_POLICY_ASK, check_exec}, /* SUNOS_SYS_execv */ { 23, SYSTR_POLICY_ASK, NULL}, /* SUNOS_SYS_setuid */ { 59, SYSTR_POLICY_ASK, check_exec}, /* SUNOS_SYS_execve */ { 126, SYSTR_POLICY_ASK, NULL}, /* SUNOS_SYS_setreuid */ @@ -136,7 +140,7 @@ static struct syscallaction syscalls_sunos[] = { }; static struct syscallaction syscalls_svr4[] = { - { 11, SYSTR_POLICY_ASK, NULL}, /* SVR4_SYS_execv */ + { 11, SYSTR_POLICY_ASK, check_exec}, /* SVR4_SYS_execv */ { 23, SYSTR_POLICY_ASK, NULL}, /* SVR4_SYS_setuid */ { 59, SYSTR_POLICY_ASK, check_exec}, /* SVR4_SYS_execve */ { 141, SYSTR_POLICY_ASK, NULL}, /* SVR4_SYS_seteuid */ @@ -145,7 +149,7 @@ static struct syscallaction syscalls_svr4[] = { }; static struct syscallaction syscalls_ultrix[] = { - { 11, SYSTR_POLICY_ASK, NULL}, /* ULTRIX_SYS_execv */ + { 11, SYSTR_POLICY_ASK, check_exec}, /* ULTRIX_SYS_execv */ { 23, SYSTR_POLICY_ASK, NULL}, /* ULTRIX_SYS_setuid */ { 59, SYSTR_POLICY_ASK, check_exec}, /* ULTRIX_SYS_execve */ { 126, SYSTR_POLICY_ASK, NULL}, /* ULTRIX_SYS_setreuid */ @@ -153,7 +157,7 @@ static struct syscallaction syscalls_ultrix[] = { }; static struct syscallaction syscalls_irix[] = { - { 11, SYSTR_POLICY_ASK, NULL}, /* IRIX_SYS_execv */ + { 11, SYSTR_POLICY_ASK, check_exec}, /* IRIX_SYS_execv */ { 23, SYSTR_POLICY_ASK, NULL}, /* IRIX_SYS_setuid */ { 59, SYSTR_POLICY_ASK, check_exec}, /* IRIX_SYS_execve */ { 124, SYSTR_POLICY_ASK, NULL}, /* IRIX_SYS_setreuid */