TUCoPS :: BSD :: bsd5622.htm

OpenBSD local priviledge escalation via select call
12th Aug 2002 [SBWID-5622]
COMMAND

	OpenBSD local priviledge escalation via select call

SYSTEMS AFFECTED

	All versions of OpenBSD

PROBLEM

	In OpenBSD security advisory by Niels Provos [provos@citi.umich.edu] :
	

	Insufficient boundary checks in the select call  allow  an  attacker  to
	overwrite kernel memory and execute arbitrary code in kernel context.
	

	Traditionally, the size parameter  for  the  select  system  call  is  a
	signed integer. As a result, the kernel  evaluates  the  upper  boundary
	checks in a signed context, so that  an  attacker  can  circumvent  when
	using certain negative values.
	

	When the kernel  copies  the  data  for  the  select  system  call  from
	userland the size is used as an unsigned  integer  which  causes  kernel
	memory to be overwritten with arbitrary data.
	

	Local users can obtain complete system  privileges  and  circumvent  the
	extra security measures provided by the securelevel system.

SOLUTION

	Apply one of the supplied kernel patches  or  update  to  3.0-stable  or
	3.1-stable from 2002-08-11 17:00 EDT or later.
	 

	Apply by doing:

	        cd /usr/src

	        patch -p0 < 014_scarg.patch

	And then rebuild your kernel.

	

	Index: sys/kern/sys_generic.c

	===================================================================

	RCS file: /cvs/src/sys/kern/sys_generic.c,v

	retrieving revision 1.39

	retrieving revision 1.39.2.1

	diff -u -r1.39 -r1.39.2.1

	--- sys/kern/sys_generic.c      14 Mar 2002 01:27:04 -0000      1.39

	+++ sys/kern/sys_generic.c      11 Aug 2002 17:14:55 -0000      1.39.2.1

	@@ -1,4 +1,4 @@

	-/*     $OpenBSD: sys_generic.c,v 1.39 2002/03/14 01:27:04 millert Exp $        */

	+/*     $OpenBSD: sys_generic.c,v 1.39.2.1 2002/08/11 17:14:55 jason Exp $      */

	 /*     $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $     */

	 

	 /*

	@@ -644,12 +644,9 @@

	  * Select system call.

	  */

	 int

	-sys_select(p, v, retval)

	-       register struct proc *p;

	-       void *v;

	-       register_t *retval;

	+sys_select(struct proc *p, void *v, register_t *retval)

	 {

	-       register struct sys_select_args /* {

	+       struct sys_select_args /* {

	                syscallarg(int) nd;

	                syscallarg(fd_set *) in;

	                syscallarg(fd_set *) ou;

	@@ -659,14 +656,15 @@

	        fd_set bits[6], *pibits[3], *pobits[3];

	        struct timeval atv;

	        int s, ncoll, error = 0, timo;

	-       u_int ni;

	+       u_int nd, ni;

	 

	-       if (SCARG(uap, nd) > p->p_fd->fd_nfiles) {

	+       nd = SCARG(uap, nd);

	+       if (nd > p->p_fd->fd_nfiles) {

	                /* forgiving; slightly wrong */

	-               SCARG(uap, nd) = p->p_fd->fd_nfiles;

	+               nd = p->p_fd->fd_nfiles;

	        }

	-       ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask);

	-       if (SCARG(uap, nd) > FD_SETSIZE) {

	+       ni = howmany(nd, NFDBITS) * sizeof(fd_mask);

	+       if (nd > FD_SETSIZE) {

	                caddr_t mbits;

	 

	                mbits = malloc(ni * 6, M_TEMP, M_WAITOK);

	@@ -713,7 +711,7 @@

	 retry:

	        ncoll = nselcoll;

	        p->p_flag |= P_SELECT;

	-       error = selscan(p, pibits[0], pobits[0], SCARG(uap, nd), retval);

	+       error = selscan(p, pibits[0], pobits[0], nd, retval);

	        if (error || *retval)

	                goto done;

	        if (SCARG(uap, tv)) {

	@@ -919,10 +917,7 @@

	  * differently.

	  */

	 int

	-sys_poll(p, v, retval)

	-       register struct proc *p;

	-       void *v;

	-       register_t *retval;

	+sys_poll(struct proc *p, void *v, register_t *retval)

	 {

	        struct sys_poll_args *uap = v;

	        size_t sz;

	@@ -931,13 +926,13 @@

	        struct timeval atv;

	        int timo, ncoll, i, s, error, error2;

	        extern int nselcoll, selwait;

	+       u_int nfds = SCARG(uap, nfds);

	 

	        /* Standards say no more than MAX_OPEN; this is possibly better. */

	-       if (SCARG(uap, nfds) > min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, 

	-           maxfiles))

	+       if (nfds > min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles))

	                return (EINVAL);

	 

	-       sz = sizeof(struct pollfd) * SCARG(uap, nfds);

	+       sz = sizeof(struct pollfd) * nfds;

	        

	        /* optimize for the default case, of a small nfds value */

	        if (sz > sizeof(pfds))

	@@ -946,7 +941,7 @@

	        if ((error = copyin(SCARG(uap, fds), pl, sz)) != 0)

	                goto bad;

	 

	-       for (i = 0; i < SCARG(uap, nfds); i++)

	+       for (i = 0; i < nfds; i++)

	                pl[i].revents = 0;

	 

	        if (msec != -1) {

	@@ -966,7 +961,7 @@

	 retry:

	        ncoll = nselcoll;

	        p->p_flag |= P_SELECT;

	-       pollscan(p, pl, SCARG(uap, nfds), retval);

	+       pollscan(p, pl, nfds, retval);

	        if (*retval)

	                goto done;

	        if (msec != -1) {

	

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH