2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-30 13:58:05 +00:00

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
This commit is contained in:
Todd C. Miller
2004-10-01 18:30:20 +00:00
parent ebf22ee977
commit e173a07c85
2 changed files with 102 additions and 80 deletions

View File

@@ -17,17 +17,7 @@
#include "config.h" #include "config.h"
#include <sys/param.h> #include <sys/param.h>
#include <sys/syscall.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#ifdef HAVE_DEV_SYSTRACE_H
# include <dev/systrace.h>
#else
# ifdef HAVE_SYS_SYSTRACE_H
# include <sys/systrace.h>
# else
# include <systrace.h>
# endif
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
@@ -42,6 +32,19 @@
#else #else
# include "emul/err.h" # include "emul/err.h"
#endif /* HAVE_ERR_H */ #endif /* HAVE_ERR_H */
#ifdef HAVE_DEV_SYSTRACE_H
# include <dev/systrace.h>
#else
# ifdef HAVE_SYS_SYSTRACE_H
# include <sys/systrace.h>
# else
# ifdef HAVE_LINUX_SYSTRACE_H
# include <linux/systrace.h>
# else
# include <systrace.h>
# endif
# endif
#endif
#include "sudo.h" #include "sudo.h"
#include "trace_systrace.h" #include "trace_systrace.h"
@@ -100,12 +103,13 @@ void
systrace_attach(pid) systrace_attach(pid)
pid_t pid; pid_t pid;
{ {
schandler_t handler;
struct systrace_answer ans; struct systrace_answer ans;
struct str_message msg; struct str_message msg;
sigaction_t sa, osa; sigaction_t sa, osa;
sigset_t set, oset; sigset_t set, oset;
ssize_t nread; ssize_t nread;
int fd; int fd, cookie;
if ((fd = systrace_open()) == -1) if ((fd = systrace_open()) == -1)
err(1, "unable to open systrace"); err(1, "unable to open systrace");
@@ -144,8 +148,10 @@ systrace_attach(pid)
/* reset signal state for tracer */ /* reset signal state for tracer */
if (sigaction(SIGUSR1, &osa, NULL) != 0 || 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; goto fail;
}
/* become a daemon */ /* become a daemon */
if (setsid() == -1) { if (setsid() == -1) {
@@ -165,12 +171,15 @@ systrace_attach(pid)
(void) kill(pid, SIGUSR1); (void) kill(pid, SIGUSR1);
_exit(0); _exit(0);
} }
warn("unable to systrace %s", user_cmnd);
goto fail; goto fail;
} }
new_child(-1, pid); 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; goto fail;
}
if (kill(pid, SIGUSR1) != 0) { if (kill(pid, SIGUSR1) != 0) {
warn("unable to wake up sleeping child"); warn("unable to wake up sleeping child");
@@ -201,25 +210,33 @@ systrace_attach(pid)
case SYSTR_MSG_UGID: case SYSTR_MSG_UGID:
/* uid/gid change */ /* 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)); memset(&ans, 0, sizeof(ans));
ans.stra_pid = msg.msg_pid; ans.stra_pid = msg.msg_pid;
ans.stra_seqnr = msg.msg_seqnr; ans.stra_seqnr = msg.msg_seqnr;
ans.stra_policy = SYSTR_POLICY_PERMIT; ans.stra_policy = SYSTR_POLICY_PERMIT;
if ((ioctl(fd, STRIOCANSWER, &ans)) == -1) if ((ioctl(fd, STRIOCANSWER, &ans)) == 0)
goto fail; update_child(msg.msg_pid, msg.msg_data.msg_ugid.uid);
break; break;
case SYSTR_MSG_ASK: case SYSTR_MSG_ASK:
memset(&ans, 0, sizeof(ans)); memset(&ans, 0, sizeof(ans));
ans.stra_pid = msg.msg_pid; ans.stra_pid = msg.msg_pid;
ans.stra_seqnr = msg.msg_seqnr; ans.stra_seqnr = msg.msg_seqnr;
check_syscall(fd, &msg.msg_data.msg_ask, &ans); ans.stra_policy = SYSTR_POLICY_PERMIT;
if ((ioctl(fd, STRIOCANSWER, &ans)) == -1) handler = find_handler(msg.msg_pid, msg.msg_data.msg_ask.code);
goto fail; 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; break;
case SYSTR_MSG_EMUL: case SYSTR_MSG_EMUL:
@@ -234,12 +251,13 @@ systrace_attach(pid)
msg.msg_data.msg_emul.emul); msg.msg_data.msg_emul.emul);
ans.stra_policy = SYSTR_POLICY_NEVER; ans.stra_policy = SYSTR_POLICY_NEVER;
} }
if ((ioctl(fd, STRIOCANSWER, &ans)) == -1) (void) ioctl(fd, STRIOCANSWER, &ans);
goto fail;
break; break;
#ifdef SYSTR_MSG_POLICYFREE
case SYSTR_MSG_POLICYFREE: case SYSTR_MSG_POLICYFREE:
break; break;
#endif
default: default:
#ifdef SUDO_DEVEL #ifdef SUDO_DEVEL
@@ -249,14 +267,12 @@ systrace_attach(pid)
ans.stra_pid = msg.msg_pid; ans.stra_pid = msg.msg_pid;
ans.stra_seqnr = msg.msg_seqnr; ans.stra_seqnr = msg.msg_seqnr;
ans.stra_policy = SYSTR_POLICY_PERMIT; ans.stra_policy = SYSTR_POLICY_PERMIT;
if ((ioctl(fd, STRIOCANSWER, &ans)) == -1) (void) ioctl(fd, STRIOCANSWER, &ans);
goto fail;
break; break;
} }
} }
fail: fail:
warn("unable to systrace %s", user_cmnd);
kill(pid, SIGKILL); /* XXX - kill all pids in list */ kill(pid, SIGKILL); /* XXX - kill all pids in list */
_exit(1); _exit(1);
} }
@@ -394,16 +410,16 @@ set_policy(fd, child)
pol.strp_op = SYSTR_POLICY_NEW; pol.strp_op = SYSTR_POLICY_NEW;
pol.strp_num = -1; pol.strp_num = -1;
pol.strp_maxents = SYS_MAXSYSCALL; pol.strp_maxents = SYSTRACE_MAXENTS;
if (ioctl(fd, STRIOCPOLICY, &pol) == -1) if (ioctl(fd, STRIOCPOLICY, &pol) == -1)
return(-1); return(-1);
for (i = 0; i < SYS_MAXSYSCALL; i++) { pol.strp_op = SYSTR_POLICY_ASSIGN;
pol.strp_op = SYSTR_POLICY_ASSIGN; pol.strp_pid = child->pid;
pol.strp_pid = child->pid; if (ioctl(fd, STRIOCPOLICY, &pol) == -1)
if (ioctl(fd, STRIOCPOLICY, &pol) == -1) return(-1);
return(-1);
for (i = 0; i < SYSTRACE_MAXENTS; i++) {
pol.strp_op = SYSTR_POLICY_MODIFY; pol.strp_op = SYSTR_POLICY_MODIFY;
pol.strp_policy = SYSTR_POLICY_PERMIT; pol.strp_policy = SYSTR_POLICY_PERMIT;
pol.strp_code = i; pol.strp_code = i;
@@ -479,28 +495,23 @@ read_string(fd, pid, addr, buf, bufsiz)
return(cp - buf); return(cp - buf);
} }
static void static schandler_t
check_syscall(fd, askp, ansp) find_handler(pid, code)
int fd; pid_t pid;
struct str_msg_ask *askp; int code;
struct systrace_answer *ansp;
{ {
struct syscallaction *sca; struct syscallaction *sca;
struct childinfo *child; struct childinfo *child;
if ((child = find_child(ansp->stra_pid)) == NULL) { if ((child = find_child(pid)) == NULL) {
warnx("unable to find child with pid %d", ansp->stra_pid); warnx("unable to find child with pid %d", pid);
ansp->stra_policy = SYSTR_POLICY_NEVER; return(NULL);
return;
} }
ansp->stra_policy = SYSTR_POLICY_PERMIT; /* accept by default */
for (sca = child->action; sca->code != -1; sca++) { for (sca = child->action; sca->code != -1; sca++) {
if (sca->code == askp->code) { if (sca->code == code)
if (sca->handler != NULL) return(sca->handler);
sca->handler(fd, askp, ansp);
break;
}
} }
return(NULL);
} }
/* /*
@@ -559,39 +570,49 @@ decode_args(fd, pid, askp)
/* /*
* Decode the args to exec and check the command in sudoers. * Decode the args to exec and check the command in sudoers.
*/ */
static void static int
check_exec(fd, askp, ansp) check_exec(fd, pid, askp, cookie, policyp, errorp)
int fd; int fd;
pid_t pid;
struct str_msg_ask *askp; struct str_msg_ask *askp;
struct systrace_answer *ansp; int cookie;
int *policyp;
int *errorp;
{ {
int validated; int validated;
struct childinfo *info; 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. */ /* We're not really initialized until the first exec finishes. */
if (initialized == 0) { if (initialized == 0) {
initialized = 1; initialized = 1;
ansp->stra_policy = SYSTR_POLICY_PERMIT; *policyp = SYSTR_POLICY_PERMIT;
return; return(0);
} }
/* Failure should not be possible. */ /* Failure should not be possible. */
if ((info = find_child(ansp->stra_pid)) == NULL) { if ((info = find_child(pid)) == NULL) {
ansp->stra_policy = SYSTR_POLICY_NEVER; *policyp = SYSTR_POLICY_NEVER;
ansp->stra_error = ECHILD; *errorp = ECHILD;
return; return(0);
} }
/* Fill in user_cmnd, user_base, user_args and user_stat. */ /* 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)) { if (user_cmnd[0] != '/' || !sudo_goodpath(user_cmnd, user_stat)) {
ansp->stra_policy = SYSTR_POLICY_NEVER; *policyp = SYSTR_POLICY_NEVER;
ansp->stra_error = EACCES; *errorp = EACCES;
return; return(0);
} }
/* Get processes's cwd. */ /* Get processes's cwd. */
if (ioctl(fd, STRIOCGETCWD, &ansp->stra_pid) == -1 || if (ioctl(fd, STRIOCGETCWD, &pid) == -1 ||
!getcwd(user_cwd, sizeof(user_cwd))) { !getcwd(user_cwd, sizeof(user_cwd))) {
warnx("cannot get working directory"); warnx("cannot get working directory");
(void) strlcpy(user_cwd, "unknown", sizeof(user_cwd)); (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd));
@@ -605,14 +626,11 @@ check_exec(fd, askp, ansp)
user_runas = &info->pw->pw_name; user_runas = &info->pw->pw_name;
rewind(sudoers_fp); rewind(sudoers_fp);
validated = sudoers_lookup(0); 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)) { if (ISSET(validated, VALIDATE_OK)) {
ansp->stra_policy = SYSTR_POLICY_PERMIT; *policyp = SYSTR_POLICY_PERMIT;
} else { } else {
ansp->stra_policy = SYSTR_POLICY_NEVER; *policyp = SYSTR_POLICY_NEVER;
ansp->stra_error = EACCES; *errorp = EACCES;
} }
return(validated);
} }

View File

@@ -14,16 +14,19 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * 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; struct childinfo;
extern struct passwd *sudo_pwdup __P((const struct passwd *, int)); extern struct passwd *sudo_pwdup __P((const struct passwd *, int));
extern struct passwd *sudo_getpwuid __P((uid_t)); extern struct passwd *sudo_getpwuid __P((uid_t));
static void check_exec __P((int, struct str_msg_ask *, static int check_exec __P((int, pid_t, struct str_msg_ask *, int,
struct systrace_answer *)); int *, int *));
static void check_syscall __P((int, struct str_msg_ask *, static schandler_t find_handler __P((pid_t, int));
struct systrace_answer *));
static int decode_args __P((int, pid_t, struct str_msg_ask *)); static int decode_args __P((int, pid_t, struct str_msg_ask *));
static int set_policy __P((int, struct childinfo *)); static int set_policy __P((int, struct childinfo *));
static int systrace_open __P((void)); static int systrace_open __P((void));
@@ -55,7 +58,7 @@ struct childinfo {
struct syscallaction { struct syscallaction {
int code; int code;
int policy; int policy;
void (*handler) __P((int, struct str_msg_ask *, struct systrace_answer *)); schandler_t handler;
}; };
static struct syscallaction syscalls_openbsd[] = { static struct syscallaction syscalls_openbsd[] = {
@@ -93,7 +96,7 @@ static struct syscallaction syscalls_netbsd[] = {
}; };
static struct syscallaction syscalls_hpux[] = { 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 */ { 23, SYSTR_POLICY_ASK, NULL}, /* HPUX_SYS_setuid */
{ 59, SYSTR_POLICY_ASK, check_exec}, /* HPUX_SYS_execve */ { 59, SYSTR_POLICY_ASK, check_exec}, /* HPUX_SYS_execve */
{ 126, SYSTR_POLICY_ASK, NULL}, /* HPUX_SYS_setresuid */ { 126, SYSTR_POLICY_ASK, NULL}, /* HPUX_SYS_setresuid */
@@ -101,12 +104,13 @@ static struct syscallaction syscalls_hpux[] = {
}; };
static struct syscallaction syscalls_ibsc2[] = { 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 */ { 23, SYSTR_POLICY_ASK, NULL}, /* ISCS2_SYS_setuid */
{ 59, SYSTR_POLICY_ASK, check_exec}, /* ISCS2_SYS_execve */ { 59, SYSTR_POLICY_ASK, check_exec}, /* ISCS2_SYS_execve */
{ -1, -1, NULL} { -1, -1, NULL}
}; };
/* XXX - deny fexecve */
static struct syscallaction syscalls_linux[] = { static struct syscallaction syscalls_linux[] = {
{ 11, SYSTR_POLICY_ASK, check_exec}, /* LINUX_SYS_execve */ { 11, SYSTR_POLICY_ASK, check_exec}, /* LINUX_SYS_execve */
{ 23, SYSTR_POLICY_ASK, NULL}, /* LINUX_SYS_setuid16 */ { 23, SYSTR_POLICY_ASK, NULL}, /* LINUX_SYS_setuid16 */
@@ -128,7 +132,7 @@ static struct syscallaction syscalls_osf1[] = {
}; };
static struct syscallaction syscalls_sunos[] = { 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 */ { 23, SYSTR_POLICY_ASK, NULL}, /* SUNOS_SYS_setuid */
{ 59, SYSTR_POLICY_ASK, check_exec}, /* SUNOS_SYS_execve */ { 59, SYSTR_POLICY_ASK, check_exec}, /* SUNOS_SYS_execve */
{ 126, SYSTR_POLICY_ASK, NULL}, /* SUNOS_SYS_setreuid */ { 126, SYSTR_POLICY_ASK, NULL}, /* SUNOS_SYS_setreuid */
@@ -136,7 +140,7 @@ static struct syscallaction syscalls_sunos[] = {
}; };
static struct syscallaction syscalls_svr4[] = { 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 */ { 23, SYSTR_POLICY_ASK, NULL}, /* SVR4_SYS_setuid */
{ 59, SYSTR_POLICY_ASK, check_exec}, /* SVR4_SYS_execve */ { 59, SYSTR_POLICY_ASK, check_exec}, /* SVR4_SYS_execve */
{ 141, SYSTR_POLICY_ASK, NULL}, /* SVR4_SYS_seteuid */ { 141, SYSTR_POLICY_ASK, NULL}, /* SVR4_SYS_seteuid */
@@ -145,7 +149,7 @@ static struct syscallaction syscalls_svr4[] = {
}; };
static struct syscallaction syscalls_ultrix[] = { 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 */ { 23, SYSTR_POLICY_ASK, NULL}, /* ULTRIX_SYS_setuid */
{ 59, SYSTR_POLICY_ASK, check_exec}, /* ULTRIX_SYS_execve */ { 59, SYSTR_POLICY_ASK, check_exec}, /* ULTRIX_SYS_execve */
{ 126, SYSTR_POLICY_ASK, NULL}, /* ULTRIX_SYS_setreuid */ { 126, SYSTR_POLICY_ASK, NULL}, /* ULTRIX_SYS_setreuid */
@@ -153,7 +157,7 @@ static struct syscallaction syscalls_ultrix[] = {
}; };
static struct syscallaction syscalls_irix[] = { 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 */ { 23, SYSTR_POLICY_ASK, NULL}, /* IRIX_SYS_setuid */
{ 59, SYSTR_POLICY_ASK, check_exec}, /* IRIX_SYS_execve */ { 59, SYSTR_POLICY_ASK, check_exec}, /* IRIX_SYS_execve */
{ 124, SYSTR_POLICY_ASK, NULL}, /* IRIX_SYS_setreuid */ { 124, SYSTR_POLICY_ASK, NULL}, /* IRIX_SYS_setreuid */