Bug 13027 - shadow_copy2 calls smb_panic on unreadable parent directory
Summary: shadow_copy2 calls smb_panic on unreadable parent directory
Status: RESOLVED FIXED
Alias: None
Product: Samba 4.1 and newer
Classification: Unclassified
Component: VFS Modules (show other bugs)
Version: 4.6.4
Hardware: All All
: P5 normal (vote)
Target Milestone: ---
Assignee: Karolin Seeger
QA Contact: Samba QA Contact
URL:
Keywords:
Depends on: 13068 13069
Blocks:
  Show dependency treegraph
 
Reported: 2017-09-11 17:29 UTC by Brian De Wolf
Modified: 2018-01-05 23:42 UTC (History)
3 users (show)

See Also:


Attachments
git-am fix for master (1.96 KB, patch)
2017-09-13 18:39 UTC, Jeremy Allison
no flags Details
Updated git-am patch for master. (3.06 KB, patch)
2017-09-14 20:33 UTC, Jeremy Allison
no flags Details
Prerequisite patch (2.73 KB, patch)
2017-10-03 18:25 UTC, Jeremy Allison
no flags Details
generic patch for smbd (3.09 KB, patch)
2017-10-04 19:57 UTC, Jeremy Allison
no flags Details
git-am fix for 4.7.next. (3.51 KB, patch)
2017-10-10 18:37 UTC, Jeremy Allison
slow: review+
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Brian De Wolf 2017-09-11 17:29:00 UTC
We upgraded from 4.3.11 to 4.6.4 and during the next business day we started seeing panics.  Here is the logs/backtrace:

[2017/09/08 09:33:16.001228,  0, pid=24759] ../source3/lib/util.c:791(smb_panic_s3)
  PANIC (pid 24759): getwd failed
  
[2017/09/08 09:33:16.001683,  0, pid=24759] ../source3/lib/util.c:902(log_stack_trace)
  BACKTRACE: 26 stack frames:
   #0 /usr/pkg/lib/libsmbconf.so.0'log_stack_trace+0x2d [0xfdfdb6cd]
   #1 /usr/pkg/lib/libsmbconf.so.0'smb_panic_s3+0x2b [0xfdfdb7fb]
   #2 /usr/pkg/lib/libsamba-util.so.0.0.1'smb_panic+0x36 [0xfedac546]
   #3 /usr/pkg/lib/samba/vfs/shadow_copy2.so'shadow_copy2_chdir+0x377 [0xfb87ad67]
   #4 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'smb_vfs_call_chdir+0x33 [0xfe51bad3]
   #5 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'vfs_ChDir+0x5e [0xfe51cc6e]
   #6 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'open_dir_safely+0x40 [0xfe4ae0a0]
   #7 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'get_real_filename_full_scan+0xe2 [0xfe503b82]
   #8 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'unix_convert+0xad4 [0xfe504c44]
   #9 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'filename_convert_internal+0xfc [0xfe505d9c]
   #10 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'filename_convert+0x46 [0xfe5060f6]
   #11 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'smbd_smb2_request_process_create+0x244c [0xfe551cbc]
   #12 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'smbd_smb2_request_dispatch+0x1074 [0xfe546ac4]
   #13 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'smbd_smb2_connection_handler+0x6bf [0xfe54786f]
   #14 /usr/pkg/lib/samba/private/libtevent.so.0.9.31'port_event_loop_once+0x2de [0xfe7cb22e]
   #15 /usr/pkg/lib/samba/private/libtevent.so.0.9.31'_tevent_loop_once+0xa3 [0xfe7c50d3]
   #16 /usr/pkg/lib/samba/private/libtevent.so.0.9.31'tevent_common_loop_wait+0x2c [0xfe7c52fc]
   #17 /usr/pkg/lib/samba/private/libtevent.so.0.9.31'_tevent_loop_wait+0x18 [0xfe7c5398]
   #18 /usr/pkg/lib/samba/private/libsmbd-base-samba4.so'smbd_process+0x855 [0xfe533955]
   #19 /usr/pkg/sbin/smbd'smbd_accept_connection+0x281 [0x805c491]
   #20 /usr/pkg/lib/samba/private/libtevent.so.0.9.31'port_event_loop_once+0x2de [0xfe7cb22e]
   #21 /usr/pkg/lib/samba/private/libtevent.so.0.9.31'_tevent_loop_once+0xa3 [0xfe7c50d3]
   #22 /usr/pkg/lib/samba/private/libtevent.so.0.9.31'tevent_common_loop_wait+0x2c [0xfe7c52fc]
   #23 /usr/pkg/lib/samba/private/libtevent.so.0.9.31'_tevent_loop_wait+0x18 [0xfe7c5398]
   #24 /usr/pkg/sbin/smbd'main+0x1a5f [0x805f35f]
   #25 /usr/pkg/sbin/smbd'_start+0x83 [0x8056653]

The error string and backtrace point to this line:

https://github.com/samba-team/samba/blob/v4-6-stable/source3/modules/vfs_shadow_copy2.c#L1516

It appears the changes to the shadow_copy2 module have introduced an easily triggered smb_panic by having a hard dependency on GETWD.  In our environment, GETWD uses getcwd(3), which generates the working directory by traversing up parent directories and reading their names.  Since traversing into directories only requires search and not read, this panic can be reliably triggered if the share has any search-only directories with readable subdirectories and shadow_copy2 enabled.

Our current workaround is to disable shadow_copy2.
Comment 1 Paul B. Henson 2017-09-11 18:35:38 UTC
I would consider this a serious security bug. Basically any authenticated user with write access to a share with shadow copy enabled can set the permissions on a directory to trigger this panic and crash the server, resulting in a DoS.
Comment 2 Jeremy Allison 2017-09-11 19:09:28 UTC
Not a serious security bug, sorry. It's a DOS but from an authenticated user, yes.

The getwd() fix is a necessary one for security race conditions so that can't be reverted.

What environment are you using where "In our environment, GETWD uses getcwd(3)" ?

No modern Linux or FreeBSD does this to my knowledge.
Comment 3 Paul B. Henson 2017-09-11 19:21:42 UTC
Well, yes, it would definitely be worse if it was an unauthenticated DoS; perhaps I'd call that critical ;). But still, I'd saying having any random user able to DoS your service, particularly in an environment where you don't necessarily trust your random users (educational institution, students 8-/), is pretty serious.

We're running samba under OmniOS, which is a distribution of illumos, the fork of OpenSolaris from when Oracle shut it down. I'm assuming commercial Solaris would have the same issue but have not verified it.
Comment 4 Jeremy Allison 2017-09-11 20:12:03 UTC
Any chance you can move off to Linux / FreeBSD ? Depending on Solaris is not a good long term solution...

https://twitter.com/webmink/status/904081073256243201
Comment 5 Paul B. Henson 2017-09-11 20:35:34 UTC
We're not depending on Solaris; as I said we're running OmniOS, an illumos distribution:

https://wiki.illumos.org/display/illumos/illumos+Home

While illumos is a fork of OpenSolaris, it has zero dependencies on commercial Solaris or Oracle, and the death of either is irrelevant to its use or viability (Oh, if only Oracle would die, if only, if only). There are a number of otyher widely used open source illumos based distributions such as OpenIndiana or SmartOS, as well as commercial products based on it such as Nexenta or Delphix. It's not going anywhere.
Comment 6 Jeremy Allison 2017-09-11 20:38:08 UTC
Can you get me a backtrace with symbols. I'll take a look, but we're not going to be able to remove the GETWD code, it is a vital security requirement. It's possible the best we can do is note that shadow_copy2 is incompatible with Solaris-based systems.
Comment 7 Paul B. Henson 2017-09-11 20:44:09 UTC
My colleague will follow up on the backtrace.

Can you at least make it fail in a way that doesn't crash the entire service? I haven't had a chance to look at the code in detail myself yet, but is there any way if the getwd fails to just make shadow copies not work/fail on that share for that user as opposed to killing off the entire process? It seems a bit excessive for a security check for one user on one share to completely remove access to all shares for all users when it fails.
Comment 8 Jeremy Allison 2017-09-11 20:49:50 UTC
It depends. When I see the full backtrace I'll know. It panics as it thinks someone is trying to symlink race the server, which we must not allow.
Comment 9 Brian De Wolf 2017-09-12 20:44:44 UTC
Reproduced with smbclient by connecting and doing the following steps, where the first "New folder" has read permission removed:

smb: \> cd "New folder"
smb: \New folder\> cd "New folder"
smb: \New folder\New folder\> ls
NT_STATUS_IO_TIMEOUT listing \New folder\New folder\*

gdb bt full after breaking on smb_panic:

#0  smb_panic (why=why@entry=0xfb84f279 "getwd failed\n") at ../lib/util/fault.c:164
No locals.
#1  0xfb84ad67 in store_cwd_data (connectpath=0x0, handle=0x80b1010) at ../source3/modules/vfs_shadow_copy2.c:1516
        priv = 0x80b0eb0
        cwd = 0x0
#2  shadow_copy2_chdir (handle=0x80b1010, fname=<optimized out>) at ../source3/modules/vfs_shadow_copy2.c:1574
        timestamp = 0
        stripped = 0x0
        snappath = 0x0
        ret = 0
        saved_errno = 0
        conv = 0x0
        rootpath_len = 0
#3  0xfe51bad3 in smb_vfs_call_chdir (handle=<optimized out>, path=path@entry=0x80b6e60 "New folder/New folder") at ../source3/smbd/vfs.c:2099
No locals.
#4  0xfe51cc6e in vfs_ChDir (conn=conn@entry=0x80b1fc8, path=0x80b6e60 "New folder/New folder") at ../source3/smbd/vfs.c:876
        ret = <optimized out>
        __FUNCTION__ = "vfs_ChDir"
#5  0xfe4ae0a0 in open_dir_safely (ctx=0x0, conn=0x80b1fc8, smb_dname=0x80b6dc0, wcard=0x80b6c00 "*", attr=22) at ../source3/smbd/dir.c:1689
        dir_hnd = 0x0
        smb_fname_cwd = 0x0
        saved_dir = 0x80b02e0 "/export/user/bldewolf"
