Bug 13027 - shadow_copy2 calls smb_panic on unreadable parent directory
shadow_copy2 calls smb_panic on unreadable parent directory
Status: ASSIGNED
Product: Samba 4.1 and newer
Classification: Unclassified
Component: VFS Modules
4.6.4
All All
: P5 normal
: ---
Assigned To: Jeremy Allison
Samba QA Contact
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2017-09-11 17:29 UTC by Brian De Wolf
Modified: 2017-09-14 20:33 UTC (History)
2 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

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.