s3:smbd: fix max_buffer handling of initial notify requests
authorStefan Metzmacher <metze@samba.org>
Wed, 16 Jan 2019 20:29:51 +0000 (21:29 +0100)
committerJeremy Allison <jra@samba.org>
Fri, 29 Mar 2019 00:35:39 +0000 (00:35 +0000)
The max_buffer value is only evaluated on the first notify
request on a directory handle.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13864

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Fri Mar 29 00:35:39 UTC 2019 on sn-devel-144

selftest/knownfail
source3/smbd/notify.c
source3/smbd/nttrans.c
source3/smbd/proto.h
source3/smbd/smb2_notify.c

index 49e889e..c588f2f 100644 (file)
 ^samba3.smb2.create.gentest
 ^samba3.smb2.create.blob
 ^samba3.smb2.create.open
-^samba3.smb2.notify.valid-req
 ^samba3.smb2.notify.rec
 ^samba3.smb2.durable-open.delete_on_close2
 ^samba3.smb2.durable-v2-open.app-instance
index 44c0b09..bf3fff7 100644 (file)
@@ -43,6 +43,8 @@ struct notify_change_buf {
         * we only append.
         */
 
+       uint32_t max_buffer_size;
+
        /*
         * num_changes == -1 means that we have got a catch-all change, when
         * asked we just return NT_STATUS_OK without specific changes.
@@ -224,11 +226,13 @@ void change_notify_reply(struct smb_request *req,
                return;
        }
 
-       if (max_param == 0 || notify_buf == NULL) {
+       if (notify_buf == NULL) {
                reply_fn(req, NT_STATUS_OK, NULL, 0);
                return;
        }
 
+       max_param = MIN(max_param, notify_buf->max_buffer_size);
+
        if (!notify_marshall_changes(notify_buf->num_changes, max_param,
                                        notify_buf->changes, &blob)) {
                /*
@@ -276,7 +280,9 @@ void notify_callback(struct smbd_server_connection *sconn,
        files_forall(sconn, notify_fsp_cb, &state);
 }
 
-NTSTATUS change_notify_create(struct files_struct *fsp, uint32_t filter,
+NTSTATUS change_notify_create(struct files_struct *fsp,
+                             uint32_t max_buffer_size,
+                             uint32_t filter,
                              bool recursive)
 {
        size_t len = fsp_fullbasepath(fsp, NULL, 0);
@@ -295,6 +301,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32_t filter,
        }
        fsp->notify->filter = filter;
        fsp->notify->subdir_filter = recursive ? filter : 0;
+       fsp->notify->max_buffer_size = max_buffer_size;
 
        fsp_fullbasepath(fsp, fullpath, sizeof(fullpath));
 
index 7ebd802..8bb121a 100644 (file)
@@ -1806,8 +1806,10 @@ static void call_nt_transact_notify_change(connection_struct *conn,
 
        if (fsp->notify == NULL) {
 
-               status = change_notify_create(fsp, filter, recursive);
-
+               status = change_notify_create(fsp,
+                                             max_param_count,
+                                             filter,
+                                             recursive);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(10, ("change_notify_create returned %s\n",
                                   nt_errstr(status)));
index 3662a92..fdb0ffa 100644 (file)
@@ -542,7 +542,9 @@ void change_notify_reply(struct smb_request *req,
 void notify_callback(struct smbd_server_connection *sconn,
                     void *private_data, struct timespec when,
                     const struct notify_event *e);
-NTSTATUS change_notify_create(struct files_struct *fsp, uint32_t filter,
+NTSTATUS change_notify_create(struct files_struct *fsp,
+                             uint32_t max_buffer_size,
+                             uint32_t filter,
                              bool recursive);
 NTSTATUS change_notify_add_request(struct smb_request *req,
                                uint32_t max_param,
index 2424156..68429b7 100644 (file)
@@ -263,6 +263,7 @@ static struct tevent_req *smbd_smb2_notify_send(TALLOC_CTX *mem_ctx,
        if (fsp->notify == NULL) {
 
                status = change_notify_create(fsp,
+                                             in_output_buffer_length,
                                              in_completion_filter,
                                              recursive);
                if (!NT_STATUS_IS_OK(status)) {