#6  0xfe4af577 in OpenDir (mem_ctx=<optimized out>, mem_ctx@entry=0x0, conn=<optimized out>, conn@entry=0x80b1fc8, smb_dname=<optimized out>, smb_dname@entry=0x80b6dc0, mask=mask@entry=0x80b6c00 "*", attr=attr@entry=22)
    at ../source3/smbd/dir.c:1744
No locals.
#7  0xfe4b0219 in dptr_create (conn=0x80b1fc8, req=req@entry=0x80b6750, fsp=fsp@entry=0x0, smb_dname=0x80b68d0, old_handle=old_handle@entry=false, expect_close=expect_close@entry=true, spid=5746, wcard=0x80b6c00 "*", wcard_has_wild=true, 
    attr=22, dptr_ret=dptr_ret@entry=0x80472b8) at ../source3/smbd/dir.c:533
        ret = <optimized out>
        backup_intent = <optimized out>
        status = <optimized out>
        smb_dname_cp = 0x80b6dc0
        sconn = 0x80a3170
        dptr = 0x0
        dir_hnd = <optimized out>
        __FUNCTION__ = "dptr_create"
#8  0xfe4ef31d in call_trans2findfirst (conn=conn@entry=0x80b1fc8, req=req@entry=0x80b6750, pparams=pparams@entry=0x80b01c4, total_params=62, ppdata=ppdata@entry=0x80b01cc, total_data=0, max_data_bytes=65535)
    at ../source3/smbd/trans2.c:2815
        params = <optimized out>
        pdata = 0x80b9cf0 ""
        data_end = <optimized out>
        dirtype = <optimized out>
        maxentries = <optimized out>
        findfirst_flags = <optimized out>
        close_after_first = <optimized out>
        close_if_end = <optimized out>
        requires_resume_key = <optimized out>
        info_level = <optimized out>
        directory = 0x80b6970 "New folder/New folder"
        mask = <optimized out>
        p = 0x80b6985 ""
        last_entry_off = 0
        dptr_num = -1
        numentries = 0
        i = <optimized out>
        finished = false
        dont_descend = false
        out_of_space = false
        space_remaining = <optimized out>
        mask_contains_wcard = true
        ea_list = <optimized out>
        ntstatus = {v = 0}
        ask_sharemode = <optimized out>
        dirptr = 0x0
        sconn = <optimized out>
        ucf_flags = <optimized out>
        backup_priv = <optimized out>
        as_root = <optimized out>
        __FUNCTION__ = "call_trans2findfirst"
#9  0xfe4fb236 in handle_trans2 (conn=conn@entry=0x80b1fc8, req=req@entry=0x80b6750, state=state@entry=0x80b0180) at ../source3/smbd/trans2.c:9334
        __FUNCTION__ = "handle_trans2"
#10 0xfe4ff1b6 in reply_trans2 (req=0x80b6750) at ../source3/smbd/trans2.c:9620
        conn = 0x80b1fc8
        dsoff = 132
        dscnt = <optimized out>
        psoff = 68
        pscnt = 62
        tran_call = <optimized out>
        state = 0x80b0180
        result = <optimized out>
        __FUNCTION__ = "reply_trans2"
#11 0xfe52e58d in switch_message (type=<optimized out>, req=req@entry=0x80b6750) at ../source3/smbd/process.c:1726
        flags = <optimized out>
        session_tag = <optimized out>
        conn = <optimized out>
        xconn = <optimized out>
        now = <optimized out>
        session = 0x809ae20
        status = <optimized out>
        __FUNCTION__ = "switch_message"
#12 0xfe5306ca in construct_reply (deferred_pcd=0x0, encrypted=false, seqnum=0, unread_bytes=0, size=136, inbuf=0x0, xconn=0x809be58) at ../source3/smbd/process.c:1762
        sconn = <optimized out>
        req = 0x80b6750
#13 process_smb (xconn=xconn@entry=0x809be58, inbuf=<optimized out>, nread=136, unread_bytes=0, seqnum=0, encrypted=false, deferred_pcd=deferred_pcd@entry=0x0) at ../source3/smbd/process.c:2008
        sconn = 0x80a3170
        msg_type = <optimized out>
        __FUNCTION__ = "process_smb"
#14 0xfe532223 in smbd_server_connection_read_handler (xconn=0x809be58, fd=<optimized out>) at ../source3/smbd/process.c:2608
        inbuf = 0x80b6690 ""
        inbuf_len = 136
        unread_bytes = 0
        encrypted = false
        mem_ctx = 0x80b6660
        status = {v = 0}
        seqnum = 0
        async_echo = <optimized out>
        from_client = <optimized out>
        __FUNCTION__ = "smbd_server_connection_read_handler"
#15 0xfe7cb22e in port_event_loop (tvalp=0x8047650, port_ev=0x80963c0) at ../lib/tevent/tevent_port.c:603
        mpx_fde = <optimized out>
        fde = <optimized out>
        flags = <optimized out>
        val = <optimized out>
        ret = <optimized out>
        nget = 1
        max_events = 1
        i = 0
        port_errno = <optimized out>
        events = {{portev_events = 1, portev_source = 4, portev_pad = 0, portev_object = 10, portev_user = 0x80a6190}}
        ts = {tv_sec = 42, tv_nsec = 290369000}
        ev = 0x8096318
#16 port_event_loop_once (ev=0x8096318, location=0xfe6b68ec "../source3/smbd/process.c:4125") at ../lib/tevent/tevent_port.c:781
        port_ev = 0x80963c0
        tval = {tv_sec = 42, tv_usec = 290369}
#17 0xfe7c50d3 in _tevent_loop_once (ev=ev@entry=0x8096318, location=location@entry=0xfe6b68ec "../source3/smbd/process.c:4125") at ../lib/tevent/tevent.c:721
        ret = <optimized out>
        nesting_stack_ptr = 0x0
#18 0xfe7c52fc in tevent_common_loop_wait (ev=0x8096318, location=0xfe6b68ec "../source3/smbd/process.c:4125") at ../lib/tevent/tevent.c:844
        ret = <optimized out>
#19 0xfe7c5398 in _tevent_loop_wait (ev=0x8096318, location=location@entry=0xfe6b68ec "../source3/smbd/process.c:4125") at ../lib/tevent/tevent.c:863
No locals.
#20 0xfe533955 in smbd_process (ev_ctx=ev_ctx@entry=0x8096318, msg_ctx=msg_ctx@entry=0x8098448, sock_fd=sock_fd@entry=10, interactive=interactive@entry=false) at ../source3/smbd/process.c:4125
        trace_state = {ev = 0x8096318, frame = 0x80b6660}
        client = 0x80a2ab0
        sconn = 0x80a3170
        xconn = 0x809be58
        locaddr = <optimized out>
        remaddr = <optimized out>
        ret = <optimized out>
        status = <optimized out>
        tv = {tv_sec = 1505246493, tv_usec = 194018}
        now = <optimized out>
        chroot_dir = <optimized out>
        rc = <optimized out>
        __func__ = "smbd_process"
        __FUNCTION__ = "smbd_process"
#21 0x0805c491 in smbd_accept_connection (ev=0x8096318, fde=0x80a5ad0, flags=1, private_data=0x80a3220) at ../source3/smbd/server.c:1017
        status = {v = 0}
        s = 0x0
        msg_ctx = 0x8098448
        addr = {ss_family = 26, _ss_pad1 = "\347\200\000\000\000", _ss_align = 1.4583677777643215e-302, 
          _ss_pad2 = "\000\000\000\002\356\356\356\356\000\000\000\000\000\000\000\000\000\000g\374\004\bg\374@1\n\bhx\004\b\000\000\000\000\004\bg\374.\200Y\374\253\070\204\376\000\000g\374\004\bg\374@1\n\b\210x\004\b\213\201Y\374\004\bg\374\000\000\000\000\310x\004\b\330l`\374\004\bg\374\000\000\000\000\000\000\000\000n(\204\376@1\n\b\250\223\t\b\004\bg\374\re`\374\004\bg\374\000\000\000\000\by\004\b\371\234|\376\020y\004\b|\352\t\b\330x\004\b\000\000\000\000\004\bg\374\000\000\000\000\333\234|\376\\\311}\376p\352\t\b\020y\004\b8y\004\b5\243|\376\030y\004\b\020y\004\b|\352\t\b\000\000\000\000\004\bg\374"...}
        in_addrlen = 32
        fd = 10
        pid = <optimized out>
        __FUNCTION__ = "smbd_accept_connection"
#22 0xfe7cb22e in port_event_loop (tvalp=0x8047980, port_ev=0x80963c0) at ../lib/tevent/tevent_port.c:603
        mpx_fde = <optimized out>
        fde = <optimized out>
        flags = <optimized out>
        val = <optimized out>
        ret = <optimized out>
        nget = 1
        max_events = 1
        i = 0
        port_errno = <optimized out>
        events = {{portev_events = 1, portev_source = 4, portev_pad = 0, portev_object = 37, portev_user = 0x80a6848}}
        ts = {tv_sec = 746, tv_nsec = 335205000}
        ev = 0x8096318
#23 port_event_loop_once (ev=0x8096318, location=0x8062ec9 "../source3/smbd/server.c:1384") at ../lib/tevent/tevent_port.c:781
        port_ev = 0x80963c0
        tval = {tv_sec = 746, tv_usec = 335205}
#24 0xfe7c50d3 in _tevent_loop_once (ev=ev@entry=0x8096318, location=location@entry=0x8062ec9 "../source3/smbd/server.c:1384") at ../lib/tevent/tevent.c:721
        ret = <optimized out>
        nesting_stack_ptr = 0x0
#25 0xfe7c52fc in tevent_common_loop_wait (ev=0x8096318, location=0x8062ec9 "../source3/smbd/server.c:1384") at ../lib/tevent/tevent.c:844
        ret = <optimized out>
#26 0xfe7c5398 in _tevent_loop_wait (ev=0x8096318, location=location@entry=0x8062ec9 "../source3/smbd/server.c:1384") at ../lib/tevent/tevent.c:863
No locals.
#27 0x0805f35f in smbd_parent_loop (parent=<optimized out>, ev_ctx=<optimized out>) at ../source3/smbd/server.c:1384
        trace_state = {frame = 0x80a5b40}
        ret = 0
#28 main (argc=<optimized out>, argv=0x8047de0) at ../source3/smbd/server.c:2038
        is_daemon = <optimized out>
        interactive = <optimized out>
        Fork = <optimized out>
        no_process_group = <optimized out>
        log_stdout = <optimized out>
        ports = 0x0
        profile_level = 0x0
        opt = <optimized out>
        pc = <optimized out>
        print_build_options = <optimized out>
        main_server_id = {pid = 5833, task_id = 0, vnn = 4294967295, unique_id = 3380973686010842310}
        long_options = {{longName = 0x0, shortName = 0 '\000', argInfo = 4, arg = 0xfc759b60 <poptHelpOptions>, val = 0, descrip = 0x8063474 "Help options:", argDescrip = 0x0}, {longName = 0x8063482 "daemon", shortName = 68 'D', 
            argInfo = 0, arg = 0x0, val = 1000, descrip = 0x8063489 "Become a daemon (default)", argDescrip = 0x0}, {longName = 0x80634a3 "interactive", shortName = 105 'i', argInfo = 0, arg = 0x0, val = 1001, 
            descrip = 0x80614d0 "Run interactive (not a daemon)", argDescrip = 0x0}, {longName = 0x80634af "foreground", shortName = 70 'F', argInfo = 0, arg = 0x0, val = 1002, 
            descrip = 0x80614f0 "Run daemon in foreground (for daemontools, etc.)", argDescrip = 0x0}, {longName = 0x80634ba "no-process-group", shortName = 0 '\000', argInfo = 0, arg = 0x0, val = 1003, 
            descrip = 0x8061524 "Don't create a new process group", argDescrip = 0x0}, {longName = 0x80634cb "log-stdout", shortName = 83 'S', argInfo = 0, arg = 0x0, val = 1004, descrip = 0x80634d6 "Log to stdout", argDescrip = 0x0}, {
            longName = 0x80634e4 "build-options", shortName = 98 'b', argInfo = 0, arg = 0x0, val = 98, descrip = 0x80634f2 "Print build options", argDescrip = 0x0}, {longName = 0x8063506 "port", shortName = 112 'p', argInfo = 1, 
            arg = 0x8047b04, val = 0, descrip = 0x806350b "Listen on the specified ports", argDescrip = 0x0}, {longName = 0x8063529 "profiling-level", shortName = 80 'P', argInfo = 1, arg = 0x8047b08, val = 0, 
            descrip = 0x8063539 "Set profiling level", argDescrip = 0x806354d "PROFILE_LEVEL"}, {longName = 0x0, shortName = 0 '\000', argInfo = 4, arg = 0xfee238a0 <popt_common_samba>, val = 0, 
            descrip = 0x806355b "Common samba options:", argDescrip = 0x0}, {longName = 0x0, shortName = 0 '\000', argInfo = 0, arg = 0x0, val = 0, descrip = 0x0, argDescrip = 0x0}}
        parent = <optimized out>
        frame = <optimized out>
        status = <optimized out>
        ev_ctx = <optimized out>
        msg_ctx = <optimized out>
        server_id = {pid = 5834, task_id = 0, vnn = 4294967295, unique_id = 8775075741836112969}
        se = <optimized out>
        profiling_level = <optimized out>
        np_dir = <optimized out>
        smbd_shim_fns = {cancel_pending_lock_requests_by_fid = 0x805651c <smbd_cancel_pending_lock_requests_by_fid@plt>, send_stat_cache_delete_message = 0x805652c <smbd_send_stat_cache_delete_message@plt>, 
          change_to_root_user = 0x805653c <smbd_change_to_root_user@plt>, become_authenticated_pipe_user = 0x805654c <smbd_become_authenticated_pipe_user@plt>, 
          unbecome_authenticated_pipe_user = 0x805655c <smbd_unbecome_authenticated_pipe_user@plt>, contend_level2_oplocks_begin = 0x805656c <smbd_contend_level2_oplocks_begin@plt>, 
          contend_level2_oplocks_end = 0x805657c <smbd_contend_level2_oplocks_end@plt>, become_root = 0x805658c <smbd_become_root@plt>, unbecome_root = 0x805659c <smbd_unbecome_root@plt>, exit_server = 0x80565ac <smbd_exit_server@plt>, 
          exit_server_cleanly = 0x80565bc <smbd_exit_server_cleanly@plt>}
        __FUNCTION__ = "main"
Comment 10 Jeremy Allison 2017-09-12 22:16:29 UTC
It's failing inside store_cwd_data(), which is only called from shadow_copy2_chdir() after the SMB_VFS_NEXT_CHDIR() has succeeded.

The only thing I can think of is doing a local patch that passes in the argument passed to SMB_VFS_NEXT_CHDIR(), and if the getwd() fails it uses that as the directory returned from GETWD().

This is inherently insecure though, and can't go upstream.

Can you give this a go and see if it fixes your problem ?
Comment 11 Paul B. Henson 2017-09-12 23:13:18 UTC
I'm certainly not advocating anything be done insecurely. In this scenario, I have no issue with service being denied if the getwd fails.

However, stepping back a moment, do you really agree with the design philosophy that if the getwd call fails for one user trying to access one share, the proper failure mode is to panic the entire samba server, killing off the parent process and all children, denying service to all users on all existing connections and any future users attempting to connect to any shares?

There's no way for this to fail securely and either simply not allow shadow copies to work for this user on this share, or even just not allow this user to access this share at all, rather than going nuclear on the entire process? If shadow copies are simply not enabled, the share works fine (and presumably securely) in this state, so denying access to shadow copies (rather than denying access to the whole share, let alone the whole server) when this condition arises would seem to maintain security without compromising availability?

Thanks...
Comment 12 Jeremy Allison 2017-09-13 18:31:40 UTC
The issue is the lower level shadow_copy2 code doesn't know what the upper level is doing. All it knows is a directory that it just chdir()'ed into is not resolvable with getwd(). That usually means shenanigans, so terminating is a fail safe here.

Samba is full of areas where:

chdir("....path....")
getwd() => error

is an immediate panic. If getwd() fails chdir should also fail.
Comment 13 Jeremy Allison 2017-09-13 18:39:16 UTC
Created attachment 13594 [details]
git-am fix for master

You know what. I think I was wrong in my previous comment.

Can you test the following patch ? It may fix the issue for you.

Cheers,

Jeremy.
Comment 14 Brian De Wolf 2017-09-14 18:11:53 UTC
I backported the patch to 4.6.4 and tested it out.  The server no longer panics, but things still get weird when looking at a broken perms nested directory.  If I try to create a file, it fails with bad permissions and starts returning access denied for the entire share until the server is restarted.

So I have three test cases currently:
4.6.4 patched with shadow_copy2: gives perm denied in test dir then starts denying entire share
4.6.4 no shadow_copy2: gives perm denied but still works outside bad perms test dir
4.3.11 with shadow_copy2: allows file creation/etc in the bad perms test dir

While fiddling with this, I wanted to see if the cwd of the samba process was getting mangled and found "pwdx".  I poked at "pwdx" and realized it readlink's /proc/self/path/cwd, which made me a bit annoyed that getcwd is unwilling to give out information readily available from proc.

So I made a quick LD_PRELOAD library that emulates getcwd and getwd by reading proc.  Running with this lib makes the 4.6.4 patched with shadow_copy2 testcase no longer deny permission to everything after being poked, so I suspect there's still some dependency on working getcwd/getwd lurking somewhere.

I'd also like to squish the regression of not being able to do file operations in a directory with an unreadable parent, but that looks like it might not be caused by broken getcwd/getwd operations.

I'll see if I can find some more time to poke at this more.
Comment 15 Jeremy Allison 2017-09-14 18:36:11 UTC
Yes, the patch isn't correct yet. It will leave us in the wrong directory. I realized that this morning in the shower. I'll fix this and upload a new version.
Comment 16 Jeremy Allison 2017-09-14 20:33:34 UTC
Created attachment 13601 [details]
Updated git-am patch for master.

Here's the update. Can you test ? Thanks ! Jeremy.
Comment 17 Brian De Wolf 2017-09-21 23:09:16 UTC
Sorry for the delay on this one.  I was having trouble getting a build with your latest patch going but I tried again with 4.7.0 and got it.

Viewing the folder shows its contents, but when I try to create a file in the folder I get this panic trace:

#0  0xfc5a1d85 in _lwp_kill () from /lib/libc.so.1
No symbol table info available.
#1  0xfc599422 in thr_kill () from /lib/libc.so.1
No symbol table info available.
#2  0xfc53672b in raise () from /lib/libc.so.1
No symbol table info available.
#3  0xfc51104e in abort () from /lib/libc.so.1
No symbol table info available.
#4  0xfdfcd7ef in dump_core () at ../source3/lib/dumpcore.c:338
        called = true
        __FUNCTION__ = "dump_core"
#5  0xfdfbbf24 in smb_panic_s3 (why=0xfb78fe57 "talloc failed\n") at ../source3/lib/util.c:827
        cmd = <optimized out>
        result = <optimized out>
        __FUNCTION__ = "smb_panic_s3"
#6  0xfed9cde6 in smb_panic (why=why@entry=0xfb78fe57 "talloc failed\n") at ../lib/util/fault.c:166
No locals.
#7  0xfb78b1d6 in store_cwd_data (connectpath=0x0, handle=0x80b2568) at ../source3/modules/vfs_shadow_copy2.c:1546
        priv = 0x80b25c0
        cwd_fname = 0x0
#8  shadow_copy2_chdir (handle=0x80b2568, smb_fname=0x80bbf20) at ../source3/modules/vfs_shadow_copy2.c:1625
        timestamp = 0
        stripped = 0x0
        snappath = 0x0
        ret = 0
        saved_errno = 0
        conv = 0x0
        rootpath_len = 0
        conv_smb_fname = 0x80bc400
        saved_cwd_fname = 0x80bc570
#9  0xfe597bc3 in smb_vfs_call_chdir (handle=<optimized out>, smb_fname=smb_fname@entry=0x80bbf20) at ../source3/smbd/vfs.c:2141
No locals.
#10 0xfe598c10 in vfs_ChDir (conn=conn@entry=0x809b6f0, smb_fname=smb_fname@entry=0x80bbf20) at ../source3/smbd/vfs.c:877
        ret = <optimized out>
        __FUNCTION__ = "vfs_ChDir"
#11 0xfe529e4e in open_dir_safely (ctx=0x80bbee0, conn=0x809b6f0, smb_dname=0x80bbf20, wcard=0x0, attr=0) at ../source3/smbd/dir.c:1690
        dir_hnd = 0x0
        smb_fname_cwd = 0x0
        saved_dir_fname = 0x80bc230
