Subject: kern/8904: Linux compatibility signal code is panic-friendly
To: None <gnats-bugs@gnats.netbsd.org>
From: None <dave@dtsp.co.nz>
List: netbsd-bugs
Date: 11/28/1999 10:57:37
>Number:         8904
>Category:       kern
>Synopsis:       Linux compatibility signal code is panic-friendly
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Nov 28 10:57:00 1999
>Last-Modified:
>Originator:     Dave Sainty
>Organization:
Dynamic Technology Services and Products Ltd (NZ)
>Release:        Current as of today
>Environment:
System: NetBSD tequila.dave.dtsp.co.nz 1.4K NetBSD 1.4K (TEQUILA) #7: Fri Sep 17 23:43:58 NZST 1999 dave@tequila.dave.dtsp.co.nz:/vol/tequila/userB/u2/NetBSD-current/src/sys/arch/i386/compile/TEQUILA i386


>Description:
	Running the setup program from Staroffice (off the official CD,
	version 5.1 I think), causes a panic.  This appears to be because it
	tries to call signal() on signal number 0x204f9860.

	See the code, sys/compat/linux/common/linux_sig_notalpha.c:

	linux_sys_signal(p, v, retval)
	register struct proc *p;
	void *v;
	register_t *retval;
	{
	struct linux_sys_signal_args /* {
		syscallarg(int) sig;
		syscallarg(linux_handler_t) handler;
	} */ *uap = v;
	struct sigaction nbsa, obsa;
	int error;

	nbsa.sa_handler = SCARG(uap, handler);
	sigemptyset(&nbsa.sa_mask);
	nbsa.sa_flags = SA_RESETHAND | SA_NODEFER;
	error = sigaction1(p, linux_to_native_sig[SCARG(uap, sig)],
	    &nbsa, &obsa);

	Note there is no bounds checking on the array index to
	linux_to_native_sig[].  signal() is not the only call guilty of this
	problem, several of the signal related calls make this mistake (at
	least sigaction() and kill()).

>How-To-Repeat:
	Run Staroffice setup program, or create the obvious exploit programs.
	I guess probably a linux kill(1) binary counts as an exploit program.

>Fix:
	Do bounds checking on the signal number, return EINVAL if it is out of
	range [0 < signum < int_sizeof(linux_to_native_sig)].  Probably
	wrapping the conversion in a function is best.

	No patch is included because there is an additional problem in
	that there is no simple way to get the actual array size of
	linux_to_native_sig[].
	
	% fgrep 'linux_to_native_sig[L' **/*.c
	arch/alpha/linux_sigarray.c:int linux_to_native_sig[LINUX_NSIG] = {
	arch/i386/linux_sigarray.c:int linux_to_native_sig[LINUX__NSIG] = {
	arch/m68k/linux_sigarray.c:int linux_to_native_sig[LINUX_NSIG] = {

	LINUX_NSIG is consistently 32
	LINUX__NSIG is consistently 64

	So the array is either 32 or 64 entries.  Perhaps this is a separate
	bug?  Currently it means that the array is architecture dependent.
>Audit-Trail:
>Unformatted: