Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 30 Jul 2016 10:38:34 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        John Baldwin <jhb@freebsd.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org,  svn-src-head@freebsd.org
Subject:   Re: svn commit: r303503 - head/sys/kern
Message-ID:  <20160730101227.J1336@besplex.bde.org>
In-Reply-To: <201607292019.u6TKJE98050271@repo.freebsd.org>

index | next in thread | previous in thread | raw e-mail

On Fri, 29 Jul 2016, John Baldwin wrote:

> Log:
>  Don't treat NOCPU as a valid CPU to CPU_ISSET.
>
>  If a thread is created bound to a cpuset it might already be bound before
>  it's very first timeslice, and td_lastcpu will be NOCPU in that case.
>
>  MFC after:	1 week

Thanks.  Did you get this from your mail queue on 2016/05/08?
>
> Modified: head/sys/kern/sched_4bsd.c
> ==============================================================================
> --- head/sys/kern/sched_4bsd.c	Fri Jul 29 19:36:10 2016	(r303502)
> +++ head/sys/kern/sched_4bsd.c	Fri Jul 29 20:19:14 2016	(r303503)
> @@ -1241,7 +1241,7 @@ sched_pickcpu(struct thread *td)
>
> 	mtx_assert(&sched_lock, MA_OWNED);
>
> -	if (THREAD_CAN_SCHED(td, td->td_lastcpu))
> +	if (td->td_lastcpu != NOCPU && THREAD_CAN_SCHED(td, td->td_lastcpu))
> 		best = td->td_lastcpu;
> 	else
> 		best = NOCPU;

This bug was more fatal on amd64 than on i386.  td_last_cpu has a correct
(signed) type int and NOCPU is -1.  THREAD_CAN_SCHED uses unsigned type.
-1 becomes 0xFFFFFFFFFFFFFFFF in it on amd64 and 0xFFFFFFFF on i386.
The old mail says that these get shifted to 1/4 as big, but I think
the relevant value is more like 8 -- 8 bits per byte requires a byte
at offset 1/8 of of these values in a byte array for a bitmap, but the
array is of u_int or u_long so the array index is 1/32nd or 1/64 of
these values and the memory offset is 1/8.  Anyway, the final offset
is small enough to not always trap on i386 only.

When NOCPU was 255, t_lastcpu was u_char and the memory offset was 31
bytes.  This didn't even give a buffer overrun with MAXCPU = 254.

When td_lastcpu is NOCPU and the check doesn't trap, 'best' is set to
NOCPU in both cases and the code works.

Bruce


help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20160730101227.J1336>