#12 0xfe52b327 in OpenDir (mem_ctx=<optimized out>, conn=<optimized out>, conn@entry=0x809b6f0, smb_dname=<optimized out>, smb_dname@entry=0x80bbf20, mask=mask@entry=0x0, attr=attr@entry=0) at ../source3/smbd/dir.c:1745
No locals.
#13 0xfe57f992 in get_real_filename_full_scan (conn=0x809b6f0, path=0x80bbe50 "New folder/New folder", path@entry=0x813445af <error: Cannot access memory at address 0x813445af>, name=0x80a8976 "New Text Document.txt", mangled=false, 
    mem_ctx=0x80bbee0, found_name=0x80470cc) at ../source3/smbd/filename.c:1381
        cur_dir = <optimized out>
        dname = 0x0
        talloced = <optimized out>
        unmangled_name = <optimized out>
        curpos = 134908278
        smb_fname = 0x80bbf20
        __FUNCTION__ = "get_real_filename_full_scan"
#14 0xfe57ff83 in get_real_filename (conn=0x80a8976, conn@entry=0x809b6f0, path=0x0, name=0x80bbee0 "\340\277\v\b\002", mem_ctx=0x80470cc, found_name=found_name@entry=0x80470cc) at ../source3/smbd/filename.c:1465
        ret = <optimized out>
        mangled = <optimized out>
#15 0xfe580aa4 in unix_convert (ctx=0x80c3248, conn=conn@entry=0x809b6f0, orig_path=0x80b08e8 "New folder/New folder/New Text Document.txt", smb_fname_out=0x804739c, ucf_flags=ucf_flags@entry=32) at ../source3/smbd/filename.c:920
        found_name = 0x0
        smb_fname = 0x80ae120
        cnull = 0 '\000'
        start = 0x80a8976 "New Text Document.txt"
        end = 0x0
        stream = 0x0
        component_was_mangled = false
        name_has_wildcard = false
        posix_pathnames = false
        allow_wcard_last_component = false
        save_last_component = false
        snapshot_path = false
        status = <optimized out>
        ret = <optimized out>
        __FUNCTION__ = "unix_convert"
#16 0xfe581c29 in filename_convert_internal (ctx=ctx@entry=0x80c3248, conn=conn@entry=0x809b6f0, smbreq=smbreq@entry=0x0, name_in=<optimized out>, name_in@entry=0x80b08e8 "New folder/New folder/New Text Document.txt", 
    ucf_flags=ucf_flags@entry=32, ppath_contains_wcard=ppath_contains_wcard@entry=0x0, pp_smb_fname=pp_smb_fname@entry=0x804739c) at ../source3/smbd/filename.c:1619
        status = <optimized out>
        __FUNCTION__ = "filename_convert_internal"
#17 0xfe581f9e in filename_convert (ctx=0x80c3248, conn=0x809b6f0, name_in=0x80b08e8 "New folder/New folder/New Text Document.txt", ucf_flags=32, ppath_contains_wcard=ppath_contains_wcard@entry=0x0, 
    pp_smb_fname=pp_smb_fname@entry=0x804739c) at ../source3/smbd/filename.c:1664
No locals.
#18 0xfe5ce0c8 in smbd_smb2_create_send (in_context_blobs=..., in_name=<optimized out>, in_create_options=<optimized out>, in_create_disposition=<optimized out>, in_share_access=<optimized out>, in_file_attributes=<optimized out>, 
    in_desired_access=<optimized out>, in_impersonation_level=<optimized out>, in_oplock_level=<optimized out>, smb2req=<optimized out>, ev=<optimized out>, mem_ctx=<optimized out>) at ../source3/smbd/smb2_create.c:1114
        smb_fname = 0x0
        ucf_flags = <optimized out>
        ea_list = <optimized out>
        sec_desc = <optimized out>
        durable_requested = <optimized out>
        need_replay_cache = <optimized out>
        mxac = <optimized out>
        max_access_time = <optimized out>
        allocation_size = <optimized out>
        lease_ptr = <optimized out>
        lease_len = <optimized out>
        op = 0x0
        fname = <optimized out>
        secd = <optimized out>
        _create_guid = {time_low = 1045307681, time_mid = 40099, time_hi_and_version = 4583, clock_seq = "\200\335", node = "\000PV\215Fd"}
        create_guid = <optimized out>
        do_durable_reconnect = <optimized out>
        persistent_id = <optimized out>
        exta = <optimized out>
        qfid = <optimized out>
        update_open = <optimized out>
        lease = {lease_key = {data = {18446673710247975600, 3954}}, lease_state = 7, lease_flags = 0, lease_duration = 0, parent_lease_key = {data = {0, 0}}, lease_version = 2, lease_epoch = 0}
        alsi = <optimized out>
        twrp = <optimized out>
        durable_timeout_msec = <optimized out>
        state = 0x80c3328
        smb1req = <optimized out>
        req = <optimized out>
        result = 0x0
        dhnc = <optimized out>
        dh2c = <optimized out>
        status = <optimized out>
        info = 0
        requested_oplock_level = <optimized out>
        rqls = <optimized out>
        dhnq = <optimized out>
        dh2q = <optimized out>
        replay_operation = <optimized out>
#19 smbd_smb2_request_process_create (smb2req=smb2req@entry=0x80c2968) at ../source3/smbd/smb2_create.c:227
        inbody = <optimized out>
        indyniov = <optimized out>
        in_oplock_level = <optimized out>
        in_impersonation_level = <optimized out>
        in_desired_access = <optimized out>
        in_file_attributes = <optimized out>
        in_share_access = <optimized out>
        in_create_disposition = <optimized out>
        in_create_options = <optimized out>
        in_name_offset = <optimized out>
        in_name_length = <optimized out>
        in_name_buffer = <optimized out>
        in_name_string = 0x80c2ce8 "New folder\\New folder\\New Text Document.txt"
        in_name_string_size = 43
        name_offset = <optimized out>
        name_available_length = <optimized out>
        in_context_offset = <optimized out>
        in_context_length = <optimized out>
        in_context_blobs = {num_blobs = 4, blobs = 0x80c3078}
        context_offset = <optimized out>
        context_available_length = <optimized out>
        dyn_offset = <optimized out>
        status = <optimized out>
        ok = <optimized out>
#20 0xfe5c30a4 in smbd_smb2_request_dispatch (req=req@entry=0x80c2968) at ../source3/smbd/smb2_server.c:2597
        xconn = <optimized out>
        call = <optimized out>
        intf_v = <optimized out>
        inhdr = <optimized out>
        opcode = <optimized out>
        flags = <optimized out>
        mid = <optimized out>
        status = <optimized out>
        session_status = <optimized out>
        allowed_flags = <optimized out>
        return_value = <optimized out>
        x = <optimized out>
        signing_required = <optimized out>
        encryption_desired = false
        encryption_required = <optimized out>
        __FUNCTION__ = "smbd_smb2_request_dispatch"
#21 0xfe5c3e4f in smbd_smb2_io_handler (fde_flags=<optimized out>, xconn=0x809cdc0) at ../source3/smbd/smb2_server.c:3890
        err = <optimized out>
        sconn = <optimized out>
        state = 0x809ce34
        req = <optimized out>
        min_recvfile_size = 4294967295
        ret = <optimized out>
        retry = false
        status = <optimized out>
        now = <optimized out>
#22 smbd_smb2_connection_handler (ev=0x8099b40, fde=0x80a93d8, flags=1, private_data=0x809cdc0) at ../source3/smbd/smb2_server.c:3928
        xconn = 0x809cdc0
        status = <optimized out>
#23 0xfe7cbc76 in epoll_event_loop (tvalp=0x80475ac, epoll_ev=0x80991f8) at ../lib/tevent/tevent_epoll.c:728
        fde = <optimized out>
        flags = <optimized out>
        mpx_fde = <optimized out>
        ret = <optimized out>
        i = 0
        timeout = <optimized out>
        wait_errno = <optimized out>
        events = {{events = 1, data = {ptr = 0x80a93d8, fd = 134910936, u32 = 134910936, u64 = 134910936}}}
#24 epoll_event_loop_once (ev=0x8099b40, location=0xfe6cba64 "../source3/smbd/process.c:4126") at ../lib/tevent/tevent_epoll.c:930
        epoll_ev = 0x80991f8
        tval = {tv_sec = 30, tv_usec = 843178}
        panic_triggered = false
#25 0xfe7c9c1e in std_event_loop_once (ev=0x8099b40, location=0xfe6cba64 "../source3/smbd/process.c:4126") at ../lib/tevent/tevent_standard.c:114
        glue_ptr = <optimized out>
        glue = 0x8099150
        ret = <optimized out>
#26 0xfe7c53d3 in _tevent_loop_once (ev=ev@entry=0x8099b40, location=location@entry=0xfe6cba64 "../source3/smbd/process.c:4126") at ../lib/tevent/tevent.c:726
        ret = <optimized out>
        nesting_stack_ptr = 0x0
#27 0xfe7c55fc in tevent_common_loop_wait (ev=0x8099b40, location=0xfe6cba64 "../source3/smbd/process.c:4126") at ../lib/tevent/tevent.c:849
        ret = <optimized out>
#28 0xfe7c9b9e in std_event_loop_wait (ev=0x8099b40, location=0xfe6cba64 "../source3/smbd/process.c:4126") at ../lib/tevent/tevent_standard.c:145
        glue_ptr = <optimized out>
        glue = 0x8099150
        ret = <optimized out>
#29 0xfe7c5698 in _tevent_loop_wait (ev=0x8099b40, location=location@entry=0xfe6cba64 "../source3/smbd/process.c:4126") at ../lib/tevent/tevent.c:868
No locals.
#30 0xfe5afce5 in smbd_process (ev_ctx=ev_ctx@entry=0x8099b40, msg_ctx=msg_ctx@entry=0x80992f0, sock_fd=sock_fd@entry=41, interactive=interactive@entry=false) at ../source3/smbd/process.c:4126
        trace_state = {ev = 0x8099b40, frame = 0x80bbee0}
        client = 0x80a3d08
        sconn = 0x80a8d98
        xconn = 0x809cdc0
        locaddr = <optimized out>
        remaddr = <optimized out>
        ret = <optimized out>
        status = <optimized out>
        tv = {tv_sec = 1506034990, tv_usec = 686316}
        now = <optimized out>
        chroot_dir = <optimized out>
        rc = <optimized out>
        __func__ = "smbd_process"
        __FUNCTION__ = "smbd_process"
