[Samba] Crash on stat() fail with fsp_flags.fstat_before_close

Ratna Bolla (rbolla) Ratna.Bolla at quest.com
Wed Oct 4 11:43:13 UTC 2023


fd_close() does not reset fsp->fd to -1, if vfs_stat_fsp() call fails for any reason.
This leads to crash when fd_handle_destructor() is called.

INTERNAL ERROR: assert failed: (fh->fd == -1) || (fh->fd == AT_FDCWD) in pid 3930585

#2  0x00007f58b7a54d46 in __GI_raise (sig=sig at entry=6) at ../sysdeps/posix/raise.c:26
#3  0x00007f58b7a287f3 in __GI_abort () at abort.c:79
#4  0x00007f58b7f811e4 in dump_core () from /lib64/libsmbconf.so.0
#5  0x00007f58b7f8b865 in smb_panic_s3 () from /lib64/libsmbconf.so.0
#6  0x00007f58b7cb9a1e in smb_panic () from /usr/lib64/samba/libgenrand-samba4.so
#7  0x00007f58b807ebb3 in fd_handle_destructor () from /usr/lib64/samba/libsmbd-base-samba4.so
#8  0x00007f58b7c80828 in _tc_free_internal () from /lib64/libtalloc.so.2
#9  0x00007f58b8094cf5 in file_free () from /usr/lib64/samba/libsmbd-base-samba4.so
#10 0x00007f58b80ca32d in close_file_free () from /usr/lib64/samba/libsmbd-base-samba4.so
#11 0x00007f58b809464f in close_file_in_loop () from /usr/lib64/samba/libsmbd-base-samba4.so
#12 0x00007f58b80947de in file_close_user_fn () from /usr/lib64/samba/libsmbd-base-samba4.so
#13 0x00007f58b808cbf1 in files_forall () from /usr/lib64/samba/libsmbd-base-samba4.so
#14 0x00007f58b808cd42 in file_close_user () from /usr/lib64/samba/libsmbd-base-samba4.so
#15 0x00007f58b810e5f2 in smbXsrv_session_logoff () from /usr/lib64/samba/libsmbd-base-samba4.so
#16 0x00007f58b810ea15 in smbXsrv_session_logoff_all_callback () from /usr/lib64/samba/libsmbd-base-samba4.so
#17 0x00007f58b7977916 in db_rbt_traverse_internal.constprop () from /usr/lib64/samba/libdbwrap-samba4.so
#18 0x00007f58b7977b53 in db_rbt_traverse () from /usr/lib64/samba/libdbwrap-samba4.so
#19 0x00007f58b797875b in dbwrap_traverse () from /usr/lib64/samba/libdbwrap-samba4.so
#20 0x00007f58b810c49c in smbXsrv_session_logoff_all () from /usr/lib64/samba/libsmbd-base-samba4.so
#21 0x00007f58b81119b9 in exit_server_common () from /usr/lib64/samba/libsmbd-base-samba4.so
#22 0x00007f58b8111e44 in smbd_exit_server_cleanly () from /usr/lib64/samba/libsmbd-base-samba4.so
#23 0x00007f58b7cbda08 in exit_server_cleanly () from /usr/lib64/samba/libsmbd-shim-samba4.so
#24 0x00007f58b80d58b6 in smbd_sig_term_handler.lto_priv () from /usr/lib64/samba/libsmbd-base-samba4.so
#25 0x00007f58b7c60c3a in tevent_common_invoke_signal_handler () from /lib64/libtevent.so.0
#26 0x00007f58b7c60da4 in tevent_common_check_signal () from /lib64/libtevent.so.0
#27 0x00007f58b7c632db in epoll_event_loop_once () from /lib64/libtevent.so.0
#28 0x00007f58b7c5b6ab in std_event_loop_once () from /lib64/libtevent.so.0
#29 0x00007f58b7c5db88 in _tevent_loop_once () from /lib64/libtevent.so.0
#30 0x00007f58b7c5dc7b in tevent_common_loop_wait () from /lib64/libtevent.so.0
#31 0x00007f58b7c5b71b in std_event_loop_wait () from /lib64/libtevent.so.0
#32 0x00007f58b80db5c0 in smbd_process () from /usr/lib64/samba/libsmbd-base-samba4.so
#33 0x0000563cd2d260c1 in smbd_accept_connection ()
#34 0x00007f58b7c5f675 in tevent_common_invoke_fd_handler () from /lib64/libtevent.so.0
#35 0x00007f58b7c633cf in epoll_event_loop_once () from /lib64/libtevent.so.0
#36 0x00007f58b7c5b6ab in std_event_loop_once () from /lib64/libtevent.so.0
#37 0x00007f58b7c5db88 in _tevent_loop_once () from /lib64/libtevent.so.0
#38 0x00007f58b7c5dc7b in tevent_common_loop_wait () from /lib64/libtevent.so.0
#39 0x00007f58b7c5b71b in std_event_loop_wait () from /lib64/libtevent.so.0
#40 0x0000563cd2d23b94 in main ()
(gdb)



No workaround is possible, as vfs plugin has no chance to reset fstat_before_close flag.
It gets set when close() call is received, and no plugin calls are made before it is checked to do a stat() call.
Please advise on any other workarounds possible to avoid the crash.

Thanks.

NTSTATUS fd_close(files_struct *fsp)
{
    NTSTATUS status;
    int ret;

    if (fsp == fsp->conn->cwd_fsp) {
        return NT_STATUS_OK;
    }

    if (fsp->fsp_flags.fstat_before_close) {
        status = vfs_stat_fsp(fsp);
        if (!NT_STATUS_IS_OK(status)) {
            return status;
        }
    }

    ...
    ...

    ret = SMB_VFS_CLOSE(fsp);
    fsp_set_fd(fsp, -1);
    if (ret == -1) {
        return map_nt_error_from_unix(errno);
    }
    return NT_STATUS_OK;
}




More information about the samba mailing list