The branch, master has been updated via 633a3ee6894 s3: smbd: Ignore fstat() error on deleted stream in fd_close(). via 23deb79a280 tests: Add reproducer for bug 15487 via 340f0420bd3 pylibsmb: Add SMB2_CLOSE_FLAGS_FULL_INFORMATION constant via c4047443a51 libsmb: Pass "flags" through cli_close_send() and pylibsmb via f72ef19cf51 libsmb: Add "flags" to cli_smb2_close_fnum_send() from d1846452e96 vfs: Add VFS_OPEN_HOW_WITH_BACKUP_INTENT
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 633a3ee6894cc1d05b44dbe47a278202803d9b21 Author: Ralph Boehme <s...@samba.org> Date: Wed Sep 20 14:21:44 2023 -0700 s3: smbd: Ignore fstat() error on deleted stream in fd_close(). In the fd_close() fsp->fsp_flags.fstat_before_close code path. If this is a stream and delete-on-close was set, the backing object (an xattr from streams_xattr) might already be deleted so fstat() fails with NT_STATUS_NOT_FOUND. So if fsp refers to a stream we ignore the error and only bail for normal files where an fstat() should still work. NB. We cannot use fsp_is_alternate_stream(fsp) for this as the base_fsp has already been closed at this point and so the value fsp_is_alternate_stream() checks for is already NULL. Remove knownfail. Bug: https://bugzilla.samba.org/show_bug.cgi?id=15487 Signed-off-by: Ralph Boehme <s...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Volker Lendecke <v...@samba.org> Autobuild-Date(master): Tue Oct 10 09:39:27 UTC 2023 on atb-devel-224 commit 23deb79a28009f5c4ea2f2c2ceb84cfdbc9fb5b1 Author: Volker Lendecke <v...@samba.org> Date: Sat Oct 7 12:28:05 2023 +0200 tests: Add reproducer for bug 15487 Show that smbd crashes if asked to return full information on close of a stream handle with delete on close disposition set. Bug: https://bugzilla.samba.org/show_bug.cgi?id=15487 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 340f0420bd34149ebe8fc76eb5fe4547970a5c5b Author: Volker Lendecke <v...@samba.org> Date: Sat Oct 7 12:20:35 2023 +0200 pylibsmb: Add SMB2_CLOSE_FLAGS_FULL_INFORMATION constant Bug: https://bugzilla.samba.org/show_bug.cgi?id=15487 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit c4047443a511f003eb855504315eeb8499fafcb7 Author: Volker Lendecke <v...@samba.org> Date: Sat Oct 7 12:13:09 2023 +0200 libsmb: Pass "flags" through cli_close_send() and pylibsmb Bug: https://bugzilla.samba.org/show_bug.cgi?id=15487 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit f72ef19cf51d8ededa449344cc16b72cf3685302 Author: Volker Lendecke <v...@samba.org> Date: Sat Oct 7 12:06:26 2023 +0200 libsmb: Add "flags" to cli_smb2_close_fnum_send() Bug: https://bugzilla.samba.org/show_bug.cgi?id=15487 Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: examples/fuse/clifuse.c | 2 +- examples/winexe/winexe.c | 37 +++++++++++------------- python/samba/tests/libsmb-basic.py | 21 ++++++++++++++ source3/libsmb/cli_smb2_fnum.c | 56 +++++++++++++++++++++++++----------- source3/libsmb/cli_smb2_fnum.h | 3 +- source3/libsmb/clifile.c | 23 ++++++++------- source3/libsmb/clisymlink.c | 11 ++++--- source3/libsmb/proto.h | 4 ++- source3/libsmb/pylibsmb.c | 11 ++++--- source3/smbd/open.c | 15 +++++++++- source3/torture/nbench.c | 7 +++-- source3/torture/test_chain3.c | 2 +- source3/torture/test_notify.c | 11 ++++--- source3/torture/test_notify_online.c | 6 ++-- source3/torture/torture.c | 6 ++-- 15 files changed, 141 insertions(+), 74 deletions(-) Changeset truncated at 500 lines: diff --git a/examples/fuse/clifuse.c b/examples/fuse/clifuse.c index 28c5177b250..ba4aca751fe 100644 --- a/examples/fuse/clifuse.c +++ b/examples/fuse/clifuse.c @@ -952,7 +952,7 @@ static void cli_ll_release(fuse_req_t freq, fuse_ino_t ino, fnum = fi->fh; - req = cli_smb2_close_fnum_send(state, mstate->ev, mstate->cli, fnum); + req = cli_smb2_close_fnum_send(state, mstate->ev, mstate->cli, fnum, 0); if (req == NULL) { TALLOC_FREE(state); fuse_reply_err(freq, ENOMEM); diff --git a/examples/winexe/winexe.c b/examples/winexe/winexe.c index 29e1fe2055b..5c2529cb2de 100644 --- a/examples/winexe/winexe.c +++ b/examples/winexe/winexe.c @@ -993,11 +993,11 @@ static void winexe_out_pipe_got_data(struct tevent_req *subreq) nt_errstr(status)); if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_DISCONNECTED)) { - subreq = cli_close_send( - state, - state->ev, - state->cli, - state->out_pipe); + subreq = cli_close_send(state, + state->ev, + state->cli, + state->out_pipe, + 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -1206,11 +1206,11 @@ static void winexe_in_pipe_written(struct tevent_req *subreq) if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_DISCONNECTED) || state->close_requested) { - subreq = cli_close_send( - state, - state->ev, - state->cli, - state->in_pipe); + subreq = cli_close_send(state, + state->ev, + state->cli, + state->in_pipe, + 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -1275,11 +1275,8 @@ static bool winexe_in_pipe_close(struct tevent_req *req) TALLOC_FREE(state->fd_read_req); - subreq = cli_close_send( - state, - state->ev, - state->cli, - state->in_pipe); + subreq = + cli_close_send(state, state->ev, state->cli, state->in_pipe, 0); if (subreq == NULL) { return false; } @@ -1597,11 +1594,11 @@ static void winexe_ctrl_got_read(struct tevent_req *subreq) TALLOC_FREE(subreq); if (NT_STATUS_EQUAL(status, NT_STATUS_PIPE_DISCONNECTED)) { - subreq = cli_close_send( - state, - state->ev, - state->cli, - state->ctrl_pipe); + subreq = cli_close_send(state, + state->ev, + state->cli, + state->ctrl_pipe, + 0); if (tevent_req_nomem(subreq, req)) { return; } diff --git a/python/samba/tests/libsmb-basic.py b/python/samba/tests/libsmb-basic.py index 163c5b09ea9..20d3dd48c3c 100644 --- a/python/samba/tests/libsmb-basic.py +++ b/python/samba/tests/libsmb-basic.py @@ -242,6 +242,27 @@ class LibsmbTestCase(samba.tests.libsmb.LibsmbTests): # Without the bugfix for 15481 we get 'file' not 'File' self.assertEqual(directory[0]['name'], 'File') + def test_stream_close_with_full_information(self): + c = libsmb.Conn(self.server_ip, "streams_xattr", self.lp, self.creds) + + try: + c.deltree("teststreams") + except: + pass + + c.mkdir("teststreams") + fh = c.create("teststreams\\stream_full_close_info.txt:Stream", + DesiredAccess=security.SEC_STD_DELETE, + CreateDisposition=libsmb.FILE_CREATE) + c.delete_on_close(fh, 1) + + try: + c.close(fh, libsmb.SMB2_CLOSE_FLAGS_FULL_INFORMATION) + except: + self.fail() + + c.deltree("teststreams") + if __name__ == "__main__": import unittest unittest.main() diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c index 42f6d807fc5..1939db1b711 100644 --- a/source3/libsmb/cli_smb2_fnum.c +++ b/source3/libsmb/cli_smb2_fnum.c @@ -463,7 +463,8 @@ static void cli_smb2_close_fnum_done(struct tevent_req *subreq); struct tevent_req *cli_smb2_close_fnum_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, - uint16_t fnum) + uint16_t fnum, + uint16_t flags) { struct tevent_req *req, *subreq; struct cli_smb2_close_fnum_state *state; @@ -482,9 +483,14 @@ struct tevent_req *cli_smb2_close_fnum_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - subreq = smb2cli_close_send(state, ev, cli->conn, cli->timeout, - cli->smb2.session, cli->smb2.tcon, - 0, state->ph->fid_persistent, + subreq = smb2cli_close_send(state, + ev, + cli->conn, + cli->timeout, + cli->smb2.session, + cli->smb2.tcon, + flags, + state->ph->fid_persistent, state->ph->fid_volatile); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); @@ -546,7 +552,7 @@ NTSTATUS cli_smb2_close_fnum(struct cli_state *cli, uint16_t fnum) if (ev == NULL) { goto fail; } - req = cli_smb2_close_fnum_send(frame, ev, cli, fnum); + req = cli_smb2_close_fnum_send(frame, ev, cli, fnum, 0); if (req == NULL) { goto fail; } @@ -843,7 +849,8 @@ static void cli_smb2_mkdir_opened(struct tevent_req *subreq) return; } - subreq = cli_smb2_close_fnum_send(state, state->ev, state->cli, fnum); + subreq = + cli_smb2_close_fnum_send(state, state->ev, state->cli, fnum, 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -1004,8 +1011,11 @@ static void cli_smb2_rmdir_disp_set(struct tevent_req *subreq) * Close the fd even if the set_disp failed */ - subreq = cli_smb2_close_fnum_send( - state, state->ev, state->cli, state->fnum); + subreq = cli_smb2_close_fnum_send(state, + state->ev, + state->cli, + state->fnum, + 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -1134,7 +1144,8 @@ static void cli_smb2_unlink_opened1(struct tevent_req *subreq) return; } - subreq = cli_smb2_close_fnum_send(state, state->ev, state->cli, fnum); + subreq = + cli_smb2_close_fnum_send(state, state->ev, state->cli, fnum, 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -1157,7 +1168,8 @@ static void cli_smb2_unlink_opened2(struct tevent_req *subreq) return; } - subreq = cli_smb2_close_fnum_send(state, state->ev, state->cli, fnum); + subreq = + cli_smb2_close_fnum_send(state, state->ev, state->cli, fnum, 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -1541,8 +1553,11 @@ static void cli_smb2_list_done(struct tevent_req *subreq) TALLOC_FREE(response); - subreq = cli_smb2_close_fnum_send( - state, state->ev, state->cli, state->fnum); + subreq = cli_smb2_close_fnum_send(state, + state->ev, + state->cli, + state->fnum, + 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -2345,7 +2360,8 @@ static void cli_smb2_qpathinfo_done(struct tevent_req *subreq) subreq = cli_smb2_close_fnum_send(state, state->ev, state->cli, - state->fnum); + state->fnum, + 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -3027,8 +3043,11 @@ static void cli_smb2_mxac_opened(struct tevent_req *subreq) state->mxac = IVAL(mxac_blob->data.data, 4); close: - subreq = cli_smb2_close_fnum_send( - state, state->ev, state->cli, state->fnum); + subreq = cli_smb2_close_fnum_send(state, + state->ev, + state->cli, + state->fnum, + 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -3333,8 +3352,11 @@ static void cli_smb2_rename_renamed(struct tevent_req *subreq) state->rename_status = cli_smb2_rename_fnum_recv(subreq); TALLOC_FREE(subreq); - subreq = cli_smb2_close_fnum_send( - state, state->ev, state->cli, state->fnum); + subreq = cli_smb2_close_fnum_send(state, + state->ev, + state->cli, + state->fnum, + 0); if (tevent_req_nomem(subreq, req)) { return; } diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h index 0eb2a026527..7f3d7c2be1b 100644 --- a/source3/libsmb/cli_smb2_fnum.h +++ b/source3/libsmb/cli_smb2_fnum.h @@ -70,7 +70,8 @@ NTSTATUS cli_smb2_create_fnum( struct tevent_req *cli_smb2_close_fnum_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, - uint16_t fnum); + uint16_t fnum, + uint16_t flags); NTSTATUS cli_smb2_close_fnum_recv(struct tevent_req *req); NTSTATUS cli_smb2_close_fnum(struct cli_state *cli, uint16_t fnum); struct tevent_req *cli_smb2_delete_on_close_send(TALLOC_CTX *mem_ctx, diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 46b9f27bf4e..6f1625ce190 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -2048,8 +2048,11 @@ static void cli_smb2_hardlink_info_set(struct tevent_req *subreq) /* ignore error here, we need to close the file */ - subreq = cli_smb2_close_fnum_send( - state, state->ev, state->cli, state->fnum_src); + subreq = cli_smb2_close_fnum_send(state, + state->ev, + state->cli, + state->fnum_src, + 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -3634,9 +3637,10 @@ struct cli_close_state { static void cli_close_done(struct tevent_req *subreq); struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct cli_state *cli, - uint16_t fnum) + struct tevent_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint16_t flags) { struct tevent_req *req, *subreq; struct cli_close_state *state; @@ -3648,10 +3652,7 @@ struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx, } if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - subreq = cli_smb2_close_fnum_send(state, - ev, - cli, - fnum); + subreq = cli_smb2_close_fnum_send(state, ev, cli, fnum, flags); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -3714,7 +3715,7 @@ NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum) goto fail; } - req = cli_close_send(frame, ev, cli, fnum); + req = cli_close_send(frame, ev, cli, fnum, 0); if (req == NULL) { status = NT_STATUS_NO_MEMORY; goto fail; @@ -5117,7 +5118,7 @@ static void cli_chkpath_opened(struct tevent_req *subreq) return; } - subreq = cli_close_send(state, state->ev, state->cli, fnum); + subreq = cli_close_send(state, state->ev, state->cli, fnum, 0); if (tevent_req_nomem(subreq, req)) { return; } diff --git a/source3/libsmb/clisymlink.c b/source3/libsmb/clisymlink.c index 81d8646afcc..d7ecf545761 100644 --- a/source3/libsmb/clisymlink.c +++ b/source3/libsmb/clisymlink.c @@ -125,8 +125,11 @@ static void cli_create_reparse_point_done(struct tevent_req *subreq) TALLOC_FREE(subreq); if (NT_STATUS_IS_OK(state->set_reparse_status)) { - subreq = cli_close_send(state, state->ev, state->cli, - state->fnum); + subreq = cli_close_send(state, + state->ev, + state->cli, + state->fnum, + 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -159,7 +162,7 @@ static void cli_create_reparse_point_doc_done(struct tevent_req *subreq) (void)cli_nt_delete_on_close_recv(subreq); TALLOC_FREE(subreq); - subreq = cli_close_send(state, state->ev, state->cli, state->fnum); + subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -390,7 +393,7 @@ static void cli_get_reparse_data_done(struct tevent_req *subreq) state->datalen = out.length; } - subreq = cli_close_send(state, state->ev, state->cli, state->fnum); + subreq = cli_close_send(state, state->ev, state->cli, state->fnum, 0); if (tevent_req_nomem(subreq, req)) { return; } diff --git a/source3/libsmb/proto.h b/source3/libsmb/proto.h index 6ed2be9757a..b5a0311469e 100644 --- a/source3/libsmb/proto.h +++ b/source3/libsmb/proto.h @@ -435,7 +435,9 @@ struct tevent_req *cli_smb1_close_create(TALLOC_CTX *mem_ctx, struct tevent_req **psubreq); struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, - struct cli_state *cli, uint16_t fnum); + struct cli_state *cli, + uint16_t fnum, + uint16_t flags); NTSTATUS cli_close_recv(struct tevent_req *req); NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum); struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx, diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c index 9ac49437820..39d2f290a9f 100644 --- a/source3/libsmb/pylibsmb.c +++ b/source3/libsmb/pylibsmb.c @@ -1242,13 +1242,14 @@ static PyObject *py_cli_close(struct py_cli_state *self, PyObject *args) { struct tevent_req *req; int fnum; + int flags = 0; NTSTATUS status; - if (!PyArg_ParseTuple(args, "i", &fnum)) { + if (!PyArg_ParseTuple(args, "i|i", &fnum, &flags)) { return NULL; } - req = cli_close_send(NULL, self->ev, self->cli, fnum); + req = cli_close_send(NULL, self->ev, self->cli, fnum, flags); if (!py_tevent_req_wait_exc(self, req)) { return NULL; } @@ -1370,7 +1371,7 @@ static PyObject *py_smb_savefile(struct py_cli_state *self, PyObject *args) PyErr_NTSTATUS_NOT_OK_RAISE(status); /* close the file handle */ - req = cli_close_send(NULL, self->ev, self->cli, fnum); + req = cli_close_send(NULL, self->ev, self->cli, fnum, 0); if (!py_tevent_req_wait_exc(self, req)) { return NULL; } @@ -1492,7 +1493,7 @@ static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args) } /* close the file handle */ - req = cli_close_send(NULL, self->ev, self->cli, fnum); + req = cli_close_send(NULL, self->ev, self->cli, fnum, 0); if (!py_tevent_req_wait_exc(self, req)) { Py_XDECREF(result); return NULL; @@ -3014,5 +3015,7 @@ MODULE_INIT_FUNC(libsmb_samba_cwrapper) ADD_FLAGS(FILE_OVERWRITE_IF); ADD_FLAGS(FILE_DIRECTORY_FILE); + ADD_FLAGS(SMB2_CLOSE_FLAGS_FULL_INFORMATION); + return m; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index d912acbb409..52c23ba93ea 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -997,7 +997,20 @@ NTSTATUS fd_close(files_struct *fsp) if (fsp->fsp_flags.fstat_before_close) { status = vfs_stat_fsp(fsp); if (!NT_STATUS_IS_OK(status)) { - return status; + /* + * If this is a stream and delete-on-close was set, the + * backing object (an xattr from streams_xattr) might + * already be deleted so fstat() fails with + * NT_STATUS_NOT_FOUND. So if fsp refers to a stream we + * ignore the error and only bail for normal files where + * an fstat() should still work. NB. We cannot use + * fsp_is_alternate_stream(fsp) for this as the base_fsp + * has already been closed at this point and so the value + * fsp_is_alternate_stream() checks for is already NULL. + */ + if (fsp->fsp_name->stream_name == NULL) { + return status; + } } } diff --git a/source3/torture/nbench.c b/source3/torture/nbench.c index e9a0b4f2f33..8646d7a9b7c 100644 --- a/source3/torture/nbench.c +++ b/source3/torture/nbench.c @@ -274,8 +274,11 @@ static struct tevent_req *nbench_cmd_send(TALLOC_CTX *mem_ctx, tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return tevent_req_post(req, ev); } - subreq = cli_close_send( - state, ev, nb_state->cli, state->ft->fnum); + subreq = cli_close_send(state, + ev, + nb_state->cli, + state->ft->fnum, + 0); break; } case NBENCH_CMD_MKDIR: { diff --git a/source3/torture/test_chain3.c b/source3/torture/test_chain3.c index d957e5145d4..5320ef898f0 100644 --- a/source3/torture/test_chain3.c +++ b/source3/torture/test_chain3.c @@ -206,7 +206,7 @@ static void chain3_got_break(struct tevent_req *subreq) if (tevent_req_nterror(req, status)) { return; } - subreq = cli_close_send(state, state->ev, state->cli, fnum); + subreq = cli_close_send(state, state->ev, state->cli, fnum, 0); if (tevent_req_nomem(subreq, req)) { return; } diff --git a/source3/torture/test_notify.c b/source3/torture/test_notify.c index 33c2381fbbd..b265845f822 100644 --- a/source3/torture/test_notify.c +++ b/source3/torture/test_notify.c @@ -137,7 +137,7 @@ static void wait_for_one_notify_done(struct tevent_req *subreq) if (tevent_req_nterror(req, status)) { return; } - subreq = cli_close_send(state, state->ev, state->cli, state->dnum); + subreq = cli_close_send(state, state->ev, state->cli, state->dnum, 0); if (tevent_req_nomem(subreq, req)) { return; } @@ -501,8 +501,11 @@ static void notify_bench3_before_close_subdir(struct tevent_req *subreq) tevent_req_nterror(req, map_nt_error_from_unix(ret)); return; } - subreq = cli_close_send(state, state->ev, state->cli, -- Samba Shared Repository