#31 0x0805c7b1 in smbd_accept_connection (ev=0x8099b40, fde=0x80a4d10, flags=1, private_data=0x80a4cc0) at ../source3/smbd/server.c:1026
        status = {v = 0}
        s = 0x0
        msg_ctx = 0x80992f0
        addr = {ss_family = 2, _ss_pad1 = "\312+\206G\273F", _ss_align = 0, 
          _ss_pad2 = "\reY\374\004\b`\374\000\000\000\000\030x\004\b\000\000`\374\004\b`\374\250\247\t\b\030x\004\b\000\000\000\000\004\b`\374.\200R\374\273\070\204\376\000\000`\374\004\b`\374\250\247\t\b8x\004\b\213\201R\374\004\b`\374\000\000\000\000xx\004\b\021Y\332\376\224\257\205\376\000\000\000\000\210x\004\b~(\204\376\250\247\t\b(|\t\b\000\000\000\000\330lY\374\004\b`\374\000\000\000\000\270x\004\bY\241|\376\300x\004\b\324\371\t\b\004\b`\374\reY\374\004\b`\374\000\000\000\000;\241|\376\020\347}\376\310\371\t\b\300x\004\b\350x\004\b\225\247|\376\310x\004\b\300x\004\b\324\371\t\b\000\000`\374\004\b`\374"...}
        in_addrlen = 16
        fd = 41
        pid = <optimized out>
        __FUNCTION__ = "smbd_accept_connection"
#32 0xfe7cbc76 in epoll_event_loop (tvalp=0x804792c, epoll_ev=0x80991f8) at ../lib/tevent/tevent_epoll.c:728
        fde = <optimized out>
        flags = <optimized out>
        mpx_fde = <optimized out>
        ret = <optimized out>
        i = 0
        timeout = <optimized out>
        wait_errno = <optimized out>
        events = {{events = 1, data = {ptr = 0x80a4d10, fd = 134892816, u32 = 134892816, u64 = 134892816}}}
#33 epoll_event_loop_once (ev=0x8099b40, location=0x8063c6d "../source3/smbd/server.c:1393") at ../lib/tevent/tevent_epoll.c:930
        epoll_ev = 0x80991f8
        tval = {tv_sec = 883, tv_usec = 381616}
        panic_triggered = false
#34 0xfe7c9c1e in std_event_loop_once (ev=0x8099b40, location=0x8063c6d "../source3/smbd/server.c:1393") at ../lib/tevent/tevent_standard.c:114
        glue_ptr = <optimized out>
        glue = 0x8099150
        ret = <optimized out>
#35 0xfe7c53d3 in _tevent_loop_once (ev=ev@entry=0x8099b40, location=location@entry=0x8063c6d "../source3/smbd/server.c:1393") at ../lib/tevent/tevent.c:726
        ret = <optimized out>
        nesting_stack_ptr = 0x0
#36 0xfe7c55fc in tevent_common_loop_wait (ev=0x8099b40, location=0x8063c6d "../source3/smbd/server.c:1393") at ../lib/tevent/tevent.c:849
        ret = <optimized out>
#37 0xfe7c9b9e in std_event_loop_wait (ev=0x8099b40, location=0x8063c6d "../source3/smbd/server.c:1393") at ../lib/tevent/tevent_standard.c:145
        glue_ptr = <optimized out>
        glue = 0x8099150
        ret = <optimized out>
#38 0xfe7c5698 in _tevent_loop_wait (ev=0x8099b40, location=location@entry=0x8063c6d "../source3/smbd/server.c:1393") at ../lib/tevent/tevent.c:868
No locals.
#39 0x0805ef55 in smbd_parent_loop (parent=<optimized out>, ev_ctx=<optimized out>) at ../source3/smbd/server.c:1393
        trace_state = {frame = 0x80a3b50}
        ret = 0
#40 main (argc=<optimized out>, argv=0x8047de0) at ../source3/smbd/server.c:2160
        is_daemon = <optimized out>
        interactive = <optimized out>
        Fork = <optimized out>
        no_process_group = <optimized out>
        log_stdout = <optimized out>
        ports = 0x0
        profile_level = 0x0
        opt = <optimized out>
        pc = <optimized out>
        print_build_options = <optimized out>
        main_server_id = {pid = 17505, task_id = 0, vnn = 4294967295, unique_id = 3533014807489980013}
        long_options = {{longName = 0x0, shortName = 0 '\000', argInfo = 4, arg = 0xfc6e9b60 <poptHelpOptions>, val = 0, descrip = 0x8064253 "Help options:", argDescrip = 0x0}, {longName = 0x8064261 "daemon", shortName = 68 'D', 
            argInfo = 0, arg = 0x0, val = 1000, descrip = 0x8064268 "Become a daemon (default)", argDescrip = 0x0}, {longName = 0x8064282 "interactive", shortName = 105 'i', argInfo = 0, arg = 0x0, val = 1001, 
            descrip = 0x8061d74 "Run interactive (not a daemon)", argDescrip = 0x0}, {longName = 0x806428e "foreground", shortName = 70 'F', argInfo = 0, arg = 0x0, val = 1002, 
            descrip = 0x8061d94 "Run daemon in foreground (for daemontools, etc.)", argDescrip = 0x0}, {longName = 0x8064299 "no-process-group", shortName = 0 '\000', argInfo = 0, arg = 0x0, val = 1003, 
            descrip = 0x8061dc8 "Don't create a new process group", argDescrip = 0x0}, {longName = 0x80642aa "log-stdout", shortName = 83 'S', argInfo = 0, arg = 0x0, val = 1004, descrip = 0x80642b5 "Log to stdout", argDescrip = 0x0}, {
            longName = 0x80642c3 "build-options", shortName = 98 'b', argInfo = 0, arg = 0x0, val = 98, descrip = 0x80642d1 "Print build options", argDescrip = 0x0}, {longName = 0x80642e5 "port", shortName = 112 'p', argInfo = 1, 
            arg = 0x8047b04, val = 0, descrip = 0x80642ea "Listen on the specified ports", argDescrip = 0x0}, {longName = 0x8064308 "profiling-level", shortName = 80 'P', argInfo = 1, arg = 0x8047b08, val = 0, 
            descrip = 0x8064318 "Set profiling level", argDescrip = 0x806432c "PROFILE_LEVEL"}, {longName = 0x0, shortName = 0 '\000', argInfo = 4, arg = 0xfee239e0 <popt_common_samba>, val = 0, 
            descrip = 0x806433a "Common samba options:", argDescrip = 0x0}, {longName = 0x0, shortName = 0 '\000', argInfo = 0, arg = 0x0, val = 0, descrip = 0x0, argDescrip = 0x0}}
        parent = <optimized out>
        frame = <optimized out>
        status = <optimized out>
        ev_ctx = <optimized out>
        msg_ctx = <optimized out>
        server_id = {pid = 17506, task_id = 0, vnn = 4294967295, unique_id = 11824355283717389693}
        se = <optimized out>
        profiling_level = <optimized out>
        np_dir = <optimized out>
        smbd_shim_fns = {cancel_pending_lock_requests_by_fid = 0x8056794 <smbd_cancel_pending_lock_requests_by_fid@plt>, send_stat_cache_delete_message = 0x80567a4 <smbd_send_stat_cache_delete_message@plt>, 
          change_to_root_user = 0x80567b4 <smbd_change_to_root_user@plt>, become_authenticated_pipe_user = 0x80567c4 <smbd_become_authenticated_pipe_user@plt>, 
          unbecome_authenticated_pipe_user = 0x80567d4 <smbd_unbecome_authenticated_pipe_user@plt>, contend_level2_oplocks_begin = 0x80567e4 <smbd_contend_level2_oplocks_begin@plt>, 
          contend_level2_oplocks_end = 0x80567f4 <smbd_contend_level2_oplocks_end@plt>, become_root = 0x8056804 <smbd_become_root@plt>, unbecome_root = 0x8056814 <smbd_unbecome_root@plt>, exit_server = 0x8056824 <smbd_exit_server@plt>, 
          exit_server_cleanly = 0x8056834 <smbd_exit_server_cleanly@plt>}
        __FUNCTION__ = "main"
        __func__ = "main"
quit
Detaching from program: /usr/pkg/sbin/smbd, process 17516
Comment 18 Jeremy Allison 2017-09-22 17:51:10 UTC
You're going to need to walk into this with gdb to debug. Add the line:

panic action = /bin/sleep 99999

to the [global] section of your smb.conf, and when it dies attach to the parent process of the sleep with gdb.

The code looks like:

1522 static int store_cwd_data(vfs_handle_struct *handle,
1523                                 const char *connectpath)
1524 {
1525         struct shadow_copy2_private *priv = NULL;
1526         struct smb_filename *cwd_fname = NULL;
1527 
1528         SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
1529                                 return -1);
1530 
1531         cwd_fname = SMB_VFS_NEXT_GETWD(handle, talloc_tos());
1532         if (cwd_fname == NULL) {
1533                 return -1;
1534         }
1535         DBG_DEBUG("shadow cwd = %s\n", cwd_fname->base_name);
1536 
1537         /*
1538          * Now we're modifying the priv data. Any
1539          * failures here are terminal.
1540          */
1541 
1542         TALLOC_FREE(priv->shadow_cwd);
1543         priv->shadow_cwd = talloc_strdup(priv, cwd_fname->base_name);
1544         TALLOC_FREE(cwd_fname);
1545         if (priv->shadow_cwd == NULL) {
1546                 smb_panic("talloc failed\n");
1547         }

and it seems to be dieing with priv->shadow_cwd == NULL, which means the line:

priv->shadow_cwd = talloc_strdup(priv, cwd_fname->base_name);

returned NULL. If:

1531         cwd_fname = SMB_VFS_NEXT_GETWD(handle, talloc_tos());

didn't return NULL, then I really don't see how the talloc can have
failed here (I'm assuming you're not out of memory :-).

You'll have to debug to explain I'm afraid. We need to know what *exactly* is in cwd_fname after the SMB_VFS_NEXT_GETWD call.
Comment 19 Brian De Wolf 2017-09-22 22:32:34 UTC
I was able to break on source3/modules/vfs_shadow_copy2.c:1527 and next through the function.  It looks like the smb_filename that comes back is rather empty:

(gdb) print cwd_fname
$9 = (struct smb_filename *) 0x80c4b70
(gdb) print *cwd_fname
$10 = {base_name = 0x0, stream_name = 0x0, original_lcomp = 0x0, flags = 0, st = {st_ex_dev = 0, st_ex_ino = 0, st_ex_mode = 0, st_ex_nlink = 0, st_ex_uid = 0, st_ex_gid = 0, st_ex_rdev = 0, st_ex_size = 0, st_ex_atime = {tv_sec = 0,
      tv_nsec = 0}, st_ex_mtime = {tv_sec = 0, tv_nsec = 0}, st_ex_ctime = {tv_sec = 0, tv_nsec = 0}, st_ex_btime = {tv_sec = 0, tv_nsec = 0}, st_ex_calculated_birthtime = false, st_ex_blksize = 0, st_ex_blocks = 0, st_ex_flags = 0,
    st_ex_mask = 0}}

It looks like the result of getwd is never checked when constructing the smb_filename that gets returned.
Comment 20 Brian De Wolf 2017-09-25 23:56:25 UTC
I tweaked the patch to check base_name instead of the cwd_fname pointer:

-       if (cwd_fname == NULL) {
-               smb_panic("getwd failed\n");
+       if (cwd_fname->base_name == NULL) {
+               return -1;

And now it's not crashing when I try to create files.  Any other operations I should test?
Comment 21 Jeremy Allison 2017-10-03 00:29:01 UTC
Oh - you've found a bug in the vfs_default.c getwd() handling ! It should be returning NULL on error, not an invalid struct smb_filename.

I'll log a separate bug for that, and make this dependent on it.
Comment 22 Jeremy Allison 2017-10-03 18:25:14 UTC
Created attachment 13646 [details]
Prerequisite patch

Can you try adding this patch also, and *then* applying the specific patch for this bug. I think with all these patches the bug should be fixed. Sorry for the problem.
Comment 23 Brian De Wolf 2017-10-04 00:04:20 UTC
Looks like that really broke things.  With shadow_copy2 enabled, every location I tried to poke returned NT_STATUS_ACCESS_DENIED.  With shadow_copy2 disabled, it hits the smb_panic at source3/smbd/vfs.c:887.  Here's a backtrace in the call to vfs_GetWd that returns null:

#0  vfs_GetWd (ctx=ctx@entry=0x80b64c8, conn=conn@entry=0x80b64c8) at ../source3/smbd/vfs.c:903
        current_dir_fname = 0x80b38a8
        key = {devid = 579619958582465752, inode = 579619065229424920, extid = 18334714099516047364}
        smb_fname_dot = <optimized out>
        smb_fname_full = <optimized out>
        result = <optimized out>
        __FUNCTION__ = "vfs_GetWd"
#1  0xfe598c72 in vfs_ChDir (conn=conn@entry=0x80b64c8, smb_fname=smb_fname@entry=0x80b7530)
    at ../source3/smbd/vfs.c:885
        ret = <optimized out>
        __FUNCTION__ = "vfs_ChDir"
#2  0xfe529e4e in open_dir_safely (ctx=0x80b74f0, conn=0x80b64c8, smb_dname=0x80b7530, wcard=0x0, attr=0)
    at ../source3/smbd/dir.c:1690
        dir_hnd = 0x0
        smb_fname_cwd = 0x0
        saved_dir_fname = 0x80b77f0
#3  0xfe52b327 in OpenDir (mem_ctx=<optimized out>, conn=<optimized out>, conn@entry=0x80b64c8, 
    smb_dname=<optimized out>, smb_dname@entry=0x80b7530, mask=mask@entry=0x0, attr=attr@entry=0)
    at ../source3/smbd/dir.c:1745
No locals.
#4  0xfe57f992 in get_real_filename_full_scan (conn=0x80b64c8, path=0x80ae260 "New folder/New folder", 
    path@entry=0x59c88924 <error: Cannot access memory at address 0x59c88924>, 
    name=0x80add96 "New Text Document (2).txt", mangled=false, mem_ctx=0x80b74f0, found_name=0x804702c)
    at ../source3/smbd/filename.c:1381
        cur_dir = <optimized out>
        dname = 0x0
        talloced = <optimized out>
        unmangled_name = <optimized out>
        curpos = 134929814
        smb_fname = 0x80b7530
        __FUNCTION__ = "get_real_filename_full_scan"
#5  0xfe57ff83 in get_real_filename (conn=0x80add96, conn@entry=0x80b64c8, path=0x0, name=0x80b74f0 "\360u\v\b\002", 
    mem_ctx=0x804702c, found_name=found_name@entry=0x804702c) at ../source3/smbd/filename.c:1465
        ret = <optimized out>
        mangled = <optimized out>
#6  0xfe580aa4 in unix_convert (ctx=0x80afac8, conn=conn@entry=0x80b64c8, 
    orig_path=0x80b1ae0 "New folder/New folder/New Text Document (2).txt", smb_fname_out=0x80472fc, 
    ucf_flags=ucf_flags@entry=0) at ../source3/smbd/filename.c:920
        found_name = 0x0
        smb_fname = 0x80b0ee8
        cnull = 0 '\000'
        start = 0x80add96 "New Text Document (2).txt"
        end = 0x0
        stream = 0x0
        component_was_mangled = false
        name_has_wildcard = false
        posix_pathnames = false
        allow_wcard_last_component = false
        save_last_component = false
        snapshot_path = false
        status = <optimized out>
        ret = <optimized out>
        __FUNCTION__ = "unix_convert"
#7  0xfe581c29 in filename_convert_internal (ctx=ctx@entry=0x80afac8, conn=conn@entry=0x80b64c8, 
    smbreq=smbreq@entry=0x0, name_in=<optimized out>, 
    name_in@entry=0x80b1ae0 "New folder/New folder/New Text Document (2).txt", ucf_flags=ucf_flags@entry=0, 
    ppath_contains_wcard=ppath_contains_wcard@entry=0x0, pp_smb_fname=pp_smb_fname@entry=0x80472fc)
    at ../source3/smbd/filename.c:1619
        status = <optimized out>
        __FUNCTION__ = "filename_convert_internal"
#8  0xfe581f9e in filename_convert (ctx=0x80afac8, conn=0x80b64c8, 
    name_in=0x80b1ae0 "New folder/New folder/New Text Document (2).txt", ucf_flags=0, 
    ppath_contains_wcard=ppath_contains_wcard@entry=0x0, pp_smb_fname=pp_smb_fname@entry=0x80472fc)
    at ../source3/smbd/filename.c:1664
No locals.
#9  0xfe5ce0c8 in smbd_smb2_create_send (in_context_blobs=..., in_name=<optimized out>, 
    in_create_options=<optimized out>, in_create_disposition=<optimized out>, in_share_access=<optimized out>, 
    in_file_attributes=<optimized out>, in_desired_access=<optimized out>, in_impersonation_level=<optimized out>, 
    in_oplock_level=<optimized out>, smb2req=<optimized out>, ev=<optimized out>, mem_ctx=<optimized out>)
    at ../source3/smbd/smb2_create.c:1114
        smb_fname = 0x0
        ucf_flags = <optimized out>
        ea_list = <optimized out>
        sec_desc = <optimized out>
        durable_requested = <optimized out>
        need_replay_cache = <optimized out>
        mxac = <optimized out>
        max_access_time = <optimized out>
        allocation_size = <optimized out>
        lease_ptr = <optimized out>
        lease_len = <optimized out>
        op = 0x0
        fname = <optimized out>
        secd = <optimized out>
        _create_guid = {time_low = 0, time_mid = 0, time_hi_and_version = 0, clock_seq = "\000", 
          node = "\000\000\000\000\000"}
        create_guid = <optimized out>
        do_durable_reconnect = <optimized out>
        persistent_id = <optimized out>
        exta = <optimized out>
        qfid = <optimized out>
        update_open = <optimized out>
        lease = {lease_key = {data = {0, 0}}, lease_state = 0, lease_flags = 0, lease_duration = 0, 
          parent_lease_key = {data = {0, 0}}, lease_version = 0, lease_epoch = 0}
        alsi = <optimized out>
        twrp = <optimized out>
        durable_timeout_msec = <optimized out>
        state = 0x80afba8
        smb1req = <optimized out>
        req = <optimized out>
        result = 0x0
        dhnc = <optimized out>
        dh2c = <optimized out>
        status = <optimized out>
        info = 0
        requested_oplock_level = <optimized out>
        rqls = <optimized out>
        dhnq = <optimized out>
        dh2q = <optimized out>
        replay_operation = <optimized out>
#10 smbd_smb2_request_process_create (smb2req=smb2req@entry=0x80af338) at ../source3/smbd/smb2_create.c:227
        inbody = <optimized out>
        indyniov = <optimized out>
        in_oplock_level = <optimized out>
        in_impersonation_level = <optimized out>
        in_desired_access = <optimized out>
        in_file_attributes = <optimized out>
        in_share_access = <optimized out>
        in_create_disposition = <optimized out>
        in_create_options = <optimized out>
        in_name_offset = <optimized out>
        in_name_length = <optimized out>
        in_name_buffer = <optimized out>
        in_name_string = 0x80af658 "New folder\\New folder\\New Text Document (2).txt"
        in_name_string_size = 47
        name_offset = <optimized out>
        name_available_length = <optimized out>
        in_context_offset = <optimized out>
        in_context_length = <optimized out>
        in_context_blobs = {num_blobs = 3, blobs = 0x80af9e8}
        context_offset = <optimized out>
        context_available_length = <optimized out>
        dyn_offset = <optimized out>
        status = <optimized out>
        ok = <optimized out>
#11 0xfe5c30a4 in smbd_smb2_request_dispatch (req=req@entry=0x80af338) at ../source3/smbd/smb2_server.c:2597
        xconn = <optimized out>
        call = <optimized out>
        intf_v = <optimized out>
        inhdr = <optimized out>
        opcode = <optimized out>
        flags = <optimized out>
        mid = <optimized out>
        status = <optimized out>
        session_status = <optimized out>
        allowed_flags = <optimized out>
        return_value = <optimized out>
        x = <optimized out>
        signing_required = <optimized out>
        encryption_desired = false
        encryption_required = <optimized out>
        __FUNCTION__ = "smbd_smb2_request_dispatch"
