diff options
| author | christos <christos@NetBSD.org> | 2002-01-11 21:16:27 +0000 |
|---|---|---|
| committer | christos <christos@NetBSD.org> | 2002-01-11 21:16:27 +0000 |
| commit | d4e7e4c9c46b73dc49ea2bba07f79c9dcaf04ab2 (patch) | |
| tree | 23e8cc1b8efd86e1670941c32a10838c8f53c549 | |
| parent | 94faea123bc369a6a06405eb4a3bf094ec1ba71d (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.c | 16 | ||||
| -rw-r--r-- | sys/kern/sys_process.c | 8 | ||||
| -rw-r--r-- | sys/sys/proc.h | 43 |
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 */ /* |
