The Samba-Bugzilla – Attachment 15367 Details for
Bug 14060
smbd fails to open kernel-oplocked files with smb1
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 4.11
14060-4.11.patch (text/plain), 15.05 KB, created by
Volker Lendecke
on 2019-08-02 08:07:35 UTC
(
hide
)
Description:
Patch for 4.11
Filename:
MIME Type:
Creator:
Volker Lendecke
Created:
2019-08-02 08:07:35 UTC
Size:
15.05 KB
patch
obsolete
>From 5f317f5d229c135437981882e8d5851299df191c Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Mon, 29 Jul 2019 17:14:00 +0200 >Subject: [PATCH 1/4] torture3: Add oplock5 kernel-oplock test > >Show that the current smb1 server does not properly retry a nonblocking >open of a kernel-oplocked file > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=14060 >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 57695ad44bf10d6ae1dc466551358bd826dac923) >--- > selftest/knownfail | 1 + > source3/selftest/tests.py | 13 +++ > source3/torture/torture.c | 273 ++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 287 insertions(+) > >diff --git a/selftest/knownfail b/selftest/knownfail >index ded80b12259..99772b45c4d 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -15,6 +15,7 @@ > ^samba3.smbtorture_s3.crypt_server # expected to give ACCESS_DENIED as SMB1 encryption isn't used > ^samba3.smbtorture_s3.*.LOCK12.*\(fileserver\) > ^samba3.smbtorture_s3.*.LOCK12.*\(nt4_dc\) >+^samba3.smbtorture_s3.*.OPLOCK5.*\(fileserver\) > ^samba3.nbt.dgram.*netlogon2\(nt4_dc\) > ^samba3.*rap.sam.*.useradd # Not provided by Samba 3 > ^samba3.*rap.sam.*.userdelete # Not provided by Samba 3 >diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py >index 78f58bdb30c..532b878d6fb 100755 >--- a/source3/selftest/tests.py >+++ b/source3/selftest/tests.py >@@ -113,6 +113,19 @@ for t in tests: > t = "TLDAP" > plantestsuite("samba3.smbtorture_s3.plain.%s" % t, "ad_dc", [os.path.join(samba3srcdir, "script/tests/test_smbtorture_s3.sh"), t, '//$SERVER/tmp', '$DC_USERNAME', '$DC_PASSWORD', smbtorture3, "", "-l $LOCAL_PATH"]) > >+t = "OPLOCK5" >+plantestsuite("samba3.smbtorture_s3.plain.%s" % t, >+ "fileserver", >+ [os.path.join(samba3srcdir, >+ "script/tests/test_smbtorture_s3.sh"), >+ t, >+ '//$SERVER/tmp', >+ '$USERNAME', >+ '$PASSWORD', >+ smbtorture3, >+ "", >+ "-l $LOCAL_PATH", >+ "-mNT1"]) > # > # RENAME-ACCESS needs to run against a special share - acl_xattr_ign_sysacl_windows > # >diff --git a/source3/torture/torture.c b/source3/torture/torture.c >index 2cb32efea46..17020328eaf 100644 >--- a/source3/torture/torture.c >+++ b/source3/torture/torture.c >@@ -45,6 +45,7 @@ > #include "lib/util/base64.h" > #include "lib/util/time.h" > #include "lib/gencache.h" >+#include "lib/util/sys_rw.h" > > #include <gnutls/gnutls.h> > #include <gnutls/crypto.h> >@@ -4801,6 +4802,274 @@ static void oplock4_got_open(struct tevent_req *req) > } > } > >+#ifdef HAVE_KERNEL_OPLOCKS_LINUX >+ >+struct oplock5_state { >+ int pipe_down_fd; >+}; >+ >+/* >+ * Async open the file that has a kernel oplock, do an echo to get >+ * that 100% across, close the file to signal to the child fd that the >+ * oplock can be dropped, wait for the open reply. >+ */ >+ >+static void oplock5_opened(struct tevent_req *subreq); >+static void oplock5_pong(struct tevent_req *subreq); >+static void oplock5_timedout(struct tevent_req *subreq); >+ >+static struct tevent_req *oplock5_send( >+ TALLOC_CTX *mem_ctx, >+ struct tevent_context *ev, >+ struct cli_state *cli, >+ const char *fname, >+ int pipe_down_fd) >+{ >+ struct tevent_req *req = NULL, *subreq = NULL; >+ struct oplock5_state *state = NULL; >+ static uint8_t data = 0; >+ >+ req = tevent_req_create(mem_ctx, &state, struct oplock5_state); >+ if (req == NULL) { >+ return NULL; >+ } >+ state->pipe_down_fd = pipe_down_fd; >+ >+ subreq = cli_ntcreate_send( >+ state, >+ ev, >+ cli, >+ fname, >+ 0, /* CreatFlags */ >+ SEC_FILE_READ_DATA, /* DesiredAccess */ >+ FILE_ATTRIBUTE_NORMAL, /* FileAttributes */ >+ FILE_SHARE_WRITE|FILE_SHARE_READ, /* ShareAccess */ >+ FILE_OPEN, /* CreateDisposition */ >+ FILE_NON_DIRECTORY_FILE, /* CreateOptions */ >+ 0, /* Impersonation */ >+ 0); /* SecurityFlags */ >+ if (tevent_req_nomem(subreq, req)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, oplock5_opened, req); >+ >+ subreq = cli_echo_send( >+ state, >+ ev, >+ cli, >+ 1, >+ (DATA_BLOB) { .data = &data, .length = sizeof(data) }); >+ if (tevent_req_nomem(subreq, req)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, oplock5_pong, req); >+ >+ subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(20, 0)); >+ if (tevent_req_nomem(subreq, req)) { >+ return tevent_req_post(req, ev); >+ } >+ tevent_req_set_callback(subreq, oplock5_timedout, req); >+ >+ return req; >+} >+ >+static void oplock5_opened(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ NTSTATUS status; >+ uint16_t fnum; >+ >+ status = cli_ntcreate_recv(subreq, &fnum, NULL); >+ TALLOC_FREE(subreq); >+ if (tevent_req_nterror(req, status)) { >+ return; >+ } >+ tevent_req_done(req); >+} >+ >+static void oplock5_pong(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ struct oplock5_state *state = tevent_req_data( >+ req, struct oplock5_state); >+ NTSTATUS status; >+ >+ status = cli_echo_recv(subreq); >+ TALLOC_FREE(subreq); >+ if (tevent_req_nterror(req, status)) { >+ return; >+ } >+ >+ close(state->pipe_down_fd); >+} >+ >+static void oplock5_timedout(struct tevent_req *subreq) >+{ >+ struct tevent_req *req = tevent_req_callback_data( >+ subreq, struct tevent_req); >+ bool ok; >+ >+ ok = tevent_wakeup_recv(subreq); >+ TALLOC_FREE(subreq); >+ if (!ok) { >+ tevent_req_oom(req); >+ return; >+ } >+ tevent_req_nterror(req, NT_STATUS_TIMEOUT); >+} >+ >+static NTSTATUS oplock5_recv(struct tevent_req *req) >+{ >+ return tevent_req_simple_recv_ntstatus(req); >+} >+ >+static bool run_oplock5(int dummy) >+{ >+ struct tevent_context *ev = NULL; >+ struct tevent_req *req = NULL; >+ struct cli_state *cli = NULL; >+ const char *fname = "oplock5.txt"; >+ int pipe_down[2], pipe_up[2]; >+ pid_t child_pid; >+ uint8_t c = '\0'; >+ NTSTATUS status; >+ int ret; >+ bool ok; >+ >+ printf("starting oplock5\n"); >+ >+ if (local_path == NULL) { >+ d_fprintf(stderr, "oplock5 must be given a local path via " >+ "-l <localpath>\n"); >+ return false; >+ } >+ >+ ret = pipe(pipe_down); >+ if (ret == -1) { >+ d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno)); >+ return false; >+ } >+ ret = pipe(pipe_up); >+ if (ret == -1) { >+ d_fprintf(stderr, "pipe() failed: %s\n", strerror(errno)); >+ return false; >+ } >+ >+ child_pid = fork(); >+ if (child_pid == -1) { >+ d_fprintf(stderr, "fork() failed: %s\n", strerror(errno)); >+ return false; >+ } >+ >+ if (child_pid == 0) { >+ char *local_file = NULL; >+ int fd; >+ >+ close(pipe_down[1]); >+ close(pipe_up[0]); >+ >+ local_file = talloc_asprintf( >+ talloc_tos(), "%s/%s", local_path, fname); >+ if (local_file == 0) { >+ c = 1; >+ goto do_write; >+ } >+ fd = open(local_file, O_RDWR|O_CREAT, 0644); >+ if (fd == -1) { >+ d_fprintf(stderr, >+ "open(%s) in child failed: %s\n", >+ local_file, >+ strerror(errno)); >+ c = 2; >+ goto do_write; >+ } >+ >+ signal(SIGIO, SIG_IGN); >+ >+ ret = fcntl(fd, F_SETLEASE, F_WRLCK); >+ if (ret == -1) { >+ d_fprintf(stderr, >+ "SETLEASE in child failed: %s\n", >+ strerror(errno)); >+ c = 3; >+ goto do_write; >+ } >+ >+ do_write: >+ ret = sys_write(pipe_up[1], &c, sizeof(c)); >+ if (ret == -1) { >+ d_fprintf(stderr, >+ "sys_write failed: %s\n", >+ strerror(errno)); >+ exit(4); >+ } >+ ret = sys_read(pipe_down[0], &c, sizeof(c)); >+ if (ret == -1) { >+ d_fprintf(stderr, >+ "sys_read failed: %s\n", >+ strerror(errno)); >+ exit(5); >+ } >+ exit(0); >+ } >+ >+ close(pipe_up[1]); >+ close(pipe_down[0]); >+ >+ ret = sys_read(pipe_up[0], &c, sizeof(c)); >+ if (ret != 1) { >+ d_fprintf(stderr, >+ "sys_read failed: %s\n", >+ strerror(errno)); >+ return false; >+ } >+ if (c != 0) { >+ d_fprintf(stderr, "got error code %"PRIu8"\n", c); >+ return false; >+ } >+ >+ ok = torture_open_connection(&cli, 0); >+ if (!ok) { >+ d_fprintf(stderr, "torture_open_connection failed\n"); >+ return false; >+ } >+ >+ ev = samba_tevent_context_init(talloc_tos()); >+ if (ev == NULL) { >+ d_fprintf(stderr, "samba_tevent_context_init failed\n"); >+ return false; >+ } >+ >+ req = oplock5_send(ev, ev, cli, fname, pipe_down[1]); >+ if (req == NULL) { >+ d_fprintf(stderr, "oplock5_send failed\n"); >+ return false; >+ } >+ >+ ok = tevent_req_poll_ntstatus(req, ev, &status); >+ if (!ok) { >+ d_fprintf(stderr, >+ "tevent_req_poll_ntstatus failed: %s\n", >+ nt_errstr(status)); >+ return false; >+ } >+ >+ status = oplock5_recv(req); >+ TALLOC_FREE(req); >+ if (!NT_STATUS_IS_OK(status)) { >+ d_fprintf(stderr, >+ "oplock5 failed: %s\n", >+ nt_errstr(status)); >+ return false; >+ } >+ >+ return true; >+} >+ >+#endif /* HAVE_KERNEL_OPLOCKS_LINUX */ >+ > /* > Test delete on close semantics. > */ >@@ -13547,6 +13816,10 @@ static struct { > .fn = run_oplock4, > }, > { >+ .name = "OPLOCK5", >+ .fn = run_oplock5, >+ }, >+ { > .name = "DIR", > .fn = run_dirtest, > }, >-- >2.11.0 > > >From dd93357ec77a4f224b733113c6664904c7bfbddc Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Mon, 29 Jul 2019 20:45:51 +0200 >Subject: [PATCH 2/4] smbd: Always open files with O_NONBLOCK > >It's perfectly possible that someone else takes a kernel oplock and >makes us block, independent of our own kernel oplock setting. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=14060 >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit ef582ffcf3a220b73f678d9bce0fd37800f76c54) >--- > source3/smbd/open.c | 28 +++++++++++++--------------- > 1 file changed, 13 insertions(+), 15 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index 2ee4a2c4fca..6838354a7d4 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -3214,21 +3214,19 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > flags2 &= ~(O_CREAT|O_TRUNC); > } > >- if (lp_kernel_oplocks(SNUM(conn))) { >- /* >- * With kernel oplocks the open breaking an oplock >- * blocks until the oplock holder has given up the >- * oplock or closed the file. We prevent this by always >- * trying to open the file with O_NONBLOCK (see "man >- * fcntl" on Linux). >- * >- * If a process that doesn't use the smbd open files >- * database or communication methods holds a kernel >- * oplock we must periodically poll for available open >- * using O_NONBLOCK. >- */ >- flags2 |= O_NONBLOCK; >- } >+ /* >+ * With kernel oplocks the open breaking an oplock >+ * blocks until the oplock holder has given up the >+ * oplock or closed the file. We prevent this by always >+ * trying to open the file with O_NONBLOCK (see "man >+ * fcntl" on Linux). >+ * >+ * If a process that doesn't use the smbd open files >+ * database or communication methods holds a kernel >+ * oplock we must periodically poll for available open >+ * using O_NONBLOCK. >+ */ >+ flags2 |= O_NONBLOCK; > > /* > * Ensure we can't write on a read-only share or file. >-- >2.11.0 > > >From e7696b57adb82be80fb9ddc3909ec88ad464a87f Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Tue, 30 Jul 2019 12:24:53 +0200 >Subject: [PATCH 3/4] smbd: Fix retry for kernel-oplocked files > >This now removed comment describes the bug correctly: >/* > * As this timer event is owned by req, it will > * disappear if req it talloc_freed. > */ > >In smb1, "req" disappears once the reply_whatever routine is done. Thus >the timer goes away and we never look at "req" again. > >This change moves the valid data (xconn and mid) to >deferred_open_record, and changes the talloc hierarchy such that the >timer is now a child of open_rec, which is a child of the deferred >message. > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=14060 >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> > >Autobuild-User(master): Jeremy Allison <jra@samba.org> >Autobuild-Date(master): Wed Jul 31 00:12:34 UTC 2019 on sn-devel-184 > >(cherry picked from commit 2b590e16bcb4f4e1f1f0bf049a863db38e634beb) >--- > selftest/knownfail | 1 - > source3/smbd/open.c | 19 +++++++++++-------- > 2 files changed, 11 insertions(+), 9 deletions(-) > >diff --git a/selftest/knownfail b/selftest/knownfail >index 99772b45c4d..ded80b12259 100644 >--- a/selftest/knownfail >+++ b/selftest/knownfail >@@ -15,7 +15,6 @@ > ^samba3.smbtorture_s3.crypt_server # expected to give ACCESS_DENIED as SMB1 encryption isn't used > ^samba3.smbtorture_s3.*.LOCK12.*\(fileserver\) > ^samba3.smbtorture_s3.*.LOCK12.*\(nt4_dc\) >-^samba3.smbtorture_s3.*.OPLOCK5.*\(fileserver\) > ^samba3.nbt.dgram.*netlogon2\(nt4_dc\) > ^samba3.*rap.sam.*.useradd # Not provided by Samba 3 > ^samba3.*rap.sam.*.userdelete # Not provided by Samba 3 >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index 6838354a7d4..8fcd7b3b580 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -44,6 +44,9 @@ > extern const struct generic_mapping file_generic_mapping; > > struct deferred_open_record { >+ struct smbXsrv_connection *xconn; >+ uint64_t mid; >+ > bool delayed_for_oplocks; > bool async_open; > struct file_id id; >@@ -2504,10 +2507,12 @@ static void kernel_oplock_poll_open_timer(struct tevent_context *ev, > struct timeval current_time, > void *private_data) > { >+ struct deferred_open_record *open_rec = talloc_get_type_abort( >+ private_data, struct deferred_open_record); > bool ok; >- struct smb_request *req = (struct smb_request *)private_data; > >- ok = schedule_deferred_open_message_smb(req->xconn, req->mid); >+ ok = schedule_deferred_open_message_smb( >+ open_rec->xconn, open_rec->mid); > if (!ok) { > exit_server("schedule_deferred_open_message_smb failed"); > } >@@ -2535,6 +2540,8 @@ static void setup_kernel_oplock_poll_open(struct timeval request_time, > if (open_rec == NULL) { > exit_server("talloc failed"); > } >+ open_rec->xconn = req->xconn; >+ open_rec->mid = req->mid; > > ok = push_deferred_open_message_smb(req, > request_time, >@@ -2545,15 +2552,11 @@ static void setup_kernel_oplock_poll_open(struct timeval request_time, > exit_server("push_deferred_open_message_smb failed"); > } > >- /* >- * As this timer event is owned by req, it will >- * disappear if req it talloc_freed. >- */ > open_rec->te = tevent_add_timer(req->sconn->ev_ctx, >- req, >+ open_rec, > timeval_current_ofs(1, 0), > kernel_oplock_poll_open_timer, >- req); >+ open_rec); > if (open_rec->te == NULL) { > exit_server("tevent_add_timer failed"); > } >-- >2.11.0 > > >From 4b36ea38f22963b68dfc43d0026b72973eef9bcc Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@samba.org> >Date: Wed, 31 Jul 2019 10:52:40 +0200 >Subject: [PATCH 4/4] s3:torture: Fix the FreeBSD build > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=14060 > >Signed-off-by: Volker Lendecke <vl@samba.org> >Reviewed-by: Stefan Metzmacher <metze@samba.org> >(cherry picked from commit 10e140d25cd3cad8428e3b080ef28dd237d903d5) >--- > source3/torture/torture.c | 2 ++ > 1 file changed, 2 insertions(+) > >diff --git a/source3/torture/torture.c b/source3/torture/torture.c >index 17020328eaf..9d86fc39a89 100644 >--- a/source3/torture/torture.c >+++ b/source3/torture/torture.c >@@ -13815,10 +13815,12 @@ static struct { > .name = "OPLOCK4", > .fn = run_oplock4, > }, >+#ifdef HAVE_KERNEL_OPLOCKS_LINUX > { > .name = "OPLOCK5", > .fn = run_oplock5, > }, >+#endif > { > .name = "DIR", > .fn = run_dirtest, >-- >2.11.0 >
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 14060
: 15367 |
15368
|
15369
|
15436