#12 0xfe5c3e4f in smbd_smb2_io_handler (fde_flags=<optimized out>, xconn=0x809c7b8)
    at ../source3/smbd/smb2_server.c:3890
        err = <optimized out>
        sconn = <optimized out>
        state = 0x809c82c
        req = <optimized out>
        min_recvfile_size = 4294967295
        ret = <optimized out>
        retry = false
        status = <optimized out>
        now = <optimized out>
#13 smbd_smb2_connection_handler (ev=0x8099150, fde=0x80a7d88, flags=1, private_data=0x809c7b8)
    at ../source3/smbd/smb2_server.c:3928
        xconn = 0x809c7b8
        status = <optimized out>
#14 0xfe7cbc76 in epoll_event_loop (tvalp=0x804750c, epoll_ev=0x80992a0) at ../lib/tevent/tevent_epoll.c:728
        fde = <optimized out>
        flags = <optimized out>
        mpx_fde = <optimized out>
        ret = <optimized out>
        i = 0
        timeout = <optimized out>
        wait_errno = <optimized out>
        events = {{events = 1, data = {ptr = 0x80a7d88, fd = 134905224, u32 = 134905224, u64 = 134905224}}}
#15 epoll_event_loop_once (ev=0x8099150, location=0xfe6cba64 "../source3/smbd/process.c:4126")
    at ../lib/tevent/tevent_epoll.c:930
        epoll_ev = 0x80992a0
        tval = {tv_sec = 0, tv_usec = 998118}
        panic_triggered = false
#16 0xfe7c9c1e in std_event_loop_once (ev=0x8099150, location=0xfe6cba64 "../source3/smbd/process.c:4126")
    at ../lib/tevent/tevent_standard.c:114
        glue_ptr = <optimized out>
        glue = 0x80991f8
        ret = <optimized out>
#17 0xfe7c53d3 in _tevent_loop_once (ev=ev@entry=0x8099150, 
    location=location@entry=0xfe6cba64 "../source3/smbd/process.c:4126") at ../lib/tevent/tevent.c:726
        ret = <optimized out>
        nesting_stack_ptr = 0x0
#18 0xfe7c55fc in tevent_common_loop_wait (ev=0x8099150, location=0xfe6cba64 "../source3/smbd/process.c:4126")
    at ../lib/tevent/tevent.c:849
        ret = <optimized out>
#19 0xfe7c9b9e in std_event_loop_wait (ev=0x8099150, location=0xfe6cba64 "../source3/smbd/process.c:4126")
    at ../lib/tevent/tevent_standard.c:145
        glue_ptr = <optimized out>
        glue = 0x80991f8
        ret = <optimized out>
#20 0xfe7c5698 in _tevent_loop_wait (ev=0x8099150, 
    location=location@entry=0xfe6cba64 "../source3/smbd/process.c:4126") at ../lib/tevent/tevent.c:868
No locals.
#21 0xfe5afce5 in smbd_process (ev_ctx=ev_ctx@entry=0x8099150, msg_ctx=msg_ctx@entry=0x8099398, 
    sock_fd=sock_fd@entry=41, interactive=interactive@entry=false) at ../source3/smbd/process.c:4126
        trace_state = {ev = 0x8099150, frame = 0x80b74f0}
        client = 0x809daf0
        sconn = 0x80a8a90
        xconn = 0x809c7b8
        locaddr = <optimized out>
        remaddr = <optimized out>
        ret = <optimized out>
        status = <optimized out>
        tv = {tv_sec = 1507074148, tv_usec = 938243}
        now = <optimized out>
        chroot_dir = <optimized out>
        rc = <optimized out>
        __func__ = "smbd_process"
        __FUNCTION__ = "smbd_process"
#22 0x0805c7b1 in smbd_accept_connection (ev=0x8099150, fde=0x80a6d18, flags=1, private_data=0x80a6cc8)
    at ../source3/smbd/server.c:1026
        status = {v = 0}
        s = 0x0
        msg_ctx = 0x8099398
        addr = {ss_family = 2, _ss_pad1 = "\325\370\206G\372\061", _ss_align = 0, 
          _ss_pad2 = "\reY\374\004\b`\374\000\000\000\000xw\004\b\000\000`\374\004\b`\374 \235\t\bxw\004\b\000\000\000\000\004\b`\374.\200R\374\273\070\204\376\000\000`\374\004\b`\374 \235\t\b\230w\004\b\213\201R\374\004\b`\374\000\000\000\000\330w\004\b\021Y\332\376\224\257\205\376\000\000\000\000\350w\004\b~(\204\376 \235\t\bh\032\n\b\000\000\000\000\330lY\374\004\b`\374\000\000\000\000\030x\004\bY\241|\376 x\004\bt\364\t\b\004\b`\374\reY\374\004\b`\374\000\000\000\000;\241|\376\020\347}\376h\364\t\b x\004\bHx\004\b\225\247|\376(x\004\b x\004\bt\364\t\b\000\000`\374\004\b`\374"...}
        in_addrlen = 16
        fd = 41
        pid = <optimized out>
        __FUNCTION__ = "smbd_accept_connection"
#23 0xfe7cbc76 in epoll_event_loop (tvalp=0x804788c, epoll_ev=0x80992a0) at ../lib/tevent/tevent_epoll.c:728
        fde = <optimized out>
        flags = <optimized out>
        mpx_fde = <optimized out>
        ret = <optimized out>
        i = 0
        timeout = <optimized out>
        wait_errno = <optimized out>
        events = {{events = 1, data = {ptr = 0x80a6d18, fd = 134901016, u32 = 134901016, u64 = 134901016}}}
#24 epoll_event_loop_once (ev=0x8099150, location=0x8063c6d "../source3/smbd/server.c:1393")
    at ../lib/tevent/tevent_epoll.c:930
        epoll_ev = 0x80992a0
        tval = {tv_sec = 407, tv_usec = 144170}
        panic_triggered = false
#25 0xfe7c9c1e in std_event_loop_once (ev=0x8099150, location=0x8063c6d "../source3/smbd/server.c:1393")
    at ../lib/tevent/tevent_standard.c:114
        glue_ptr = <optimized out>
        glue = 0x80991f8
        ret = <optimized out>
#26 0xfe7c53d3 in _tevent_loop_once (ev=ev@entry=0x8099150, 
    location=location@entry=0x8063c6d "../source3/smbd/server.c:1393") at ../lib/tevent/tevent.c:726
        ret = <optimized out>
        nesting_stack_ptr = 0x0
#27 0xfe7c55fc in tevent_common_loop_wait (ev=0x8099150, location=0x8063c6d "../source3/smbd/server.c:1393")
    at ../lib/tevent/tevent.c:849
        ret = <optimized out>
#28 0xfe7c9b9e in std_event_loop_wait (ev=0x8099150, location=0x8063c6d "../source3/smbd/server.c:1393")
    at ../lib/tevent/tevent_standard.c:145
        glue_ptr = <optimized out>
        glue = 0x80991f8
        ret = <optimized out>
#29 0xfe7c5698 in _tevent_loop_wait (ev=0x8099150, location=location@entry=0x8063c6d "../source3/smbd/server.c:1393")
    at ../lib/tevent/tevent.c:868
No locals.
#30 0x0805ef55 in smbd_parent_loop (parent=<optimized out>, ev_ctx=<optimized out>) at ../source3/smbd/server.c:1393
        trace_state = {frame = 0x809deb8}
        ret = 0
#31 main (argc=<optimized out>, argv=0x8047d48) at ../source3/smbd/server.c:2160
        is_daemon = <optimized out>
        interactive = <optimized out>
        Fork = <optimized out>
        no_process_group = <optimized out>
        log_stdout = <optimized out>
        ports = 0x0
        profile_level = 0x0
        opt = <optimized out>
        pc = <optimized out>
        print_build_options = <optimized out>
        main_server_id = {pid = 6167, task_id = 0, vnn = 4294967295, unique_id = 12535287533572478642}
        long_options = {{longName = 0x0, shortName = 0 '\000', argInfo = 4, arg = 0xfc6e9b60 <poptHelpOptions>, 
            val = 0, descrip = 0x8064253 "Help options:", argDescrip = 0x0}, {longName = 0x8064261 "daemon", 
            shortName = 68 'D', argInfo = 0, arg = 0x0, val = 1000, descrip = 0x8064268 "Become a daemon (default)", 
            argDescrip = 0x0}, {longName = 0x8064282 "interactive", shortName = 105 'i', argInfo = 0, arg = 0x0, 
            val = 1001, descrip = 0x8061d74 "Run interactive (not a daemon)", argDescrip = 0x0}, {
            longName = 0x806428e "foreground", shortName = 70 'F', argInfo = 0, arg = 0x0, val = 1002, 
            descrip = 0x8061d94 "Run daemon in foreground (for daemontools, etc.)", argDescrip = 0x0}, {
            longName = 0x8064299 "no-process-group", shortName = 0 '\000', argInfo = 0, arg = 0x0, val = 1003, 
            descrip = 0x8061dc8 "Don't create a new process group", argDescrip = 0x0}, {
            longName = 0x80642aa "log-stdout", shortName = 83 'S', argInfo = 0, arg = 0x0, val = 1004, 
            descrip = 0x80642b5 "Log to stdout", argDescrip = 0x0}, {longName = 0x80642c3 "build-options", 
            shortName = 98 'b', argInfo = 0, arg = 0x0, val = 98, descrip = 0x80642d1 "Print build options", 
            argDescrip = 0x0}, {longName = 0x80642e5 "port", shortName = 112 'p', argInfo = 1, arg = 0x8047a64, 
            val = 0, descrip = 0x80642ea "Listen on the specified ports", argDescrip = 0x0}, {
            longName = 0x8064308 "profiling-level", shortName = 80 'P', argInfo = 1, arg = 0x8047a68, val = 0, 
            descrip = 0x8064318 "Set profiling level", argDescrip = 0x806432c "PROFILE_LEVEL"}, {longName = 0x0, 
            shortName = 0 '\000', argInfo = 4, arg = 0xfee239e0 <popt_common_samba>, val = 0, 
            descrip = 0x806433a "Common samba options:", argDescrip = 0x0}, {longName = 0x0, shortName = 0 '\000', 
            argInfo = 0, arg = 0x0, val = 0, descrip = 0x0, argDescrip = 0x0}}
        parent = <optimized out>
        frame = <optimized out>
        status = <optimized out>
        ev_ctx = <optimized out>
        msg_ctx = <optimized out>
        server_id = {pid = 6168, task_id = 0, vnn = 4294967295, unique_id = 13867607488433539256}
        se = <optimized out>
        profiling_level = <optimized out>
        np_dir = <optimized out>
        smbd_shim_fns = {
          cancel_pending_lock_requests_by_fid = 0x8056794 <smbd_cancel_pending_lock_requests_by_fid@plt>, 
          send_stat_cache_delete_message = 0x80567a4 <smbd_send_stat_cache_delete_message@plt>, 
          change_to_root_user = 0x80567b4 <smbd_change_to_root_user@plt>, 
          become_authenticated_pipe_user = 0x80567c4 <smbd_become_authenticated_pipe_user@plt>, 
          unbecome_authenticated_pipe_user = 0x80567d4 <smbd_unbecome_authenticated_pipe_user@plt>, 
          contend_level2_oplocks_begin = 0x80567e4 <smbd_contend_level2_oplocks_begin@plt>, 
          contend_level2_oplocks_end = 0x80567f4 <smbd_contend_level2_oplocks_end@plt>, 
          become_root = 0x8056804 <smbd_become_root@plt>, unbecome_root = 0x8056814 <smbd_unbecome_root@plt>, 
          exit_server = 0x8056824 <smbd_exit_server@plt>, 
          exit_server_cleanly = 0x8056834 <smbd_exit_server_cleanly@plt>}
        __FUNCTION__ = "main"
        __func__ = "main"
