Bug 15434 - use-after-free in smbclient -L rpc_api_pipe_got_pdu() if RPC parsing fails
Summary: use-after-free in smbclient -L rpc_api_pipe_got_pdu() if RPC parsing fails
Status: NEW
Alias: None
Product: Samba 4.1 and newer
Classification: Unclassified
Component: libsmbclient (show other bugs)
Version: unspecified
Hardware: All All
: P5 normal (vote)
Target Milestone: ---
Assignee: Samba QA Contact
QA Contact: Samba QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-07-25 09:41 UTC by Robert Morris
Modified: 2023-07-25 09:41 UTC (History)
0 users

See Also:


Attachments
fake smb server that causes smbclient -L's rpc_api_pipe_got_pdu() to use a freed heap block (14.32 KB, text/x-csrc)
2023-07-25 09:41 UTC, Robert Morris
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Robert Morris 2023-07-25 09:41:53 UTC
Created attachment 17998 [details]
fake smb server that causes smbclient -L's rpc_api_pipe_got_pdu() to use a freed heap block

In this code in rpc_api_pipe_got_pdu() in source3/rpc_client/cli_pipe.c:

        status = dcerpc_pull_ncacn_packet(state->pkt,
                                          &state->incoming_frag,
                                          state->pkt);
        if (tevent_req_nterror(req, status)) {
                ...;
                TALLOC_FREE(state->cli->transport);

If status is not OK, then state is freed inside the call to
tevent_req_nterror(), and thus state->cli->transport is a dereference
of an undefined pointer.

Here's a backtrace showing how tevent_req_nterror() frees state:

#0  rpc_pipe_bind_step_one_done (subreq=0x8042a52d0)
    at ../../source3/rpc_client/cli_pipe.c:1856
#1  0x0000000001c0a066 in _tevent_req_notify_callback (req=0x8042a52d0, 
    location=0x1319be7 "../../source3/rpc_client/cli_pipe.c:906")
    at ../../lib/tevent/tevent_req.c:151
#2  0x0000000001c0a224 in tevent_req_finish (req=0x8042a52d0, 
    state=TEVENT_REQ_USER_ERROR, 
    location=0x1319be7 "../../source3/rpc_client/cli_pipe.c:906")
    at ../../lib/tevent/tevent_req.c:203
#3  0x0000000001c0a296 in _tevent_req_error (req=0x8042a52d0, 
    error=10483072397370982435, 
    location=0x1319be7 "../../source3/rpc_client/cli_pipe.c:906")
    at ../../lib/tevent/tevent_req.c:221
#4  0x00000000017a4579 in _tevent_req_nterror (req=0x8042a52d0, status=..., 
    location=0x1319be7 "../../source3/rpc_client/cli_pipe.c:906")
    at ../../lib/util/tevent_ntstatus.c:46
#5  0x0000000001be8840 in rpc_api_pipe_got_pdu (subreq=0x0)
    at ../../source3/rpc_client/cli_pipe.c:906

cli_pipe.c line 1856 is

        TALLOC_FREE(subreq);

and subreq is the same as req in rpc_api_pipe_got_pdu().

I've attached a fake smb server that produces this problem in
smbclient -L; the the broken RPC reply generated in my program's
smb_read() is what causes dcerpc_pull_ncacn_packet() to return an
error.

Here's the backtrace at the point of the crash (with a debugging
allocator that fills freed blocks with junk):

Program received signal SIGBUS, Bus error.
Object-specific hardware error.
0x0000000001be885a in rpc_api_pipe_got_pdu (subreq=0x0)
    at ../../source3/rpc_client/cli_pipe.c:912
912                     TALLOC_FREE(state->cli->transport);
(gdb) where
#0  0x0000000001be885a in rpc_api_pipe_got_pdu (subreq=0x0)
    at ../../source3/rpc_client/cli_pipe.c:912
#1  0x0000000001c0a066 in _tevent_req_notify_callback (req=0x8042ae180, 
    location=0x142a5f9 "../../source3/rpc_client/cli_pipe.c:295")
    at ../../lib/tevent/tevent_req.c:151
#2  0x0000000001c0a224 in tevent_req_finish (req=0x8042ae180, 
    state=TEVENT_REQ_DONE, 
    location=0x142a5f9 "../../source3/rpc_client/cli_pipe.c:295")
    at ../../lib/tevent/tevent_req.c:203
#3  0x0000000001c0a377 in tevent_req_trigger (ev=0x8042a4300, im=0x8042ae4d0, 
    private_data=0x8042ae180) at ../../lib/tevent/tevent_req.c:260
#4  0x0000000001c08862 in tevent_common_invoke_immediate_handler (
    im=0x8042ae4d0, removed=0x0) at ../../lib/tevent/tevent_immediate.c:190
#5  0x0000000001c089d9 in tevent_common_loop_immediate (ev=0x8042a4300)
    at ../../lib/tevent/tevent_immediate.c:236
#6  0x0000000001c0d04b in poll_event_loop_once (ev=0x8042a4300, 
    location=0x12ae924 "../../lib/tevent/tevent_req.c:310")
    at ../../lib/tevent/tevent_poll.c:617
#7  0x0000000001c06204 in _tevent_loop_once (ev=0x8042a4300, 
    location=0x12ae924 "../../lib/tevent/tevent_req.c:310")
    at ../../lib/tevent/tevent.c:823
#8  0x0000000001c0a576 in tevent_req_poll (req=0x8042a46e0, ev=0x8042a4300)
    at ../../lib/tevent/tevent_req.c:310
#9  0x00000000017a47ff in tevent_req_poll_ntstatus (req=0x8042a46e0, 
    ev=0x8042a4300, status=0x7fffffffdea0)
    at ../../lib/util/tevent_ntstatus.c:109
#10 0x0000000001be370f in rpc_pipe_bind (cli=0x804298bd0, auth=0x80429d5b0)
    at ../../source3/rpc_client/cli_pipe.c:2055
#11 0x0000000001be5d5f in cli_rpc_pipe_open_noauth_transport (cli=0x80426f780, 
    transport=NCACN_NP, table=0x2753d58 <ndr_table_srvsvc>, 
    remote_name=0x80426fda0 "x", remote_sockaddr=0x80426fae8, 
    presult=0x7fffffffe048) at ../../source3/rpc_client/cli_pipe.c:3390
#12 0x0000000001be6064 in cli_rpc_pipe_open_noauth (cli=0x80426f780, 
    table=0x2753d58 <ndr_table_srvsvc>, presult=0x7fffffffe048)
    at ../../source3/rpc_client/cli_pipe.c:3427
#13 0x00000000025616c1 in browse_host_rpc (sort=true)
    at ../../source3/client/client.c:4888
#14 0x00000000025613a6 in browse_host (sort=true)
    at ../../source3/client/client.c:4943
#15 0x0000000002552eb8 in do_host_query (query_host=0x804259340 "x")
    at ../../source3/client/client.c:6230
#16 0x00000000025528f0 in main (argc=9, argv=0x7fffffffe6e0)
    at ../../source3/client/client.c:6724