NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/59220: accept(2): null pointer deref



>Number:         59220
>Category:       kern
>Synopsis:       accept(2): null pointer deref
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Mar 26 16:20:00 +0000 2025
>Originator:     Taylor R Campbell
>Release:        current, 10, 9, ...
>Organization:
The NetLOCAL_CONNWAIT Foundacrash
>Environment:
>Description:
uvm_fault(0x..., 0x0, 1) -> e
fatal page fault in supervisor mode
trap type 6 code 0 rip 0x... cs 0x8 rflags 0x10202 cr2 0 ilevel 0 rsp 0x...
curlwp 0x... pid 558.558 lowest kstack 0x...
kernel page fault trap, code=0
Stopped in pid 558.558 (t_unix) at      netbsd:solocked2+0x3:   movq    0(%rsi),%rdi
solocked2() at netbsd:solocked2+0x3
do_sys_accept() at netbsd:do_sys_accept+0x17f
sys_accept() at netbsd:sys_accept+0x48
syscall() at netbsd:syscall+0x112
--- syscall (number 30) ---
netbsd:syscall+0x112:
ds          b700
es          0
fs          87c0
gs          3940
rdi         ffff8e88bd7a64e0
rsi         0
rbp         ffff9b005540edc0
rbx         ffff8e88bd7a64e0
rdx         ffff8e88bd6abc00
rcx         7
rax         ffff8e88bcc0b700
r8          0
r9          0
r10         d103a0
r11         246
r12         ffff9b005540ee68
r13         ffff8e88bd7a6980
r14         ffff8e88bd975728
r15         ffff8e88bcc0b700
rip         ffffffff80e83c7e    solocked2+0x3
cs          0
rflags      10202
rsp         ffff9b005540ed98
ss          10
netbsd:solocked2+0x3:   movq    0(%rsi),%rdi
db{1}> 

(gdb) list *(solocked2+0x3)
0xffffffff80e842ce is in solocked2 (/home/riastradh/netbsd/current/src/sys/kern/uipc_socket2.c:1504).
1499            /*
1500             * Used only for diagnostic assertions, so so_lock should be
1501             * stable at this point, hence on need for atomic_load_*.
1502             */
1503            lock = so1->so_lock;
1504            if (lock != so2->so_lock)
1505                    return false;
1506            return mutex_owned(lock);
1507    }
1508    
(gdb) disas solocked2
Dump of assembler code for function solocked2:
   0xffffffff80e842cb <+0>:     mov    (%rdi),%rax
   0xffffffff80e842ce <+3>:     mov    (%rsi),%rdi
   0xffffffff80e842d1 <+6>:     cmp    %rax,%rdi
   0xffffffff80e842d4 <+9>:     je     0xffffffff80e842d9 <solocked2+14>
   0xffffffff80e842d6 <+11>:    xor    %eax,%eax
   0xffffffff80e842d8 <+13>:    retq   
   0xffffffff80e842d9 <+14>:    push   %rbp
   0xffffffff80e842da <+15>:    mov    %rsp,%rbp
   0xffffffff80e842dd <+18>:    callq  0xffffffff80de89d6 <mutex_owned>
   0xffffffff80e842e2 <+23>:    test   %eax,%eax
   0xffffffff80e842e4 <+25>:    setne  %al
   0xffffffff80e842e7 <+28>:    pop    %rbp
   0xffffffff80e842e8 <+29>:    retq   

>How-To-Repeat:
ATF_TC(sockaddr_un_local_connwait);
ATF_TC_HEAD(sockaddr_un_local_connwait, tc)
{

	atf_tc_set_md_var(tc, "descr", "Check that LOCAL_CONNWAIT works");
}

ATF_TC_BODY(sockaddr_un_local_connwait, tc)
{
	/* too annoying to fit this into the test(...) framework above */
	struct sockaddr_un sun = {.sun_family = AF_UNIX, .sun_path = "sock"};
	int listener, conn, acc;
	const int one = 1;
	struct pollfd pfd;
	int nfd, error;
	socklen_t errorlen = sizeof(error);

	RL(listener = socket(PF_LOCAL, SOCK_STREAM|SOCK_NONBLOCK, 0));
	RL(bind(listener, (const struct sockaddr *)&sun, sizeof(sun)));
	RL(listen(listener, 5));

	/* accept would block */
	ATF_REQUIRE_ERRNO(EAGAIN, accept(listener, NULL, NULL) == -1);

	/* success without accept if we don't set LOCAL_CONNWAIT */
	RL(conn = socket(PF_LOCAL, SOCK_STREAM|SOCK_NONBLOCK, 0));
	RL(connect(conn, (const struct sockaddr *)&sun, sizeof(sun)));
	RL(close(conn));

	/* accept should happen now; chuck the client */
	RL(acc = accept(listener, NULL, NULL));
	RL(close(acc));

	/* fail EINPROGRESS without accept if we do set LOCAL_CONNWAIT */
	RL(conn = socket(PF_LOCAL, SOCK_STREAM|SOCK_NONBLOCK, 0));
	RL(setsockopt(conn, SOL_LOCAL, LOCAL_CONNWAIT, &one, sizeof(one)));
	ATF_REQUIRE_ERRNO(EINPROGRESS,
	    connect(conn, (const struct sockaddr *)&sun, sizeof(sun)) == -1);
	ATF_REQUIRE_ERRNO(EALREADY,
	    connect(conn, (const struct sockaddr *)&sun, sizeof(sun)) == -1);

	/* accept should happen now and connect should finish */
	RL(acc = accept(listener, NULL, NULL));
	pfd = (struct pollfd){.fd = conn, .events = POLLOUT};
	RL(nfd = poll(&pfd, 1, 0));
	ATF_REQUIRE_MSG(pfd.revents & POLLOUT, "revents=0x%x", pfd.revents);
	RL(getsockopt(conn, SOL_SOCKET, SO_ERROR, &error, &errorlen));
	ATF_REQUIRE_MSG(errorlen == sizeof(error), "errorlen=%d", errorlen);
	ATF_REQUIRE_MSG(error == 0, "error=%d", error);

	RL(close(acc));
	RL(close(conn));
	RL(close(listener));
}

>Fix:
Yes, please!



Home | Main Index | Thread Index | Old Index