Comment 24 Jeremy Allison 2017-10-04 00:24:06 UTC
OK, I'm puzzled now. The prerequisite patch should ensure that the lowest level vfswrap_getwd() can never return a half-constructed struct smb_filename pointer, but only NULL on error - which is certainly what is needed as the low level fix. Returning an initialized struct smb_filename pointer where base_name is NULL is *definitely* the wrong thing to do :-).

I'll take a look at the backtrace tomorrow and try and figure out what is going on.
Comment 25 Jeremy Allison 2017-10-04 00:34:41 UTC
Can you let me know which code path is being taken on your system through sys_getwd() ? Can you test this on 4.7.x (the prerequisite patch was created and tested on 4.7.x) ?

Not being able to reproduce locally makes this very frustrating to work on. Can you attach with gdb to a single instance (smbd -i) with smbclient as the client and step through this to help me debug it ?
Comment 26 Brian De Wolf 2017-10-04 18:15:50 UTC
>OK, I'm puzzled now. The prerequisite patch should ensure that the lowest level vfswrap_getwd() can never return a half-constructed struct smb_filename pointer

Sorry, maybe I wasn't clear.  It's returning null properly now.  The panic I'm talking about is this one in vfs_ChDir:

                conn->cwd_fname = vfs_GetWd(conn, conn);
                if (conn->cwd_fname == NULL) {
                        smb_panic("con->cwd getwd failed\n");
                        /* NOTREACHED */
                        return -1;
                }

This makes the server pretty unusable on platforms where getcwd is unreliable.

I've been testing the two patches against 4.7.0.

Here's a partial bt showing where getcwd gets used:

#0  0xfc5188c6 in getcwd () from /lib/libc.so.1
#1  0xfdfb88b6 in sys_getwd () at ../source3/lib/system.c:592
#2  0xfe4dfd68 in vfswrap_getwd (handle=0x808db30, ctx=0x80aa470) at ../source3/modules/vfs_default.c:2227
#3  0xfe597c03 in smb_vfs_call_getwd (handle=<optimized out>, ctx=0x80aa470) at ../source3/smbd/vfs.c:2148
#4  0xfe5988ec in vfs_GetWd (ctx=ctx@entry=0x80aa470, conn=conn@entry=0x80aa470) at ../source3/smbd/vfs.c:965
#5  0xfe598c72 in vfs_ChDir (conn=conn@entry=0x80aa470, smb_fname=smb_fname@entry=0x80becd8)
    at ../source3/smbd/vfs.c:885
#6  0xfe529e4e in open_dir_safely (ctx=0x80bec98, conn=0x80aa470, smb_dname=0x80becd8, wcard=0x0, attr=0)
    at ../source3/smbd/dir.c:1690
#7  0xfe52b327 in OpenDir (mem_ctx=<optimized out>, conn=<optimized out>, conn@entry=0x80aa470, 
    smb_dname=<optimized out>, smb_dname@entry=0x80becd8, mask=mask@entry=0x0, attr=attr@entry=0)
    at ../source3/smbd/dir.c:1745

You can probably simulate my getcwd issue with LD_PRELOAD.  I don't have any linux boxes running samba to test this against, but it worked on linux against `pwd`.  Just change the string to be the dir you want to simulate in:

#define _GNU_SOURCE
#include <unistd.h>
#include <string.h>
#include <dlfcn.h>

static char* (*real_getcwd)(char *buf, size_t size) = NULL;
static char* (*real_getwd)(char *buf) = NULL;

char *getcwd(char *buf, size_t size) {
        return NULL;
        real_getcwd = dlsym(RTLD_NEXT, "getcwd");
        char *ret = real_getcwd(buf, size);
        if(ret && strcmp(ret, "/user/bldewolf/cwdwrap") == 0) {
                return NULL;
        }
        return ret;
}

char *getwd(char *buf) {
        return NULL;
        real_getwd = dlsym(RTLD_NEXT, "getwd");
        char *ret = real_getwd(buf);
        if(ret && strcmp(ret, "/user/bldewolf/cwdwrap") == 0) {
                return NULL;
        }
        return ret;
}
Comment 27 Jeremy Allison 2017-10-04 18:33:22 UTC
Ah, thanks. The return NULL behaviour for getwd is correct now (and pushed to master). I have to examine all the code paths before possibly changing the vfs_ChDir() behaviour. It's pretty clear from the intent of the vfs_ChDir() code that smbd expects that if chdir() succeeds, that getwd() must also succeed.

If we change that behaviour, are we introducing a security hole somewhere ?
Comment 28 Jeremy Allison 2017-10-04 19:57:08 UTC
Created attachment 13651 [details]
generic patch for smbd

OK, can you try this generic patch for smbd. It changes the behaviour for chdir+getwd()-fail to be return to previous directory, instead of panic.

This should simply prevent you from chdir()'ing into a directory for which you can't getwd().

You will still need the prerequisite patch.

Can you test this both with and without the shadow_copy2 module ? If we still crash with the shadow_copy2 module then we probably need both this and the previous 'Updated git-am patch for master.' patch.

Cheers,

Jeremy.
Comment 29 Brian De Wolf 2017-10-05 00:06:29 UTC
Alright, I built and tested with all three patches applied.  It's now working with shadow_copy2 and without.

I was actually the cause of the server returning permission denied for everything when shadow_copy2 was enabled.  Because it tries to store the cwd before doing a chdir, it's very picky about what directory the server starts in.  I was starting the server in /root, and since the server starts impersonating the user, every getcwd call fails before it can chdir out of /root.  After starting the daemon in /, shadow_copy2 was happy again.

I'm still concerned about one regression (from pre-4.6) that remains: when the user is in a directory where getcwd doesn't work, they are unable to create/modify/delete any files.  I've been checking if it gets fixed incidentally, but no dice.  I'll try poking at it to see if I can find what's failing.
Comment 30 Jeremy Allison 2017-10-05 00:24:30 UTC
Well being as the intent was that smbd be unable to chdir() into a directory where it can't then get the result via getwd(), I'm not too worried about that as a regression - I don't think it should have been allowing that in the first place.

Just to confirm - all 3 patches are needed ? Is the first patch:

https://attachments.samba.org/attachment.cgi?id=13601

needed to make things work with a shadow_copy2 share ?
Comment 31 Jeremy Allison 2017-10-05 00:26:51 UTC
With the patch:

https://attachments.samba.org/attachment.cgi?id=13651

that prevents chdir() into a directory where getwd() fails, I think I can simplify the first patch:

https://attachments.samba.org/attachment.cgi?id=13601

as it shouldn't need to store off the existing directory, just correctly handle the chdir() fail.

I'll upload a modified version of that one tomorrow.
Comment 32 Jeremy Allison 2017-10-05 00:31:36 UTC
(In reply to Jeremy Allison from comment #31)

Hmmm. In fact, maybe patch:

https://attachments.samba.org/attachment.cgi?id=13601

isn't needed at all for shadow_copy2 shares, now that the underlying chdir() call should fail if the target directory is unreadable with getwd().
Comment 33 Brian De Wolf 2017-10-05 23:33:49 UTC
I rebuilt samba 4.7.0 with two patches:

https://bugzilla.samba.org/attachment.cgi?id=13646
https://bugzilla.samba.org/attachment.cgi?id=13651

The server runs fine with shadow_copy2 enabled now.  Looks like that fixes it.
Comment 34 Jeremy Allison 2017-10-10 18:37:08 UTC
Created attachment 13676 [details]
git-am fix for 4.7.next.

Cherry-picked from master.
Comment 35 Ralph Böhme 2017-10-10 19:53:56 UTC
Reassigning to metzolin for inclusion in 4.7. :)
Comment 36 Karolin Seeger 2017-10-24 08:12:20 UTC
(In reply to Ralph Böhme from comment #35)
Pushed to autobuild-v4-7-test.
Comment 37 Karolin Seeger 2017-11-01 08:48:57 UTC
(In reply to Karolin Seeger from comment #36)
Pushed to v4-7-test.
Closing out bug report.

Thanks!
Comment 38 Brian De Wolf 2018-01-05 22:15:49 UTC
Well, I started preparing to deploy 4.7.4 and noticed I still get crashes when I try to enable the shadow_copy2 module.  It looks like I messed up testing last October and the patch

https://attachments.samba.org/attachment.cgi?id=13601

is still required.  Should I re-open this bug or should I make a new one?
Comment 39 Jeremy Allison 2018-01-05 23:42:40 UTC
New one please - add the patch you think is needed to it and give me a *GOOD* reproducible scenario.

Thanks.

Jeremy.