Subject: kern/26468: unprivileged user can cause repeatable kernel panic
To: None <gnats-bugs@gnats.netbsd.org>
From: Andrew Brown <atatat@atatdot.net>
List: netbsd-bugs
Date: 07/28/2004 21:22:48
>Number:         26468
>Category:       kern
>Synopsis:       unprivileged user can cause repeatable kernel panic
>Confidential:   yes
>Severity:       critical
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jul 29 01:23:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator:     TheMan
>Release:        2.0G (2.0_BETA suspected as well; not verified yet)
>Organization:
none
>Environment:
	
System: NetBSD this 2.0G NetBSD 2.0G (THAT) #341: Mon Jul 26 21:42:06 EDT 2004  andrew@this:/usr/src/sys/arch/i386/compile/THAT i386

>Description:

unprivileged user can cause repeatable kernel panic
panic: kernel diagnostic assertion "p->p_nrlwps == 0" failed: \
    file "../../../../kern/kern_exit.c", line 780

>How-To-Repeat:

you need two ttys, so either use virtual consoles or log in remotely
twice.  we set two breakpoints in the silly program because we need it
to exist (it doesn't exist until you tell gdb to run it) and we want
it to stop before and after the fork.

				[[ start on tty#1 ]]
tty#1% cat > foo.c <<EOF
int
main(int argc, char *argv[])
{
    fork();
    printf("i am a meat popsicle\n");
    exit(0);
}
EOF
tty#1% gcc -o foo foo.c
tty#1% gdb foo
...
(gdb) b main
Breakpoint 1 at 0x8048832
(gdb) b printf
Breakpoint 2 at 0x80484b8
(gdb) r
Starting program: /home/andrew/src/hacks/shorty 
...
Breakpoint 1, 0x08048832 in main ()

				[[ switch to tty#2 ]]
tty#2% ps -jt#1 | grep foo
andrew 1073 1267 1073 a92280    1 I+   p5 0:00.07 gdb foo
andrew 1392 1073 1392 a92280    1 TX   p5 0:00.08 /home/andrew/foo
tty#2% sysctl -w proc.1392.stopfork=1
proc.1392.stopfork: 0 -> 1

				[[ back to tty#1, still in gdb ]]
(gdb) c
Continuing.
Breakpoint 2, 0xbdba4d00 in printf () from /usr/lib/libc.so.12

				[[back to tty#2 ]]

tty#2% ps -jt#1 | grep foo
andrew 1073 1267 1073 a92280    1 I+   p5 0:00.07 gdb foo
andrew 1208 1392 1392 a92280    1 ??   p5 0:00.00 /home/andrew/foo
andrew 1392 1073 1392 a92280    1 TX   p5 0:00.08 /home/andrew/foo

	(note that i don't remember what the flags
	 were exactly, so i've left them out)

tty#2% gdb foo 1208
...
(gdb) n
...
(gdb) n
...
(gdb) n
...
(gdb) n
...

keep just doing "next" in gdb and eventually the process exits (signal
5, iirc, though i'm not sure), and the kernel panics.  i suppose i
should have sent the child process a continue signal after attaching
with gdb, but i didn't.

note that while i've not verified this, i expect it also affects the
2.0 branch.  i'll be setting up a 2.0 machine to try this on later
this evening, with any luck, though if someone wants to try what i've
written above, that should be sufficient.  i went through this process
three times to make sure it wasn't random.

>Fix:

yes, please.
>Release-Note:
>Audit-Trail:
>Unformatted: