summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorelad <elad@NetBSD.org>2005-06-26 19:58:29 +0000
committerelad <elad@NetBSD.org>2005-06-26 19:58:29 +0000
commit8ebc2e9beec6e592b40d97596776d080e2b3b63c (patch)
tree0c442dbf5206a8f6ab380feb292791074a7400ed /sys
parent5b718ea54c145b7e760d67177c40cc8d02dfe719 (diff)
From marius@openbsd:
Add an exec message so that whenever a set-uid/gid process executes a new image which we may control, the exec does not go by unnoticed.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/exec_script.c13
-rw-r--r--sys/kern/kern_exec.c46
-rw-r--r--sys/kern/kern_systrace.c67
-rw-r--r--sys/sys/systrace.h9
4 files changed, 113 insertions, 22 deletions
diff --git a/sys/kern/exec_script.c b/sys/kern/exec_script.c
index 4b2dc1bd161..36a93503dc7 100644
--- a/sys/kern/exec_script.c
+++ b/sys/kern/exec_script.c
@@ -1,4 +1,4 @@
-/* $NetBSD: exec_script.c,v 1.39 2005/05/19 20:16:19 elad Exp $ */
+/* $NetBSD: exec_script.c,v 1.40 2005/06/26 19:58:29 elad Exp $ */
/*
* Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: exec_script.c,v 1.39 2005/05/19 20:16:19 elad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: exec_script.c,v 1.40 2005/06/26 19:58:29 elad Exp $");
#if defined(SETUIDSCRIPTS) && !defined(FDSCRIPTS)
#define FDSCRIPTS /* Need this for safe set-id scripts. */
@@ -56,6 +56,10 @@ __KERNEL_RCSID(0, "$NetBSD: exec_script.c,v 1.39 2005/05/19 20:16:19 elad Exp $"
#include <sys/verified_exec.h>
+#ifdef SYSTRACE
+#include <sys/systrace.h>
+#endif /* SYSTRACE */
+
/*
* exec_script_makecmds(): Check if it's an executable shell script.
*
@@ -225,8 +229,13 @@ check_shell:
if ((epp->ep_flags & EXEC_HASFD) == 0) {
#endif
/* normally can't fail, but check for it if diagnostic */
+#ifdef SYSTRACE
+ error = copystr(epp->ep_name, *tmpsap++, MAXPATHLEN,
+ (size_t *)0);
+#else
error = copyinstr(epp->ep_name, *tmpsap++, MAXPATHLEN,
(size_t *)0);
+#endif /* SYSTRACE */
#ifdef DIAGNOSTIC
if (error != 0)
panic("exec_script: copyinstr couldn't fail");
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 33d0ca6eab1..65ac44c5184 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_exec.c,v 1.199 2005/06/10 23:32:16 elad Exp $ */
+/* $NetBSD: kern_exec.c,v 1.200 2005/06/26 19:58:29 elad Exp $ */
/*-
* Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.199 2005/06/10 23:32:16 elad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.200 2005/06/26 19:58:29 elad Exp $");
#include "opt_ktrace.h"
#include "opt_syscall_debug.h"
@@ -67,6 +67,10 @@ __KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.199 2005/06/10 23:32:16 elad Exp $")
#include <sys/verified_exec.h>
#endif
+#ifdef SYSTRACE
+#include <sys/systrace.h>
+#endif /* SYSTRACE */
+
#include <uvm/uvm_extern.h>
#include <machine/cpu.h>
@@ -201,7 +205,7 @@ static void link_es(struct execsw_entry **, const struct execsw *);
* ON ENTRY:
* exec package with appropriate namei info
* proc pointer of exec'ing proc
- * iff verified exec enabled then flag indicating a direct exec or
+ * if verified exec enabled then flag indicating a direct exec or
* an indirect exec (i.e. for a shell script interpreter)
* NO SELF-LOCKED VNODES
*
@@ -222,7 +226,7 @@ static void link_es(struct execsw_entry **, const struct execsw *);
*/
int
#ifdef VERIFIED_EXEC
-check_exec(struct proc *p, struct exec_package *epp, int direct_exec)
+check_exec(struct proc *p, struct exec_package *epp, int flag)
#else
check_exec(struct proc *p, struct exec_package *epp)
#endif
@@ -270,8 +274,8 @@ check_exec(struct proc *p, struct exec_package *epp)
#ifdef VERIFIED_EXEC
/* Evaluate signature for file... */
- if ((error = veriexec_verify(p, vp, epp->ep_vap,
- epp->ep_name, direct_exec)) != 0)
+ if ((error = veriexec_verify(p, vp, epp->ep_vap, epp->ep_name,
+ flag, NULL)) != 0)
goto bad2;
#endif
@@ -391,6 +395,11 @@ sys_execve(struct lwp *l, void *v, register_t *retval)
int szsigcode;
struct exec_vmcmd *base_vcp;
int oldlwpflags;
+#ifdef SYSTRACE
+ int wassugid = ISSET(p->p_flag, P_SUGID);
+ char pathbuf[MAXPATHLEN];
+ size_t pathbuflen;
+#endif /* SYSTRACE */
/* Disable scheduler activation upcalls. */
oldlwpflags = l->l_flag & (L_SA | L_SA_UPCALL);
@@ -416,12 +425,25 @@ sys_execve(struct lwp *l, void *v, register_t *retval)
* functions call check_exec() recursively - for example,
* see exec_script_makecmds().
*/
+#ifdef SYSTRACE
+ error = copyinstr(SCARG(uap, path), pathbuf, sizeof(pathbuf),
+ &pathbuflen);
+ if (error)
+ goto clrflg;
+
+ NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, p);
+#else
NDINIT(&nid, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+#endif /* SYSTRACE */
/*
* initialize the fields of the exec package.
*/
+#ifdef SYSTRACE
+ pack.ep_name = pathbuf;
+#else
pack.ep_name = SCARG(uap, path);
+#endif /* SYSTRACE */
pack.ep_hdr = malloc(exec_maxhdrsz, M_EXEC, M_WAITOK);
pack.ep_hdrlen = exec_maxhdrsz;
pack.ep_hdrvalid = 0;
@@ -843,6 +865,12 @@ sys_execve(struct lwp *l, void *v, register_t *retval)
splx(s);
}
+#ifdef SYSTRACE
+ if (ISSET(p->p_flag, P_SYSTRACE) &&
+ wassugid && !ISSET(p->p_flag, P_SUGID))
+ systrace_execve(pathbuf, p);
+#endif /* SYSTRACE */
+
return (EJUSTRETURN);
bad:
@@ -862,13 +890,17 @@ sys_execve(struct lwp *l, void *v, register_t *retval)
uvm_km_free(exec_map, (vaddr_t) argp, NCARGS, UVM_KMF_PAGEABLE);
freehdr:
+ free(pack.ep_hdr, M_EXEC);
+
+#ifdef SYSTRACE
+ clrflg:
+#endif /* SYSTRACE */
l->l_flag |= oldlwpflags;
p->p_flag &= ~P_INEXEC;
#ifdef LKM
lockmgr(&exec_lock, LK_RELEASE, NULL);
#endif
- free(pack.ep_hdr, M_EXEC);
return error;
exec_abort:
diff --git a/sys/kern/kern_systrace.c b/sys/kern/kern_systrace.c
index 5d44fc0c828..989cb5a33f3 100644
--- a/sys/kern/kern_systrace.c
+++ b/sys/kern/kern_systrace.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_systrace.c,v 1.44 2005/02/26 21:34:55 perry Exp $ */
+/* $NetBSD: kern_systrace.c,v 1.45 2005/06/26 19:58:29 elad Exp $ */
/*
* Copyright 2002, 2003 Niels Provos <provos@citi.umich.edu>
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_systrace.c,v 1.44 2005/02/26 21:34:55 perry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_systrace.c,v 1.45 2005/06/26 19:58:29 elad Exp $");
#include "opt_systrace.h"
@@ -1242,6 +1242,42 @@ systrace_attach(struct fsystrace *fst, pid_t pid)
return (error);
}
+void
+systrace_execve(char *path, struct proc *p)
+{
+ struct str_process *strp;
+ struct fsystrace *fst;
+ struct str_message msg;
+ struct str_msg_execve *msg_execve;
+
+ do {
+ systrace_lock();
+ strp = p->p_systrace;
+ if (strp == NULL) {
+ systrace_unlock();
+ return;
+ }
+
+ msg_execve = &msg.msg_data.msg_execve;
+ fst = strp->parent;
+ SYSTRACE_LOCK(fst, curlwp);
+ systrace_unlock();
+
+ /*
+ * susers will get the execve call anyway. Also, if
+ * we're not allowed to control the process, escape.
+ */
+ if (fst->issuser ||
+ fst->p_ruid != p->p_cred->p_ruid ||
+ fst->p_rgid != p->p_cred->p_rgid) {
+ SYSTRACE_UNLOCK(fst, curlwp);
+ return;
+ }
+
+ strlcpy(msg_execve->path, path, sizeof(msg_execve->path));
+ } while (systrace_make_msg(strp, SYSTR_MSG_EXECVE, &msg) != 0);
+}
+
/* Prepare to replace arguments */
int
@@ -1348,7 +1384,6 @@ systrace_replace(struct str_process *strp, size_t argsize, register_t args[])
int
systrace_fname(struct str_process *strp, caddr_t kdata, size_t len)
{
-
if (strp->nfname >= SYSTR_MAXFNAME || len < 2)
return EINVAL;
@@ -1377,9 +1412,10 @@ void
systrace_namei(struct nameidata *ndp)
{
struct str_process *strp;
- struct fsystrace *fst;
+ struct fsystrace *fst = NULL; /* XXXGCC */
struct componentname *cnp = &ndp->ni_cnd;
size_t i;
+ int hamper = 0;
systrace_lock();
strp = cnp->cn_proc->p_systrace;
@@ -1388,18 +1424,21 @@ systrace_namei(struct nameidata *ndp)
SYSTRACE_LOCK(fst, curlwp);
systrace_unlock();
- for (i = 0; i < strp->nfname; i++) {
+ for (i = 0; i < strp->nfname; i++)
if (strcmp(cnp->cn_pnbuf, strp->fname[i]) == 0) {
- /* ELOOP if namei() tries to readlink */
- ndp->ni_loopcnt = MAXSYMLINKS;
- cnp->cn_flags &= ~FOLLOW;
- cnp->cn_flags |= NOFOLLOW;
+ hamper = 1;
break;
}
- }
SYSTRACE_UNLOCK(fst, curlwp);
} else
systrace_unlock();
+
+ if (hamper) {
+ /* ELOOP if namei() tries to readlink */
+ ndp->ni_loopcnt = MAXSYMLINKS;
+ cnp->cn_flags &= ~FOLLOW;
+ cnp->cn_flags |= NOFOLLOW;
+ }
}
struct str_process *
@@ -1614,7 +1653,11 @@ systrace_make_msg(struct str_process *strp, int type, struct str_message *tmsg)
struct str_msgcontainer *cont;
struct str_message *msg;
struct fsystrace *fst = strp->parent;
- int st;
+ int st, pri;
+
+ pri = PWAIT|PCATCH;
+ if (type == SYSTR_MSG_EXECVE)
+ pri &= ~PCATCH;
cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK);
memset(cont, 0, sizeof(struct str_msgcontainer));
@@ -1651,7 +1694,7 @@ systrace_make_msg(struct str_process *strp, int type, struct str_message *tmsg)
int f;
f = curlwp->l_flag & L_SA;
curlwp->l_flag &= ~L_SA;
- st = tsleep(strp, PWAIT | PCATCH, "systrmsg", 0);
+ st = tsleep(strp, pri, "systrmsg", 0);
curlwp->l_flag |= f;
if (st != 0)
return (ERESTART);
diff --git a/sys/sys/systrace.h b/sys/sys/systrace.h
index 2e0857834d4..71f85fae272 100644
--- a/sys/sys/systrace.h
+++ b/sys/sys/systrace.h
@@ -1,4 +1,4 @@
-/* $NetBSD: systrace.h,v 1.12 2003/10/31 03:28:14 simonb Exp $ */
+/* $NetBSD: systrace.h,v 1.13 2005/06/26 19:58:29 elad Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -48,6 +48,10 @@ struct str_msg_ugid {
gid_t gid;
};
+struct str_msg_execve {
+ char path[MAXPATHLEN];
+};
+
#define SYSTR_MAX_POLICIES 64
#define SYSTR_MAXARGS 64
#define SYSTR_MAXFNAME 8
@@ -72,6 +76,7 @@ struct str_msg_child {
#define SYSTR_MSG_CHILD 4
#define SYSTR_MSG_UGID 5
#define SYSTR_MSG_POLICYFREE 6
+#define SYSTR_MSG_EXECVE 7
#define SYSTR_MSG_NOPROCESS(x) \
((x)->msg.msg_type == SYSTR_MSG_CHILD || \
@@ -87,6 +92,7 @@ struct str_message {
struct str_msg_ugid msg_ugid;
struct str_msg_ask msg_ask;
struct str_msg_child msg_child;
+ struct str_msg_execve msg_execve;
} msg_data;
};
@@ -216,6 +222,7 @@ void systrace_exit(struct proc *, register_t, void *, register_t [], int);
void systrace_sys_exit(struct proc *);
void systrace_sys_fork(struct proc *, struct proc *);
void systrace_init(void);
+void systrace_execve(char *, struct proc *);
#endif /* _KERNEL */
#endif /* !_SYSTRACE_H_ */