summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2002-01-11 21:16:27 +0000
committerchristos <christos@NetBSD.org>2002-01-11 21:16:27 +0000
commitd4e7e4c9c46b73dc49ea2bba07f79c9dcaf04ab2 (patch)
tree23e8cc1b8efd86e1670941c32a10838c8f53c549
parent94faea123bc369a6a06405eb4a3bf094ec1ba71d (diff)
Fix a ptrace/execve race that could be used to modify the child process's
image during execve. This is a security issue because one can do that to setuid programs... From FreeBSD.
-rw-r--r--sys/kern/kern_exec.c16
-rw-r--r--sys/kern/sys_process.c8
-rw-r--r--sys/sys/proc.h43
3 files changed, 41 insertions, 26 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index f52b4deac13..a24c7daee84 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_exec.c,v 1.148 2001/12/08 00:35:30 thorpej Exp $ */
+/* $NetBSD: kern_exec.c,v 1.149 2002/01/11 21:16:27 christos 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.148 2001/12/08 00:35:30 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.149 2002/01/11 21:16:27 christos Exp $");
#include "opt_ktrace.h"
#include "opt_syscall_debug.h"
@@ -340,6 +340,15 @@ sys_execve(struct proc *p, void *v, register_t *retval)
int szsigcode;
struct exec_vmcmd *base_vcp;
+ /*
+ * Lock the process and set the P_INEXEC flag to indicate that
+ * it should be left alone until we're done here. This is
+ * necessary to avoid race conditions - e.g. in ptrace() -
+ * that might allow a local user to illicitly obtain elevated
+ * privileges.
+ */
+ p->p_flag |= P_INEXEC;
+
cred = p->p_ucred;
base_vcp = NULL;
/*
@@ -692,10 +701,11 @@ sys_execve(struct proc *p, void *v, register_t *retval)
#ifdef LKM
lockmgr(&exec_lock, LK_RELEASE, NULL);
#endif
-
+ p->p_flag &= ~P_INEXEC;
return (EJUSTRETURN);
bad:
+ p->p_flag &= ~P_INEXEC;
/* free the vmspace-creation commands, and release their references */
kill_vmcmds(&pack.ep_vmcmds);
/* kill any opened file descriptor, if necessary */
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index c74fc5a1a58..78c56f44208 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_process.c,v 1.71 2001/12/05 00:58:05 thorpej Exp $ */
+/* $NetBSD: sys_process.c,v 1.72 2002/01/11 21:16:28 christos Exp $ */
/*-
* Copyright (c) 1994 Christopher G. Demetriou. All rights reserved.
@@ -53,7 +53,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.71 2001/12/05 00:58:05 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.72 2002/01/11 21:16:28 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -107,6 +107,10 @@ sys_ptrace(p, v, retval)
return (ESRCH);
}
+ /* Can't trace a process that's currently exec'ing. */
+ if ((t->p_flag & P_INEXEC) != 0)
+ return EAGAIN;
+
/* Make sure we can operate on it. */
switch (SCARG(uap, req)) {
case PT_TRACE_ME:
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 7ccc1a2d276..30937af0398 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $NetBSD: proc.h,v 1.135 2001/12/08 00:35:32 thorpej Exp $ */
+/* $NetBSD: proc.h,v 1.136 2002/01/11 21:16:27 christos Exp $ */
/*-
* Copyright (c) 1986, 1989, 1991, 1993
@@ -272,26 +272,27 @@ struct proc {
#define P_ZOMBIE(p) ((p)->p_stat == SZOMB || (p)->p_stat == SDEAD)
/* These flags are kept in p_flag. */
-#define P_ADVLOCK 0x00001 /* Process may hold a POSIX advisory lock */
-#define P_CONTROLT 0x00002 /* Has a controlling terminal */
-#define P_INMEM 0x00004 /* Loaded into memory */
-#define P_NOCLDSTOP 0x00008 /* No SIGCHLD when children stop */
-#define P_PPWAIT 0x00010 /* Parent is waiting for child to exec/exit */
-#define P_PROFIL 0x00020 /* Has started profiling */
-#define P_SELECT 0x00040 /* Selecting; wakeup/waiting danger */
-#define P_SINTR 0x00080 /* Sleep is interruptible */
-#define P_SUGID 0x00100 /* Had set id privileges since last exec */
-#define P_SYSTEM 0x00200 /* System proc: no sigs, stats or swapping */
-#define P_TIMEOUT 0x00400 /* Timing out during sleep */
-#define P_TRACED 0x00800 /* Debugged process being traced */
-#define P_WAITED 0x01000 /* Debugging process has waited for child */
-#define P_WEXIT 0x02000 /* Working on exiting */
-#define P_EXEC 0x04000 /* Process called exec */
-#define P_OWEUPC 0x08000 /* Owe process an addupc() call at next ast */
-#define P_FSTRACE 0x10000 /* Debugger process being traced by procfs */
-#define P_NOCLDWAIT 0x20000 /* No zombies if child dies */
-#define P_32 0x40000 /* 32-bit process (used on 64-bit kernels) */
-#define P_BIGLOCK 0x80000 /* Process needs kernel "big lock" to run */
+#define P_ADVLOCK 0x000001 /* Process may hold a POSIX advisory lock */
+#define P_CONTROLT 0x000002 /* Has a controlling terminal */
+#define P_INMEM 0x000004 /* Loaded into memory */
+#define P_NOCLDSTOP 0x000008 /* No SIGCHLD when children stop */
+#define P_PPWAIT 0x000010 /* Parent is waiting for child to exec/exit */
+#define P_PROFIL 0x000020 /* Has started profiling */
+#define P_SELECT 0x000040 /* Selecting; wakeup/waiting danger */
+#define P_SINTR 0x000080 /* Sleep is interruptible */
+#define P_SUGID 0x000100 /* Had set id privileges since last exec */
+#define P_SYSTEM 0x000200 /* System proc: no sigs, stats or swapping */
+#define P_TIMEOUT 0x000400 /* Timing out during sleep */
+#define P_TRACED 0x000800 /* Debugged process being traced */
+#define P_WAITED 0x001000 /* Debugging process has waited for child */
+#define P_WEXIT 0x002000 /* Working on exiting */
+#define P_EXEC 0x004000 /* Process called exec */
+#define P_OWEUPC 0x008000 /* Owe process an addupc() call at next ast */
+#define P_FSTRACE 0x010000 /* Debugger process being traced by procfs */
+#define P_NOCLDWAIT 0x020000 /* No zombies if child dies */
+#define P_32 0x040000 /* 32-bit process (used on 64-bit kernels) */
+#define P_BIGLOCK 0x080000 /* Process needs kernel "big lock" to run */
+#define P_INEXEC 0x100000 /* Process is exec'ing and cannot be traced */
/*