The Samba-Bugzilla – Attachment 15969 Details for
Bug 14361
vfs_io_uring sometimes cause data corruption with Windows clients
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Possible patch for master (should also apply to 4.12)
tmp.diff.txt (text/plain), 66.44 KB, created by
Stefan Metzmacher
on 2020-05-11 20:58:51 UTC
(
hide
)
Description:
Possible patch for master (should also apply to 4.12)
Filename:
MIME Type:
Creator:
Stefan Metzmacher
Created:
2020-05-11 20:58:51 UTC
Size:
66.44 KB
patch
obsolete
>From 1f3b7158c37e5205b962d84dcf6e65b24b230c23 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 11 May 2020 12:37:41 +0200 >Subject: [PATCH 01/31] s4:torture: add tests to test the SMB2 read/write > offset/length boundaries > >[MS-FSA] 2.1.5.2 Server Requests a Read and >2.1.5.3 Server Requests a Write define some contraints. > >These tests demonstrate that ((int64_t)offset) < 0) is >not allowed for both reads and writes for SMB. >Also the special case for writes at offset -2 is not possible >nor the append mode with offset < 0. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > selftest/knownfail.d/rw-invalid | 2 + > source4/torture/smb2/read_write.c | 189 ++++++++++++++++++++++++++++++ > 2 files changed, 191 insertions(+) > create mode 100644 selftest/knownfail.d/rw-invalid > >diff --git a/selftest/knownfail.d/rw-invalid b/selftest/knownfail.d/rw-invalid >new file mode 100644 >index 000000000000..c6f11e03d20b >--- /dev/null >+++ b/selftest/knownfail.d/rw-invalid >@@ -0,0 +1,2 @@ >+samba3.smb2.rw.invalid >+samba4.smb2.rw.invalid >diff --git a/source4/torture/smb2/read_write.c b/source4/torture/smb2/read_write.c >index bc8898cec31a..b0eea55d7f1f 100644 >--- a/source4/torture/smb2/read_write.c >+++ b/source4/torture/smb2/read_write.c >@@ -23,8 +23,19 @@ > #include "libcli/smb2/smb2.h" > #include "libcli/smb2/smb2_calls.h" > #include "torture/torture.h" >+#include "torture/util.h" > #include "torture/smb2/proto.h" > >+#define CHECK_STATUS(_status, _expected) \ >+ torture_assert_ntstatus_equal_goto(torture, _status, _expected, \ >+ ret, done, "Incorrect status") >+ >+#define CHECK_VALUE(v, correct) \ >+ torture_assert_int_equal_goto(torture, v, correct, \ >+ ret, done, "Incorrect value") >+ >+#define FNAME "smb2_writetest.dat" >+ > static bool run_smb2_readwritetest(struct torture_context *tctx, > struct smb2_tree *t1, struct smb2_tree *t2) > { >@@ -150,12 +161,190 @@ static bool run_smb2_wrap_readwritetest(struct torture_context *tctx, > return run_smb2_readwritetest(tctx, tree1, tree1); > } > >+static bool test_rw_invalid(struct torture_context *torture, struct smb2_tree *tree) >+{ >+ bool ret = true; >+ NTSTATUS status; >+ struct smb2_handle h; >+ uint8_t buf[64*1024]; >+ struct smb2_read rd; >+ struct smb2_write w = {0}; >+ TALLOC_CTX *tmp_ctx = talloc_new(tree); >+ >+ ZERO_STRUCT(buf); >+ >+ smb2_util_unlink(tree, FNAME); >+ >+ status = torture_smb2_testfile(tree, FNAME, &h); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf)); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ >+ ZERO_STRUCT(rd); >+ rd.in.file.handle = h; >+ rd.in.length = 10; >+ rd.in.offset = 0; >+ rd.in.min_count = 1; >+ >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VALUE(rd.out.data.length, 10); >+ >+ rd.in.min_count = 0; >+ rd.in.length = 10; >+ rd.in.offset = sizeof(buf); >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_END_OF_FILE); >+ >+ rd.in.min_count = 0; >+ rd.in.length = 0; >+ rd.in.offset = sizeof(buf); >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VALUE(rd.out.data.length, 0); >+ >+ rd.in.min_count = 0; >+ rd.in.length = 1; >+ rd.in.offset = INT64_MAX - 1; >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_END_OF_FILE); >+ >+ rd.in.min_count = 0; >+ rd.in.length = 0; >+ rd.in.offset = INT64_MAX; >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VALUE(rd.out.data.length, 0); >+ >+ rd.in.min_count = 0; >+ rd.in.length = 1; >+ rd.in.offset = INT64_MAX; >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ rd.in.min_count = 0; >+ rd.in.length = 0; >+ rd.in.offset = (uint64_t)INT64_MAX + 1; >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ rd.in.min_count = 0; >+ rd.in.length = 0; >+ rd.in.offset = (uint64_t)INT64_MIN; >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ rd.in.min_count = 0; >+ rd.in.length = 0; >+ rd.in.offset = (uint64_t)(int64_t)-1; >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ rd.in.min_count = 0; >+ rd.in.length = 0; >+ rd.in.offset = (uint64_t)(int64_t)-2; >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ rd.in.min_count = 0; >+ rd.in.length = 0; >+ rd.in.offset = (uint64_t)(int64_t)-3; >+ status = smb2_read(tree, tmp_ctx, &rd); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ w.in.file.handle = h; >+ w.in.offset = (int64_t)-1; >+ w.in.data.data = buf; >+ w.in.data.length = ARRAY_SIZE(buf); >+ >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ w.in.file.handle = h; >+ w.in.offset = (int64_t)-2; >+ w.in.data.data = buf; >+ w.in.data.length = ARRAY_SIZE(buf); >+ >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ w.in.file.handle = h; >+ w.in.offset = INT64_MIN; >+ w.in.data.data = buf; >+ w.in.data.length = 1; >+ >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ w.in.file.handle = h; >+ w.in.offset = INT64_MIN; >+ w.in.data.data = buf; >+ w.in.data.length = 0; >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ w.in.file.handle = h; >+ w.in.offset = INT64_MAX; >+ w.in.data.data = buf; >+ w.in.data.length = 0; >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VALUE(w.out.nwritten, 0); >+ >+ w.in.file.handle = h; >+ w.in.offset = INT64_MAX; >+ w.in.data.data = buf; >+ w.in.data.length = 1; >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ w.in.file.handle = h; >+ w.in.offset = (uint64_t)INT64_MAX + 1; >+ w.in.data.data = buf; >+ w.in.data.length = 0; >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ w.in.file.handle = h; >+ w.in.offset = 0xfffffff0000; /* MAXFILESIZE */ >+ w.in.data.data = buf; >+ w.in.data.length = 1; >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER); >+ >+ w.in.file.handle = h; >+ w.in.offset = 0xfffffff0000 - 1; /* MAXFILESIZE - 1 */ >+ w.in.data.data = buf; >+ w.in.data.length = 1; >+ status = smb2_write(tree, &w); >+ if (TARGET_IS_SAMBA3(torture) || TARGET_IS_SAMBA4(torture)) { >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VALUE(w.out.nwritten, 1); >+ } else { >+ CHECK_STATUS(status, NT_STATUS_DISK_FULL); >+ } >+ >+ w.in.file.handle = h; >+ w.in.offset = 0xfffffff0000; /* MAXFILESIZE */ >+ w.in.data.data = buf; >+ w.in.data.length = 0; >+ status = smb2_write(tree, &w); >+ CHECK_STATUS(status, NT_STATUS_OK); >+ CHECK_VALUE(w.out.nwritten, 0); >+ >+done: >+ talloc_free(tmp_ctx); >+ return ret; >+} >+ > struct torture_suite *torture_smb2_readwrite_init(TALLOC_CTX *ctx) > { > struct torture_suite *suite = torture_suite_create(ctx, "rw"); > > torture_suite_add_2smb2_test(suite, "rw1", run_smb2_readwritetest); > torture_suite_add_2smb2_test(suite, "rw2", run_smb2_wrap_readwritetest); >+ torture_suite_add_1smb2_test(suite, "invalid", test_rw_invalid); > > suite->description = talloc_strdup(suite, "SMB2 Samba4 Read/Write"); > >-- >2.17.1 > > >From 96a22c0f125cc9bc4684394f09d472705340ced2 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 13:06:54 +0200 >Subject: [PATCH 02/31] lib: util: Add sys_valid_io_range() > >This implements the contraints of >[MS-FSA] 2.1.5.2 Server Requests a Read. > >The special handling of [MS-FSA] 2.1.5.3 Server Requests a Write >with offset < 0, should be handled by higher layers! >Which means the check can also be used for writes. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > lib/util/sys_rw.c | 24 ++++++++++++++++++++++++ > lib/util/sys_rw.h | 1 + > 2 files changed, 25 insertions(+) > >diff --git a/lib/util/sys_rw.c b/lib/util/sys_rw.c >index 9a6cdcaa6063..6fa7ca573654 100644 >--- a/lib/util/sys_rw.c >+++ b/lib/util/sys_rw.c >@@ -24,6 +24,30 @@ > #include "system/filesys.h" > #include "lib/util/sys_rw.h" > >+bool sys_valid_io_range(off_t offset, size_t length) >+{ >+ uint64_t last_byte_ofs; >+ >+ if (offset < 0) { >+ return false; >+ } >+ >+ if (offset > INT64_MAX) { >+ return false; >+ } >+ >+ if (length > UINT32_MAX) { >+ return false; >+ } >+ >+ last_byte_ofs = (uint64_t)offset + (uint64_t)length; >+ if (last_byte_ofs > INT64_MAX) { >+ return false; >+ } >+ >+ return true; >+} >+ > /******************************************************************* > A read wrapper that will deal with EINTR/EWOULDBLOCK > ********************************************************************/ >diff --git a/lib/util/sys_rw.h b/lib/util/sys_rw.h >index ab456d87b22e..70864cb2b74a 100644 >--- a/lib/util/sys_rw.h >+++ b/lib/util/sys_rw.h >@@ -27,6 +27,7 @@ > > struct iovec; > >+bool sys_valid_io_range(off_t offset, size_t length); > ssize_t sys_read(int fd, void *buf, size_t count); > void sys_read_v(int fd, void *buf, size_t count); > ssize_t sys_write(int fd, const void *buf, size_t count); >-- >2.17.1 > > >From 0534b1999f6300ea5f3738188f32a936f8ae5d35 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 7 May 2020 12:32:48 -0700 >Subject: [PATCH 03/31] lib: util: Add sys_pread_full(). > >A pread wrapper that will deal with EINTR and never return a short >read unless pread returns zero meaning EOF. > >Thread-safe so may be used as a replacement for pread >inside pread_do() thread functions. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> > >Signed-off-by: Jeremy Allison <jra@samba.org> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > lib/util/sys_rw.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ > lib/util/sys_rw.h | 1 + > 2 files changed, 49 insertions(+) > >diff --git a/lib/util/sys_rw.c b/lib/util/sys_rw.c >index 6fa7ca573654..bfeb2e6b4661 100644 >--- a/lib/util/sys_rw.c >+++ b/lib/util/sys_rw.c >@@ -143,6 +143,54 @@ ssize_t sys_pread(int fd, void *buf, size_t count, off_t off) > return ret; > } > >+/******************************************************************* >+ A pread wrapper that will deal with EINTR and never return a short >+ read unless pread returns zero meaning EOF. >+********************************************************************/ >+ >+ssize_t sys_pread_full(int fd, void *buf, size_t count, off_t off) >+{ >+ ssize_t total_read = 0; >+ uint8_t *curr_buf = (uint8_t *)buf; >+ size_t curr_count = count; >+ off_t curr_off = off; >+ bool ok; >+ >+ ok = sys_valid_io_range(off, count); >+ if (!ok) { >+ errno = EINVAL; >+ return -1; >+ } >+ >+ while (curr_count != 0) { >+ ssize_t ret = sys_pread(fd, >+ curr_buf, >+ curr_count, >+ curr_off); >+ >+ if (ret == -1) { >+ return -1; >+ } >+ if (ret == 0) { >+ /* EOF */ >+ break; >+ } >+ >+ if (ret > curr_count) { >+ errno = EIO; >+ return -1; >+ } >+ >+ curr_buf += ret; >+ curr_count -= ret; >+ curr_off += ret; >+ >+ total_read += ret; >+ } >+ >+ return total_read; >+} >+ > /******************************************************************* > A write wrapper that will deal with EINTR > ********************************************************************/ >diff --git a/lib/util/sys_rw.h b/lib/util/sys_rw.h >index 70864cb2b74a..1e0dd3730a60 100644 >--- a/lib/util/sys_rw.h >+++ b/lib/util/sys_rw.h >@@ -34,6 +34,7 @@ ssize_t sys_write(int fd, const void *buf, size_t count); > void sys_write_v(int fd, const void *buf, size_t count); > ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt); > ssize_t sys_pread(int fd, void *buf, size_t count, off_t off); >+ssize_t sys_pread_full(int fd, void *buf, size_t count, off_t off); > ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off); > > #endif >-- >2.17.1 > > >From 24bf1acbfa180a5ef2b2c43e327374cb4fb92191 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 7 May 2020 12:34:32 -0700 >Subject: [PATCH 04/31] lib: util: Add sys_pwrite_full(). > >A pwrite wrapper that will deal with EINTR and never return a short >write unless the file system returns an error. Copes with the >unspecified edge condition of pwrite returning zero by changing >the return to -1, errno = ENOSPC. > >Thread-safe so may be used as a replacement for pwrite >inside pwrite_do() thread functions. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> > >Signed-off-by: Jeremy Allison <jra@samba.org> >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > lib/util/sys_rw.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++ > lib/util/sys_rw.h | 1 + > 2 files changed, 50 insertions(+) > >diff --git a/lib/util/sys_rw.c b/lib/util/sys_rw.c >index bfeb2e6b4661..d74395fc4091 100644 >--- a/lib/util/sys_rw.c >+++ b/lib/util/sys_rw.c >@@ -204,3 +204,52 @@ ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off) > } while (ret == -1 && errno == EINTR); > return ret; > } >+ >+/******************************************************************* >+ A pwrite wrapper that will deal with EINTR and never allow a short >+ write unless the file system returns an error. >+********************************************************************/ >+ >+ssize_t sys_pwrite_full(int fd, const void *buf, size_t count, off_t off) >+{ >+ ssize_t total_written = 0; >+ const uint8_t *curr_buf = (const uint8_t *)buf; >+ size_t curr_count = count; >+ off_t curr_off = off; >+ bool ok; >+ >+ ok = sys_valid_io_range(off, count); >+ if (!ok) { >+ errno = EINVAL; >+ return -1; >+ } >+ >+ while (curr_count != 0) { >+ ssize_t ret = sys_pwrite(fd, >+ curr_buf, >+ curr_count, >+ curr_off); >+ >+ if (ret == -1) { >+ return -1; >+ } >+ if (ret == 0) { >+ /* Ensure we can never spin. */ >+ errno = ENOSPC; >+ return -1; >+ } >+ >+ if (ret > curr_count) { >+ errno = EIO; >+ return -1; >+ } >+ >+ curr_buf += ret; >+ curr_count -= ret; >+ curr_off += ret; >+ >+ total_written += ret; >+ } >+ >+ return total_written; >+} >diff --git a/lib/util/sys_rw.h b/lib/util/sys_rw.h >index 1e0dd3730a60..b224ecb30ac7 100644 >--- a/lib/util/sys_rw.h >+++ b/lib/util/sys_rw.h >@@ -36,5 +36,6 @@ ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt); > ssize_t sys_pread(int fd, void *buf, size_t count, off_t off); > ssize_t sys_pread_full(int fd, void *buf, size_t count, off_t off); > ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off); >+ssize_t sys_pwrite_full(int fd, const void *buf, size_t count, off_t off); > > #endif >-- >2.17.1 > > >From 693e9190e78a6284a7071f73221742ad39f94416 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 11 May 2020 18:18:24 +0200 >Subject: [PATCH 05/31] smb2_server: fix smbd_smb2_request_verify_sizes() for > SMB2_OP_WRITE > >Writes with a length of 0 are allowed. > >The readfile related check we had before was not really useful >as min_dyn_len can only every be 0 or 1 (and for SMB2_OP_WRITE it's >always 1). So we checked > if (unread_bytes > 0) { > if (unread_bytes < 1) { > return error; > } > } > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/smbd/smb2_server.c | 10 +--------- > 1 file changed, 1 insertion(+), 9 deletions(-) > >diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c >index a4372bf11457..718f09415326 100644 >--- a/source3/smbd/smb2_server.c >+++ b/source3/smbd/smb2_server.c >@@ -2073,16 +2073,8 @@ NTSTATUS smbd_smb2_request_verify_sizes(struct smbd_smb2_request *req, > switch (opcode) { > case SMB2_OP_IOCTL: > case SMB2_OP_GETINFO: >- min_dyn_size = 0; >- break; > case SMB2_OP_WRITE: >- if (req->smb1req != NULL && req->smb1req->unread_bytes > 0) { >- if (req->smb1req->unread_bytes < min_dyn_size) { >- return NT_STATUS_INVALID_PARAMETER; >- } >- >- min_dyn_size = 0; >- } >+ min_dyn_size = 0; > break; > } > >-- >2.17.1 > > >From 672a77370113623fb3a87c17f85755d84708cafd Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 11 May 2020 18:18:24 +0200 >Subject: [PATCH 06/31] s3:smbd: handle 0 length writes as no-op. > >They should never touch the SMB_VFS layer >and they never trigger an DISK_FULL error. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/smbd/aio.c | 5 +++++ > source3/smbd/fileio.c | 4 ++++ > 2 files changed, 9 insertions(+) > >diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c >index 7ed2691cfbff..f89ce8537a05 100644 >--- a/source3/smbd/aio.c >+++ b/source3/smbd/aio.c >@@ -337,6 +337,11 @@ static struct tevent_req *pwrite_fsync_send(TALLOC_CTX *mem_ctx, > state->fsp = fsp; > state->write_through = write_through; > >+ if (n == 0) { >+ tevent_req_done(req); >+ return tevent_req_post(req, ev); >+ } >+ > subreq = SMB_VFS_PWRITE_SEND(state, ev, fsp, data, n, offset); > if (tevent_req_nomem(subreq, req)) { > return tevent_req_post(req, ev); >diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c >index 6d58bdbbc97e..079d414db05f 100644 >--- a/source3/smbd/fileio.c >+++ b/source3/smbd/fileio.c >@@ -70,6 +70,10 @@ static ssize_t real_write_file(struct smb_request *req, > { > ssize_t ret; > >+ if (n == 0) { >+ return 0; >+ } >+ > fsp->fh->pos = pos; > if (pos && > lp_strict_allocate(SNUM(fsp->conn)) && >-- >2.17.1 > > >From 02deeda3d9a007480b66e2e1a281d57970775761 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 11 May 2020 22:00:37 +0200 >Subject: [PATCH 07/31] s3:smbd: add vfs_valid_{pread,pwrite}_range() helper > functions > >These implement the SMB2 visible behavior of the [MS-FSA] >2.1.5.2 Server Requests a Read and 2.1.5.3 Server Requests a Write >constraints. Note that offset < 0 is not allowed over SMB. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/smbd/proto.h | 2 ++ > source3/smbd/vfs.c | 32 ++++++++++++++++++++++++++++++++ > 2 files changed, 34 insertions(+) > >diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h >index 98eb2843c070..ba72fb94e0fc 100644 >--- a/source3/smbd/proto.h >+++ b/source3/smbd/proto.h >@@ -1295,6 +1295,8 @@ void sys_utmp_yield(const char *username, const char *hostname, > bool vfs_init_custom(connection_struct *conn, const char *vfs_object); > bool smbd_vfs_init(connection_struct *conn); > NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname); >+bool vfs_valid_pread_range(off_t offset, size_t length); >+bool vfs_valid_pwrite_range(off_t offset, size_t length); > ssize_t vfs_pwrite_data(struct smb_request *req, > files_struct *fsp, > const char *buffer, >diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c >index 9c75ceed6aee..5141da728a78 100644 >--- a/source3/smbd/vfs.c >+++ b/source3/smbd/vfs.c >@@ -32,6 +32,7 @@ > #include "ntioctl.h" > #include "lib/util/tevent_unix.h" > #include "lib/util/tevent_ntstatus.h" >+#include "lib/util/sys_rw.h" > > #undef DBGC_CLASS > #define DBGC_CLASS DBGC_VFS >@@ -415,6 +416,37 @@ NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname) > return NT_STATUS_OBJECT_NAME_NOT_FOUND; > } > >+bool vfs_valid_pread_range(off_t offset, size_t length) >+{ >+ return sys_valid_io_range(offset, length); >+} >+ >+bool vfs_valid_pwrite_range(off_t offset, size_t length) >+{ >+ /* >+ * See MAXFILESIZE in [MS-FSA] 2.1.5.3 Server Requests a Write >+ */ >+ static const uint64_t maxfilesize = 0xfffffff0000; >+ uint64_t last_byte_ofs; >+ bool ok; >+ >+ ok = sys_valid_io_range(offset, length); >+ if (!ok) { >+ return false; >+ } >+ >+ if (length == 0) { >+ return true; >+ } >+ >+ last_byte_ofs = offset + length; >+ if (last_byte_ofs > maxfilesize) { >+ return false; >+ } >+ >+ return true; >+} >+ > ssize_t vfs_pwrite_data(struct smb_request *req, > files_struct *fsp, > const char *buffer, >-- >2.17.1 > > >From 31c111d3627319afeb7ee87285679e124559e81e Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Mon, 11 May 2020 18:18:24 +0200 >Subject: [PATCH 08/31] smbd: add vfs_valid_{pread,pwrite}_range() checks where > needed > >I checked all callers of SMB_VFS_PWRITE[_SEND](), >all callers of SMB_VFS_PREAD[_SEND]() and also >places where we append to the file and allocate >more space. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > selftest/knownfail.d/rw-invalid | 3 +-- > source3/modules/vfs_default.c | 7 +++++++ > source3/smbd/aio.c | 19 ++++++++++++++++++ > source3/smbd/fileio.c | 14 ++++++++++++++ > source3/smbd/vfs.c | 34 +++++++++++++++++++++++++++++++-- > 5 files changed, 73 insertions(+), 4 deletions(-) > >diff --git a/selftest/knownfail.d/rw-invalid b/selftest/knownfail.d/rw-invalid >index c6f11e03d20b..ac5fe5732390 100644 >--- a/selftest/knownfail.d/rw-invalid >+++ b/selftest/knownfail.d/rw-invalid >@@ -1,2 +1 @@ >-samba3.smb2.rw.invalid >-samba4.smb2.rw.invalid >+samba4.smb2.rw.invalid.ad_dc_ntvfs >diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c >index c7f2020a9ead..b5fbc0ed5dc4 100644 >--- a/source3/modules/vfs_default.c >+++ b/source3/modules/vfs_default.c >@@ -2579,6 +2579,13 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs > int ret; > NTSTATUS status; > SMB_STRUCT_STAT *pst; >+ bool ok; >+ >+ ok = vfs_valid_pwrite_range(len, 0); >+ if (!ok) { >+ errno = EINVAL; >+ return -1; >+ } > > status = vfs_stat_fsp(fsp); > if (!NT_STATUS_IS_OK(status)) { >diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c >index f89ce8537a05..f141d6731674 100644 >--- a/source3/smbd/aio.c >+++ b/source3/smbd/aio.c >@@ -164,6 +164,12 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn, > size_t bufsize; > size_t min_aio_read_size = lp_aio_read_size(SNUM(conn)); > struct tevent_req *req; >+ bool ok; >+ >+ ok = vfs_valid_pread_range(startpos, smb_maxcnt); >+ if (!ok) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } > > if (fsp->base_fsp != NULL) { > /* No AIO on streams yet */ >@@ -328,6 +334,7 @@ static struct tevent_req *pwrite_fsync_send(TALLOC_CTX *mem_ctx, > { > struct tevent_req *req, *subreq; > struct pwrite_fsync_state *state; >+ bool ok; > > req = tevent_req_create(mem_ctx, &state, struct pwrite_fsync_state); > if (req == NULL) { >@@ -337,6 +344,12 @@ static struct tevent_req *pwrite_fsync_send(TALLOC_CTX *mem_ctx, > state->fsp = fsp; > state->write_through = write_through; > >+ ok = vfs_valid_pwrite_range(offset, n); >+ if (!ok) { >+ tevent_req_error(req, EINVAL); >+ return tevent_req_post(req, ev); >+ } >+ > if (n == 0) { > tevent_req_done(req); > return tevent_req_post(req, ev); >@@ -664,6 +677,12 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn, > struct aio_extra *aio_ex; > size_t min_aio_read_size = lp_aio_read_size(SNUM(conn)); > struct tevent_req *req; >+ bool ok; >+ >+ ok = vfs_valid_pread_range(startpos, smb_maxcnt); >+ if (!ok) { >+ return NT_STATUS_INVALID_PARAMETER; >+ } > > if (fsp->base_fsp != NULL) { > /* No AIO on streams yet */ >diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c >index 079d414db05f..40c770da8bdc 100644 >--- a/source3/smbd/fileio.c >+++ b/source3/smbd/fileio.c >@@ -32,6 +32,7 @@ > ssize_t read_file(files_struct *fsp,char *data,off_t pos,size_t n) > { > ssize_t ret = 0; >+ bool ok; > > /* you can't read from print files */ > if (fsp->print_file) { >@@ -39,6 +40,12 @@ ssize_t read_file(files_struct *fsp,char *data,off_t pos,size_t n) > return -1; > } > >+ ok = vfs_valid_pread_range(pos, n); >+ if (!ok) { >+ errno = EINVAL; >+ return -1; >+ } >+ > fsp->fh->pos = pos; > > if (n > 0) { >@@ -69,6 +76,13 @@ static ssize_t real_write_file(struct smb_request *req, > size_t n) > { > ssize_t ret; >+ bool ok; >+ >+ ok = vfs_valid_pwrite_range(pos, n); >+ if (!ok) { >+ errno = EINVAL; >+ return -1; >+ } > > if (n == 0) { > return 0; >diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c >index 5141da728a78..f49b53f4b7c6 100644 >--- a/source3/smbd/vfs.c >+++ b/source3/smbd/vfs.c >@@ -455,6 +455,13 @@ ssize_t vfs_pwrite_data(struct smb_request *req, > { > size_t total=0; > ssize_t ret; >+ bool ok; >+ >+ ok = vfs_valid_pwrite_range(offset, N); >+ if (!ok) { >+ errno = EINVAL; >+ return -1; >+ } > > if (req && req->unread_bytes) { > int sockfd = req->xconn->transport.sock; >@@ -531,6 +538,7 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) > uint64_t space_avail; > uint64_t bsize,dfree,dsize; > NTSTATUS status; >+ bool ok; > > /* > * Actually try and commit the space on disk.... >@@ -539,8 +547,9 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) > DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n", > fsp_str_dbg(fsp), (double)len)); > >- if (((off_t)len) < 0) { >- DEBUG(0,("vfs_allocate_file_space: %s negative len " >+ ok = vfs_valid_pwrite_range((off_t)len, 0); >+ if (!ok) { >+ DEBUG(0,("vfs_allocate_file_space: %s negative/invalid len " > "requested.\n", fsp_str_dbg(fsp))); > errno = EINVAL; > return -1; >@@ -625,6 +634,13 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) > int vfs_set_filelen(files_struct *fsp, off_t len) > { > int ret; >+ bool ok; >+ >+ ok = vfs_valid_pwrite_range(len, 0); >+ if (!ok) { >+ errno = EINVAL; >+ return -1; >+ } > > contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN); > >@@ -656,6 +672,13 @@ int vfs_slow_fallocate(files_struct *fsp, off_t offset, off_t len) > { > ssize_t pwrite_ret; > size_t total = 0; >+ bool ok; >+ >+ ok = vfs_valid_pwrite_range(offset, len); >+ if (!ok) { >+ errno = EINVAL; >+ return -1; >+ } > > if (!sparse_buf) { > sparse_buf = SMB_CALLOC_ARRAY(char, SPARSE_BUF_WRITE_SIZE); >@@ -696,6 +719,13 @@ int vfs_fill_sparse(files_struct *fsp, off_t len) > NTSTATUS status; > off_t offset; > size_t num_to_write; >+ bool ok; >+ >+ ok = vfs_valid_pwrite_range(len, 0); >+ if (!ok) { >+ errno = EINVAL; >+ return -1; >+ } > > status = vfs_stat_fsp(fsp); > if (!NT_STATUS_IS_OK(status)) { >-- >2.17.1 > > >From 147d0fe676b5a611c7eb39b6586cccc78148be08 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 7 May 2020 12:42:10 -0700 >Subject: [PATCH 09/31] s3: VFS: aio_fork: Change sys_pread() -> > sys_pread_full() to protect against short reads. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/modules/vfs_aio_fork.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/modules/vfs_aio_fork.c b/source3/modules/vfs_aio_fork.c >index a1fed5c06557..285b331ff9ca 100644 >--- a/source3/modules/vfs_aio_fork.c >+++ b/source3/modules/vfs_aio_fork.c >@@ -342,7 +342,7 @@ static void aio_child_loop(int sockfd, struct mmap_area *map) > > switch (cmd_struct.cmd) { > case READ_CMD: >- ret_struct.size = sys_pread( >+ ret_struct.size = sys_pread_full( > fd, discard_const(map->ptr), cmd_struct.n, > cmd_struct.offset); > #if 0 >-- >2.17.1 > > >From 07cf444ca29279aec67e4d7067a7ee35a3242531 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 7 May 2020 12:42:53 -0700 >Subject: [PATCH 10/31] s3: VFS: aio_fork: Change sys_pwrite() -> > sys_pwrite_full() to protect against short writes. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_aio_fork.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/modules/vfs_aio_fork.c b/source3/modules/vfs_aio_fork.c >index 285b331ff9ca..7c6f4b00fd04 100644 >--- a/source3/modules/vfs_aio_fork.c >+++ b/source3/modules/vfs_aio_fork.c >@@ -353,7 +353,7 @@ static void aio_child_loop(int sockfd, struct mmap_area *map) > #endif > break; > case WRITE_CMD: >- ret_struct.size = sys_pwrite( >+ ret_struct.size = sys_pwrite_full( > fd, discard_const(map->ptr), cmd_struct.n, > cmd_struct.offset); > break; >-- >2.17.1 > > >From 777fffa160588496bf11b6e19355bc0cd7f8c958 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 7 May 2020 12:43:34 -0700 >Subject: [PATCH 11/31] s3: VFS: default. Change sys_pread() -> > sys_pread_full() in SMB_VFS_PREAD() to protect against short reads. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/modules/vfs_default.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c >index b5fbc0ed5dc4..f76d7c7b918b 100644 >--- a/source3/modules/vfs_default.c >+++ b/source3/modules/vfs_default.c >@@ -734,7 +734,7 @@ static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void > > #if defined(HAVE_PREAD) || defined(HAVE_PREAD64) > START_PROFILE_BYTES(syscall_pread, n); >- result = sys_pread(fsp->fh->fd, data, n, offset); >+ result = sys_pread_full(fsp->fh->fd, data, n, offset); > END_PROFILE_BYTES(syscall_pread); > > if (result == -1 && errno == ESPIPE) { >-- >2.17.1 > > >From fadc02637234662d09f1bc56dbf35201e0c8eec1 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 7 May 2020 12:44:26 -0700 >Subject: [PATCH 12/31] s3: VFS: default. Change sys_pwrite() -> > sys_pwrite_full() in SMB_VFS_PWRITE() to protect against short writes. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_default.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c >index f76d7c7b918b..ff46966536b8 100644 >--- a/source3/modules/vfs_default.c >+++ b/source3/modules/vfs_default.c >@@ -758,7 +758,7 @@ static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, cons > > #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64) > START_PROFILE_BYTES(syscall_pwrite, n); >- result = sys_pwrite(fsp->fh->fd, data, n, offset); >+ result = sys_pwrite_full(fsp->fh->fd, data, n, offset); > END_PROFILE_BYTES(syscall_pwrite); > > if (result == -1 && errno == ESPIPE) { >-- >2.17.1 > > >From 86c6e78fd55a03ef753bb5796c4ae8bcfd816261 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 7 May 2020 12:45:10 -0700 >Subject: [PATCH 13/31] s3: VFS: default. Change pread() -> sys_pread_full() in > SMB_VFS_PREAD_SEND() to protect against short reads. > >Note that as sys_pread_full() deals with the EINTR case >we can remove the do {} while loop here. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Jeremy Allison <jra@samba.org> >--- > source3/modules/vfs_default.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > >diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c >index ff46966536b8..bce50b990c11 100644 >--- a/source3/modules/vfs_default.c >+++ b/source3/modules/vfs_default.c >@@ -838,10 +838,10 @@ static void vfs_pread_do(void *private_data) > > PROFILE_TIMESTAMP(&start_time); > >- do { >- state->ret = pread(state->fd, state->buf, state->count, >- state->offset); >- } while ((state->ret == -1) && (errno == EINTR)); >+ state->ret = sys_pread_full(state->fd, >+ state->buf, >+ state->count, >+ state->offset); > > if (state->ret == -1) { > state->vfs_aio_state.error = errno; >-- >2.17.1 > > >From 8e194063c88953f213418d99bc0cee1397dbbd78 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 7 May 2020 12:48:49 -0700 >Subject: [PATCH 14/31] s3: VFS: default. Change pwrite() -> sys_pwrite_full() > in SMB_VFS_PWRITE_SEND() to protect against short writes. > >Note that as sys_pwrite_full() deals with the EINTR case >we can remove the do {} while loop here. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_default.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > >diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c >index bce50b990c11..386a34f81d12 100644 >--- a/source3/modules/vfs_default.c >+++ b/source3/modules/vfs_default.c >@@ -966,10 +966,10 @@ static void vfs_pwrite_do(void *private_data) > > PROFILE_TIMESTAMP(&start_time); > >- do { >- state->ret = pwrite(state->fd, state->buf, state->count, >- state->offset); >- } while ((state->ret == -1) && (errno == EINTR)); >+ state->ret = sys_pwrite_full(state->fd, >+ state->buf, >+ state->count, >+ state->offset); > > if (state->ret == -1) { > state->vfs_aio_state.error = errno; >-- >2.17.1 > > >From 9bb462055192ecc28f115725a1613dc2ef087fe2 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Wed, 6 May 2020 03:05:47 -0700 >Subject: [PATCH 15/31] vfs_io_uring: fix the prefix for parametric options > from 'vfs_io_uring' to 'io_uring' > >This is what the manpage describes. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index 378e48d112f6..b409d0753379 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -172,13 +172,13 @@ static int vfs_io_uring_connect(vfs_handle_struct *handle, const char *service, > } > > num_entries = lp_parm_ulong(SNUM(handle->conn), >- "vfs_io_uring", >+ "io_uring", > "num_entries", > 128); > num_entries = MAX(num_entries, 1); > > sqpoll = lp_parm_bool(SNUM(handle->conn), >- "vfs_io_uring", >+ "io_uring", > "sqpoll", > false); > if (sqpoll) { >-- >2.17.1 > > >From 4c9cbd31a54a5a3d4e6b0374e61cba9bf054b2ac Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 10:39:52 +0200 >Subject: [PATCH 16/31] vfs_io_uring: replace vfs_io_uring_request->state with > _tevent_req_data() > >We don't need a direct pointer to the state... > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 10 ++++------ > 1 file changed, 4 insertions(+), 6 deletions(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index b409d0753379..988b309da525 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -42,7 +42,6 @@ struct vfs_io_uring_request { > struct vfs_io_uring_request **list_head; > struct vfs_io_uring_config *config; > struct tevent_req *req; >- void *state; > struct io_uring_sqe sqe; > struct io_uring_cqe cqe; > struct timespec start_time; >@@ -58,8 +57,9 @@ static void vfs_io_uring_finish_req(struct vfs_io_uring_request *cur, > struct tevent_req *req = > talloc_get_type_abort(cur->req, > struct tevent_req); >+ void *state = _tevent_req_data(req); > >- talloc_set_destructor(cur->state, NULL); >+ talloc_set_destructor(state, NULL); > if (cur->list_head != NULL) { > DLIST_REMOVE((*cur->list_head), cur); > cur->list_head = NULL; >@@ -238,6 +238,7 @@ static void vfs_io_uring_queue_run(struct vfs_io_uring_config *config) > > for (cur = config->queue; cur != NULL; cur = next) { > struct io_uring_sqe *sqe = NULL; >+ void *state = _tevent_req_data(cur->req); > > next = cur->next; > >@@ -246,7 +247,7 @@ static void vfs_io_uring_queue_run(struct vfs_io_uring_config *config) > break; > } > >- talloc_set_destructor(cur->state, >+ talloc_set_destructor(state, > vfs_io_uring_request_state_deny_destructor); > DLIST_REMOVE(config->queue, cur); > *sqe = cur->sqe; >@@ -318,7 +319,6 @@ static struct tevent_req *vfs_io_uring_pread_send(struct vfs_handle_struct *hand > } > state->ur.config = config; > state->ur.req = req; >- state->ur.state = state; > > SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p, > state->ur.profile_bytes, n); >@@ -398,7 +398,6 @@ static struct tevent_req *vfs_io_uring_pwrite_send(struct vfs_handle_struct *han > } > state->ur.config = config; > state->ur.req = req; >- state->ur.state = state; > > SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p, > state->ur.profile_bytes, n); >@@ -475,7 +474,6 @@ static struct tevent_req *vfs_io_uring_fsync_send(struct vfs_handle_struct *hand > } > state->ur.config = config; > state->ur.req = req; >- state->ur.state = state; > > SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p, > state->ur.profile_bytes, 0); >-- >2.17.1 > > >From f1f88f7e78bc01a10dacba2194b4f4981cecc7a9 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 10:42:59 +0200 >Subject: [PATCH 17/31] vfs_io_uring: introduce > vfs_io_uring_request->completion_fn() > >We'll need to add more logic than a simple _tevent_req_done() > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 49 +++++++++++++++++++++++++++++++++- > 1 file changed, 48 insertions(+), 1 deletion(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index 988b309da525..abdd4d16e9f8 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -44,6 +44,8 @@ struct vfs_io_uring_request { > struct tevent_req *req; > struct io_uring_sqe sqe; > struct io_uring_cqe cqe; >+ void (*completion_fn)(struct vfs_io_uring_request *cur, >+ const char *location); > struct timespec start_time; > struct timespec end_time; > SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes); >@@ -74,7 +76,7 @@ static void vfs_io_uring_finish_req(struct vfs_io_uring_request *cur, > * or tevent_req_defer_callback() being called > * already. > */ >- _tevent_req_done(req, location); >+ cur->completion_fn(cur, location); > } > > static void vfs_io_uring_config_destroy(struct vfs_io_uring_config *config, >@@ -297,6 +299,9 @@ struct vfs_io_uring_pread_state { > struct iovec iov; > }; > >+static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur, >+ const char *location); >+ > static struct tevent_req *vfs_io_uring_pread_send(struct vfs_handle_struct *handle, > TALLOC_CTX *mem_ctx, > struct tevent_context *ev, >@@ -319,6 +324,7 @@ static struct tevent_req *vfs_io_uring_pread_send(struct vfs_handle_struct *hand > } > state->ur.config = config; > state->ur.req = req; >+ state->ur.completion_fn = vfs_io_uring_pread_completion; > > SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pread, profile_p, > state->ur.profile_bytes, n); >@@ -344,6 +350,17 @@ static struct tevent_req *vfs_io_uring_pread_send(struct vfs_handle_struct *hand > return req; > } > >+static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur, >+ const char *location) >+{ >+ /* >+ * We rely on being inside the _send() function >+ * or tevent_req_defer_callback() being called >+ * already. >+ */ >+ _tevent_req_done(cur->req, location); >+} >+ > static ssize_t vfs_io_uring_pread_recv(struct tevent_req *req, > struct vfs_aio_state *vfs_aio_state) > { >@@ -376,6 +393,9 @@ struct vfs_io_uring_pwrite_state { > struct iovec iov; > }; > >+static void vfs_io_uring_pwrite_completion(struct vfs_io_uring_request *cur, >+ const char *location); >+ > static struct tevent_req *vfs_io_uring_pwrite_send(struct vfs_handle_struct *handle, > TALLOC_CTX *mem_ctx, > struct tevent_context *ev, >@@ -398,6 +418,7 @@ static struct tevent_req *vfs_io_uring_pwrite_send(struct vfs_handle_struct *han > } > state->ur.config = config; > state->ur.req = req; >+ state->ur.completion_fn = vfs_io_uring_pwrite_completion; > > SMBPROFILE_BYTES_ASYNC_START(syscall_asys_pwrite, profile_p, > state->ur.profile_bytes, n); >@@ -423,6 +444,17 @@ static struct tevent_req *vfs_io_uring_pwrite_send(struct vfs_handle_struct *han > return req; > } > >+static void vfs_io_uring_pwrite_completion(struct vfs_io_uring_request *cur, >+ const char *location) >+{ >+ /* >+ * We rely on being inside the _send() function >+ * or tevent_req_defer_callback() being called >+ * already. >+ */ >+ _tevent_req_done(cur->req, location); >+} >+ > static ssize_t vfs_io_uring_pwrite_recv(struct tevent_req *req, > struct vfs_aio_state *vfs_aio_state) > { >@@ -454,6 +486,9 @@ struct vfs_io_uring_fsync_state { > struct vfs_io_uring_request ur; > }; > >+static void vfs_io_uring_fsync_completion(struct vfs_io_uring_request *cur, >+ const char *location); >+ > static struct tevent_req *vfs_io_uring_fsync_send(struct vfs_handle_struct *handle, > TALLOC_CTX *mem_ctx, > struct tevent_context *ev, >@@ -474,6 +509,7 @@ static struct tevent_req *vfs_io_uring_fsync_send(struct vfs_handle_struct *hand > } > state->ur.config = config; > state->ur.req = req; >+ state->ur.completion_fn = vfs_io_uring_fsync_completion; > > SMBPROFILE_BYTES_ASYNC_START(syscall_asys_fsync, profile_p, > state->ur.profile_bytes, 0); >@@ -496,6 +532,17 @@ static struct tevent_req *vfs_io_uring_fsync_send(struct vfs_handle_struct *hand > return req; > } > >+static void vfs_io_uring_fsync_completion(struct vfs_io_uring_request *cur, >+ const char *location) >+{ >+ /* >+ * We rely on being inside the _send() function >+ * or tevent_req_defer_callback() being called >+ * already. >+ */ >+ _tevent_req_done(cur->req, location); >+} >+ > static int vfs_io_uring_fsync_recv(struct tevent_req *req, > struct vfs_aio_state *vfs_aio_state) > { >-- >2.17.1 > > >From 990193425321d033dfd4c8e1f408d38b3b5b7e5d Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 10:52:52 +0200 >Subject: [PATCH 18/31] vfs_io_uring: move error handling out of > vfs_io_uring_pread_recv() > >We should do that as early as possible and that's in >vfs_io_uring_pread_completion(). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 26 +++++++++++++++++--------- > 1 file changed, 17 insertions(+), 9 deletions(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index abdd4d16e9f8..0d8e18330092 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -297,6 +297,7 @@ static void vfs_io_uring_fd_handler(struct tevent_context *ev, > struct vfs_io_uring_pread_state { > struct vfs_io_uring_request ur; > struct iovec iov; >+ size_t nread; > }; > > static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur, >@@ -353,12 +354,23 @@ static struct tevent_req *vfs_io_uring_pread_send(struct vfs_handle_struct *hand > static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur, > const char *location) > { >+ struct vfs_io_uring_pread_state *state = tevent_req_data( >+ cur->req, struct vfs_io_uring_pread_state); >+ > /* > * We rely on being inside the _send() function > * or tevent_req_defer_callback() being called > * already. > */ >- _tevent_req_done(cur->req, location); >+ >+ if (cur->cqe.res < 0) { >+ int err = -cur->cqe.res; >+ _tevent_req_error(cur->req, err, location); >+ return; >+ } >+ >+ state->nread = state->ur.cqe.res; >+ tevent_req_done(cur->req); > } > > static ssize_t vfs_io_uring_pread_recv(struct tevent_req *req, >@@ -366,23 +378,19 @@ static ssize_t vfs_io_uring_pread_recv(struct tevent_req *req, > { > struct vfs_io_uring_pread_state *state = tevent_req_data( > req, struct vfs_io_uring_pread_state); >- int ret; >+ ssize_t ret; > > SMBPROFILE_BYTES_ASYNC_END(state->ur.profile_bytes); > vfs_aio_state->duration = nsec_time_diff(&state->ur.end_time, > &state->ur.start_time); > > if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { >+ tevent_req_received(req); > return -1; > } > >- if (state->ur.cqe.res < 0) { >- vfs_aio_state->error = -state->ur.cqe.res; >- ret = -1; >- } else { >- vfs_aio_state->error = 0; >- ret = state->ur.cqe.res; >- } >+ vfs_aio_state->error = 0; >+ ret = state->nread; > > tevent_req_received(req); > return ret; >-- >2.17.1 > > >From 249fb7d8487e00376ac8f2486d1293954941c584 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 10:52:52 +0200 >Subject: [PATCH 19/31] vfs_io_uring: move error handling out of > vfs_io_uring_pwrite_recv() > >We should do that as early as possible and that's in >vfs_io_uring_pwrite_completion(). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 26 +++++++++++++++++--------- > 1 file changed, 17 insertions(+), 9 deletions(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index 0d8e18330092..a8da341e7b7c 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -399,6 +399,7 @@ static ssize_t vfs_io_uring_pread_recv(struct tevent_req *req, > struct vfs_io_uring_pwrite_state { > struct vfs_io_uring_request ur; > struct iovec iov; >+ size_t nwritten; > }; > > static void vfs_io_uring_pwrite_completion(struct vfs_io_uring_request *cur, >@@ -455,12 +456,23 @@ static struct tevent_req *vfs_io_uring_pwrite_send(struct vfs_handle_struct *han > static void vfs_io_uring_pwrite_completion(struct vfs_io_uring_request *cur, > const char *location) > { >+ struct vfs_io_uring_pwrite_state *state = tevent_req_data( >+ cur->req, struct vfs_io_uring_pwrite_state); >+ > /* > * We rely on being inside the _send() function > * or tevent_req_defer_callback() being called > * already. > */ >- _tevent_req_done(cur->req, location); >+ >+ if (cur->cqe.res < 0) { >+ int err = -cur->cqe.res; >+ _tevent_req_error(cur->req, err, location); >+ return; >+ } >+ >+ state->nwritten = state->ur.cqe.res; >+ tevent_req_done(cur->req); > } > > static ssize_t vfs_io_uring_pwrite_recv(struct tevent_req *req, >@@ -468,23 +480,19 @@ static ssize_t vfs_io_uring_pwrite_recv(struct tevent_req *req, > { > struct vfs_io_uring_pwrite_state *state = tevent_req_data( > req, struct vfs_io_uring_pwrite_state); >- int ret; >+ ssize_t ret; > > SMBPROFILE_BYTES_ASYNC_END(state->ur.profile_bytes); > vfs_aio_state->duration = nsec_time_diff(&state->ur.end_time, > &state->ur.start_time); > > if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { >+ tevent_req_received(req); > return -1; > } > >- if (state->ur.cqe.res < 0) { >- vfs_aio_state->error = -state->ur.cqe.res; >- ret = -1; >- } else { >- vfs_aio_state->error = 0; >- ret = state->ur.cqe.res; >- } >+ vfs_aio_state->error = 0; >+ ret = state->nwritten; > > tevent_req_received(req); > return ret; >-- >2.17.1 > > >From 9a6ff1dd9bd137a20e0310702adde8ffee99e57a Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 10:52:52 +0200 >Subject: [PATCH 20/31] vfs_io_uring: move error handling out of > vfs_io_uring_fsync_recv() > >We should do that as early as possible and that's in >vfs_io_uring_fsync_completion(). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 21 +++++++++++---------- > 1 file changed, 11 insertions(+), 10 deletions(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index a8da341e7b7c..0f560c95b67d 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -556,7 +556,14 @@ static void vfs_io_uring_fsync_completion(struct vfs_io_uring_request *cur, > * or tevent_req_defer_callback() being called > * already. > */ >- _tevent_req_done(cur->req, location); >+ >+ if (cur->cqe.res < 0) { >+ int err = -cur->cqe.res; >+ _tevent_req_error(cur->req, err, location); >+ return; >+ } >+ >+ tevent_req_done(cur->req); > } > > static int vfs_io_uring_fsync_recv(struct tevent_req *req, >@@ -564,26 +571,20 @@ static int vfs_io_uring_fsync_recv(struct tevent_req *req, > { > struct vfs_io_uring_fsync_state *state = tevent_req_data( > req, struct vfs_io_uring_fsync_state); >- int ret; > > SMBPROFILE_BYTES_ASYNC_END(state->ur.profile_bytes); > vfs_aio_state->duration = nsec_time_diff(&state->ur.end_time, > &state->ur.start_time); > > if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) { >+ tevent_req_received(req); > return -1; > } > >- if (state->ur.cqe.res < 0) { >- vfs_aio_state->error = -state->ur.cqe.res; >- ret = -1; >- } else { >- vfs_aio_state->error = 0; >- ret = state->ur.cqe.res; >- } >+ vfs_aio_state->error = 0; > > tevent_req_received(req); >- return ret; >+ return 0; > } > > static struct vfs_fn_pointers vfs_io_uring_fns = { >-- >2.17.1 > > >From d62457404f6358629f24db76d647674709974872 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 13:17:05 +0200 >Subject: [PATCH 21/31] vfs_io_uring: make use of sys_valid_io_range() in > vfs_io_uring_pread_send() > >This makes the follow up commits easier as we don't have to care >about overflows. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index 0f560c95b67d..c7565b8c39de 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -25,6 +25,7 @@ > #include "smbd/smbd.h" > #include "smbd/globals.h" > #include "lib/util/tevent_unix.h" >+#include "lib/util/sys_rw.h" > #include "smbprofile.h" > #include <liburing.h> > >@@ -313,6 +314,7 @@ static struct tevent_req *vfs_io_uring_pread_send(struct vfs_handle_struct *hand > struct tevent_req *req = NULL; > struct vfs_io_uring_pread_state *state = NULL; > struct vfs_io_uring_config *config = NULL; >+ bool ok; > > SMB_VFS_HANDLE_GET_DATA(handle, config, > struct vfs_io_uring_config, >@@ -331,6 +333,12 @@ static struct tevent_req *vfs_io_uring_pread_send(struct vfs_handle_struct *hand > state->ur.profile_bytes, n); > SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->ur.profile_bytes); > >+ ok = sys_valid_io_range(offset, n); >+ if (!ok) { >+ tevent_req_error(req, EINVAL); >+ return tevent_req_post(req, ev); >+ } >+ > state->iov.iov_base = (void *)data; > state->iov.iov_len = n; > io_uring_prep_readv(&state->ur.sqe, >-- >2.17.1 > > >From bb20b2e9db88eeef3d9080e6dba39ff969364ff0 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 13:17:05 +0200 >Subject: [PATCH 22/31] vfs_io_uring: make use of sys_valid_io_range() in > vfs_io_uring_pwrite_send() > >This makes the follow up commits easier as we don't have to care >about overflows. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 7 +++++++ > 1 file changed, 7 insertions(+) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index c7565b8c39de..ee23449c63c6 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -423,6 +423,7 @@ static struct tevent_req *vfs_io_uring_pwrite_send(struct vfs_handle_struct *han > struct tevent_req *req = NULL; > struct vfs_io_uring_pwrite_state *state = NULL; > struct vfs_io_uring_config *config = NULL; >+ bool ok; > > SMB_VFS_HANDLE_GET_DATA(handle, config, > struct vfs_io_uring_config, >@@ -441,6 +442,12 @@ static struct tevent_req *vfs_io_uring_pwrite_send(struct vfs_handle_struct *han > state->ur.profile_bytes, n); > SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->ur.profile_bytes); > >+ ok = sys_valid_io_range(offset, n); >+ if (!ok) { >+ tevent_req_error(req, EINVAL); >+ return tevent_req_post(req, ev); >+ } >+ > state->iov.iov_base = discard_const(data); > state->iov.iov_len = n; > io_uring_prep_writev(&state->ur.sqe, >-- >2.17.1 > > >From 515e38a802bb273319701759de502a247df4c497 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 21:29:53 +0200 >Subject: [PATCH 23/31] vfs_io_uring: avoid stack recursion of > vfs_io_uring_queue_run() > >Instead we remember if recursion was triggered and jump to >the start of the function again from the end. > >This should make it safe to be called from the completion_fn(). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 20 +++++++++++++++++++- > 1 file changed, 19 insertions(+), 1 deletion(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index ee23449c63c6..df41c74a7953 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -34,6 +34,8 @@ struct vfs_io_uring_request; > struct vfs_io_uring_config { > struct io_uring uring; > struct tevent_fd *fde; >+ bool busy; >+ bool need_retry; > struct vfs_io_uring_request *queue; > struct vfs_io_uring_request *pending; > }; >@@ -222,7 +224,7 @@ static int vfs_io_uring_connect(vfs_handle_struct *handle, const char *service, > return 0; > } > >-static void vfs_io_uring_queue_run(struct vfs_io_uring_config *config) >+static void _vfs_io_uring_queue_run(struct vfs_io_uring_config *config) > { > struct vfs_io_uring_request *cur = NULL, *next = NULL; > struct io_uring_cqe *cqe = NULL; >@@ -280,6 +282,22 @@ static void vfs_io_uring_queue_run(struct vfs_io_uring_config *config) > io_uring_cq_advance(&config->uring, nr); > } > >+static void vfs_io_uring_queue_run(struct vfs_io_uring_config *config) >+{ >+ if (config->busy) { >+ config->need_retry = true; >+ return; >+ } >+ config->busy = true; >+ >+ do { >+ config->need_retry = false; >+ _vfs_io_uring_queue_run(config); >+ } while (config->need_retry); >+ >+ config->busy = false; >+} >+ > static void vfs_io_uring_fd_handler(struct tevent_context *ev, > struct tevent_fd *fde, > uint16_t flags, >-- >2.17.1 > > >From 91f3176f4221afe9972fcf6a7039d721abdb50eb Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 11:17:51 +0200 >Subject: [PATCH 24/31] vfs_io_uring: split out a vfs_io_uring_request_submit() > function > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 29 ++++++++++++++--------------- > 1 file changed, 14 insertions(+), 15 deletions(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index df41c74a7953..7db32760d976 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -298,6 +298,17 @@ static void vfs_io_uring_queue_run(struct vfs_io_uring_config *config) > config->busy = false; > } > >+static void vfs_io_uring_request_submit(struct vfs_io_uring_request *cur) >+{ >+ struct vfs_io_uring_config *config = cur->config; >+ >+ io_uring_sqe_set_data(&cur->sqe, cur); >+ DLIST_ADD_END(config->queue, cur); >+ cur->list_head = &config->queue; >+ >+ vfs_io_uring_queue_run(config); >+} >+ > static void vfs_io_uring_fd_handler(struct tevent_context *ev, > struct tevent_fd *fde, > uint16_t flags, >@@ -363,11 +374,7 @@ static struct tevent_req *vfs_io_uring_pread_send(struct vfs_handle_struct *hand > fsp->fh->fd, > &state->iov, 1, > offset); >- io_uring_sqe_set_data(&state->ur.sqe, &state->ur); >- DLIST_ADD_END(config->queue, &state->ur); >- state->ur.list_head = &config->queue; >- >- vfs_io_uring_queue_run(config); >+ vfs_io_uring_request_submit(&state->ur); > > if (!tevent_req_is_in_progress(req)) { > return tevent_req_post(req, ev); >@@ -472,11 +479,7 @@ static struct tevent_req *vfs_io_uring_pwrite_send(struct vfs_handle_struct *han > fsp->fh->fd, > &state->iov, 1, > offset); >- io_uring_sqe_set_data(&state->ur.sqe, &state->ur); >- DLIST_ADD_END(config->queue, &state->ur); >- state->ur.list_head = &config->queue; >- >- vfs_io_uring_queue_run(config); >+ vfs_io_uring_request_submit(&state->ur); > > if (!tevent_req_is_in_progress(req)) { > return tevent_req_post(req, ev); >@@ -567,11 +570,7 @@ static struct tevent_req *vfs_io_uring_fsync_send(struct vfs_handle_struct *hand > io_uring_prep_fsync(&state->ur.sqe, > fsp->fh->fd, > 0); /* fsync_flags */ >- io_uring_sqe_set_data(&state->ur.sqe, &state->ur); >- DLIST_ADD_END(config->queue, &state->ur); >- state->ur.list_head = &config->queue; >- >- vfs_io_uring_queue_run(config); >+ vfs_io_uring_request_submit(&state->ur); > > if (!tevent_req_is_in_progress(req)) { > return tevent_req_post(req, ev); >-- >2.17.1 > > >From 7f1ae17de0426421145e90c9b4e7ac9050e5b8ce Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 11:17:51 +0200 >Subject: [PATCH 25/31] vfs_io_uring: split out a vfs_io_uring_pread_submit() > function > >This can be reused when we add handling for short reads. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 20 +++++++++++++++----- > 1 file changed, 15 insertions(+), 5 deletions(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index 7db32760d976..1f724fbc588e 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -326,10 +326,13 @@ static void vfs_io_uring_fd_handler(struct tevent_context *ev, > > struct vfs_io_uring_pread_state { > struct vfs_io_uring_request ur; >+ struct files_struct *fsp; >+ off_t offset; > struct iovec iov; > size_t nread; > }; > >+static void vfs_io_uring_pread_submit(struct vfs_io_uring_pread_state *state); > static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur, > const char *location); > >@@ -368,13 +371,11 @@ static struct tevent_req *vfs_io_uring_pread_send(struct vfs_handle_struct *hand > return tevent_req_post(req, ev); > } > >+ state->fsp = fsp; >+ state->offset = offset; > state->iov.iov_base = (void *)data; > state->iov.iov_len = n; >- io_uring_prep_readv(&state->ur.sqe, >- fsp->fh->fd, >- &state->iov, 1, >- offset); >- vfs_io_uring_request_submit(&state->ur); >+ vfs_io_uring_pread_submit(state); > > if (!tevent_req_is_in_progress(req)) { > return tevent_req_post(req, ev); >@@ -384,6 +385,15 @@ static struct tevent_req *vfs_io_uring_pread_send(struct vfs_handle_struct *hand > return req; > } > >+static void vfs_io_uring_pread_submit(struct vfs_io_uring_pread_state *state) >+{ >+ io_uring_prep_readv(&state->ur.sqe, >+ state->fsp->fh->fd, >+ &state->iov, 1, >+ state->offset); >+ vfs_io_uring_request_submit(&state->ur); >+} >+ > static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur, > const char *location) > { >-- >2.17.1 > > >From 563b53a5f69fb6a74f1422e68ef944675d181ff9 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 11:17:51 +0200 >Subject: [PATCH 26/31] vfs_io_uring: split out a vfs_io_uring_pwrite_submit() > function > >This can be reused when we add handling for short writes. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 20 +++++++++++++++----- > 1 file changed, 15 insertions(+), 5 deletions(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index 1f724fbc588e..416681333634 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -441,10 +441,13 @@ static ssize_t vfs_io_uring_pread_recv(struct tevent_req *req, > > struct vfs_io_uring_pwrite_state { > struct vfs_io_uring_request ur; >+ struct files_struct *fsp; >+ off_t offset; > struct iovec iov; > size_t nwritten; > }; > >+static void vfs_io_uring_pwrite_submit(struct vfs_io_uring_pwrite_state *state); > static void vfs_io_uring_pwrite_completion(struct vfs_io_uring_request *cur, > const char *location); > >@@ -483,13 +486,11 @@ static struct tevent_req *vfs_io_uring_pwrite_send(struct vfs_handle_struct *han > return tevent_req_post(req, ev); > } > >+ state->fsp = fsp; >+ state->offset = offset; > state->iov.iov_base = discard_const(data); > state->iov.iov_len = n; >- io_uring_prep_writev(&state->ur.sqe, >- fsp->fh->fd, >- &state->iov, 1, >- offset); >- vfs_io_uring_request_submit(&state->ur); >+ vfs_io_uring_pwrite_submit(state); > > if (!tevent_req_is_in_progress(req)) { > return tevent_req_post(req, ev); >@@ -499,6 +500,15 @@ static struct tevent_req *vfs_io_uring_pwrite_send(struct vfs_handle_struct *han > return req; > } > >+static void vfs_io_uring_pwrite_submit(struct vfs_io_uring_pwrite_state *state) >+{ >+ io_uring_prep_writev(&state->ur.sqe, >+ state->fsp->fh->fd, >+ &state->iov, 1, >+ state->offset); >+ vfs_io_uring_request_submit(&state->ur); >+} >+ > static void vfs_io_uring_pwrite_completion(struct vfs_io_uring_request *cur, > const char *location) > { >-- >2.17.1 > > >From a160e544906edba617152c8a4807cb751fc06924 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 11:38:56 +0200 >Subject: [PATCH 27/31] vfs_io_uring: protect vfs_io_uring_pread_completion() > against invalid results > >We should never get back more than we asked for. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 14 ++++++++++++++ > 1 file changed, 14 insertions(+) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index 416681333634..a9b2db8d3cd3 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -26,6 +26,7 @@ > #include "smbd/globals.h" > #include "lib/util/tevent_unix.h" > #include "lib/util/sys_rw.h" >+#include "lib/util/iov_buf.h" > #include "smbprofile.h" > #include <liburing.h> > >@@ -399,6 +400,9 @@ static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur, > { > struct vfs_io_uring_pread_state *state = tevent_req_data( > cur->req, struct vfs_io_uring_pread_state); >+ struct iovec *iov = &state->iov; >+ int num_iov = 1; >+ bool ok; > > /* > * We rely on being inside the _send() function >@@ -412,6 +416,16 @@ static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur, > return; > } > >+ ok = iov_advance(&iov, &num_iov, cur->cqe.res); >+ if (!ok) { >+ /* This is not expected! */ >+ DBG_ERR("iov_advance() failed cur->cqe.res=%d > iov_len=%d\n", >+ (int)cur->cqe.res, >+ (int)state->iov.iov_len); >+ tevent_req_error(cur->req, EIO); >+ return; >+ } >+ > state->nread = state->ur.cqe.res; > tevent_req_done(cur->req); > } >-- >2.17.1 > > >From c7cb3ead876777bd4a13f28760e9fa1e5b6f6303 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 11:38:56 +0200 >Subject: [PATCH 28/31] vfs_io_uring: protect vfs_io_uring_pwrite_completion() > against invalid results > >We should never get more acked than we asked for. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 13 +++++++++++++ > 1 file changed, 13 insertions(+) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index a9b2db8d3cd3..7994ef17d675 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -528,6 +528,9 @@ static void vfs_io_uring_pwrite_completion(struct vfs_io_uring_request *cur, > { > struct vfs_io_uring_pwrite_state *state = tevent_req_data( > cur->req, struct vfs_io_uring_pwrite_state); >+ struct iovec *iov = &state->iov; >+ int num_iov = 1; >+ bool ok; > > /* > * We rely on being inside the _send() function >@@ -541,6 +544,16 @@ static void vfs_io_uring_pwrite_completion(struct vfs_io_uring_request *cur, > return; > } > >+ ok = iov_advance(&iov, &num_iov, cur->cqe.res); >+ if (!ok) { >+ /* This is not expected! */ >+ DBG_ERR("iov_advance() failed cur->cqe.res=%d > iov_len=%d\n", >+ (int)cur->cqe.res, >+ (int)state->iov.iov_len); >+ tevent_req_error(cur->req, EIO); >+ return; >+ } >+ > state->nwritten = state->ur.cqe.res; > tevent_req_done(cur->req); > } >-- >2.17.1 > > >From 88c6311070f574949f55a6e0c1d08706d45a50c6 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 11:38:56 +0200 >Subject: [PATCH 29/31] vfs_io_uring: protect vfs_io_uring_fsync_completion() > against invalid results > >We should never get back a value > 0. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 7 +++++++ > 1 file changed, 7 insertions(+) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index 7994ef17d675..2b5706665cf3 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -642,6 +642,13 @@ static void vfs_io_uring_fsync_completion(struct vfs_io_uring_request *cur, > return; > } > >+ if (cur->cqe.res > 0) { >+ /* This is not expected! */ >+ DBG_ERR("got cur->cqe.res=%d\n", (int)cur->cqe.res); >+ tevent_req_error(cur->req, EIO); >+ return; >+ } >+ > tevent_req_done(cur->req); > } > >-- >2.17.1 > > >From 78a22024ede0764baebe0a136f2f59c5959a7266 Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 13:30:17 +0200 >Subject: [PATCH 30/31] vfs_io_uring: retry after a short read in > vfs_io_uring_pread_completion() > >We need to be prepared for short reads from the kernel depending on >the state of the page cache. Windows and Mac clients don't >expect short reads for files, so we need to retry ourself. > >For the future we may be able to play with some io_uring flags >in order to avoid the retries in userspace, but for now we just fix >the data corruption bug... > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 24 ++++++++++++++++++++++-- > 1 file changed, 22 insertions(+), 2 deletions(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index 2b5706665cf3..965f8798ff2a 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -416,6 +416,14 @@ static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur, > return; > } > >+ if (cur->cqe.res == 0) { >+ /* >+ * We reached EOF, we're done >+ */ >+ tevent_req_done(cur->req); >+ return; >+ } >+ > ok = iov_advance(&iov, &num_iov, cur->cqe.res); > if (!ok) { > /* This is not expected! */ >@@ -426,8 +434,20 @@ static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur, > return; > } > >- state->nread = state->ur.cqe.res; >- tevent_req_done(cur->req); >+ /* sys_valid_io_range() already checked the boundaries */ >+ state->nread += state->ur.cqe.res; >+ if (num_iov == 0) { >+ /* We're done */ >+ tevent_req_done(cur->req); >+ return; >+ } >+ >+ /* >+ * sys_valid_io_range() already checked the boundaries >+ * now try to get the rest. >+ */ >+ state->offset += state->ur.cqe.res; >+ vfs_io_uring_pread_submit(state); > } > > static ssize_t vfs_io_uring_pread_recv(struct tevent_req *req, >-- >2.17.1 > > >From ef782387a974f904fa1ca8181b5e07ec9e34a51a Mon Sep 17 00:00:00 2001 >From: Stefan Metzmacher <metze@samba.org> >Date: Fri, 8 May 2020 13:30:17 +0200 >Subject: [PATCH 31/31] vfs_io_uring: retry after a short writes in > vfs_io_uring_pwrite_completion() > >We need to be prepared for short writes from the kernel depending on >the state of the page cache. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361 > >Signed-off-by: Stefan Metzmacher <metze@samba.org> >--- > source3/modules/vfs_io_uring.c | 24 ++++++++++++++++++++++-- > 1 file changed, 22 insertions(+), 2 deletions(-) > >diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c >index 965f8798ff2a..19ffbde8e40a 100644 >--- a/source3/modules/vfs_io_uring.c >+++ b/source3/modules/vfs_io_uring.c >@@ -564,6 +564,14 @@ static void vfs_io_uring_pwrite_completion(struct vfs_io_uring_request *cur, > return; > } > >+ if (cur->cqe.res == 0) { >+ /* >+ * Ensure we can never spin. >+ */ >+ tevent_req_error(cur->req, ENOSPC); >+ return; >+ } >+ > ok = iov_advance(&iov, &num_iov, cur->cqe.res); > if (!ok) { > /* This is not expected! */ >@@ -574,8 +582,20 @@ static void vfs_io_uring_pwrite_completion(struct vfs_io_uring_request *cur, > return; > } > >- state->nwritten = state->ur.cqe.res; >- tevent_req_done(cur->req); >+ /* sys_valid_io_range() already checked the boundaries */ >+ state->nwritten += state->ur.cqe.res; >+ if (num_iov == 0) { >+ /* We're done */ >+ tevent_req_done(cur->req); >+ return; >+ } >+ >+ /* >+ * sys_valid_io_range() already checked the boundaries >+ * now try to write the rest. >+ */ >+ state->offset += state->ur.cqe.res; >+ vfs_io_uring_pwrite_submit(state); > } > > static ssize_t vfs_io_uring_pwrite_recv(struct tevent_req *req, >-- >2.17.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
jra
:
review-
Actions:
View
Attachments on
bug 14361
:
15947
|
15955
|
15960
|
15961
|
15962
|
15964
|
15965
|
15969
|
15971
|
15976