The Samba-Bugzilla – Attachment 9678 Details for
Bug 10406
vfs_dirsort can trample on its own private data.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
git-am backport of the fix that went into master.
bug-10406-4.0.patchset (text/plain), 9.53 KB, created by
Jeremy Allison
on 2014-02-12 19:30:40 UTC
(
hide
)
Description:
git-am backport of the fix that went into master.
Filename:
MIME Type:
Creator:
Jeremy Allison
Created:
2014-02-12 19:30:40 UTC
Size:
9.53 KB
patch
obsolete
>From 587c0a9f23cd68dc85b6cb69f8d8e2066e3a2b22 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 29 Jan 2014 17:01:30 -0800 >Subject: [PATCH 1/2] s3: vfs_dirsort module. > >Allow dirsort to work when multiple simultaneous >directories are open. The old code only keeps one >active private data pointer on the connection struct, opening >a second directory on the same connection will overwrite it. > >This modification turns the private data pointer >into a linked list of open directories on the >connection struct, and finds the correct one by searching >on the passed in DIR *. > >With this code in place, smbd passes raw.search >torture test on a share definition with: > >vfs objects = dirsort > >https://bugzilla.samba.org/show_bug.cgi?id=10406 > >Signed-off-by: Jeremy Allison <jra@samba.org> > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(back-ported from commit fd79652b0e598882e0c4d156bd897c29dae8ec04) >--- > source3/modules/vfs_dirsort.c | 119 +++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 112 insertions(+), 7 deletions(-) > >diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c >index 64d74d5..72b46c9 100644 >--- a/source3/modules/vfs_dirsort.c >+++ b/source3/modules/vfs_dirsort.c >@@ -28,6 +28,7 @@ static int compare_dirent (const struct dirent *da, const struct dirent *db) > } > > struct dirsort_privates { >+ struct dirsort_privates *prev, *next; > long pos; > struct dirent *directory_list; > unsigned int number_of_entries; >@@ -37,10 +38,6 @@ struct dirsort_privates { > struct smb_filename *smb_fname; /* If open via OPENDIR */ > }; > >-static void free_dirsort_privates(void **datap) { >- TALLOC_FREE(*datap); >-} >- > static bool get_sorted_dir_mtime(vfs_handle_struct *handle, > struct dirsort_privates *data, > struct timespec *ret_mtime) >@@ -120,8 +117,15 @@ static DIR *dirsort_opendir(vfs_handle_struct *handle, > uint32 attr) > { > NTSTATUS status; >+ struct dirsort_privates *list_head = NULL; > struct dirsort_privates *data = NULL; > >+ if (SMB_VFS_HANDLE_TEST_DATA(handle)) { >+ /* Find the list head of all open directories. */ >+ SMB_VFS_HANDLE_GET_DATA(handle, list_head, struct dirsort_privates, >+ return NULL); >+ } >+ > /* set up our private data about this directory */ > data = talloc_zero(handle->conn, struct dirsort_privates); > if (!data) { >@@ -153,7 +157,9 @@ static DIR *dirsort_opendir(vfs_handle_struct *handle, > return NULL; > } > >- SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates, >+ /* Add to the private list of all open directories. */ >+ DLIST_ADD(list_head, data); >+ SMB_VFS_HANDLE_SET_DATA(handle, list_head, NULL, > struct dirsort_privates, return NULL); > > return data->source_directory; >@@ -164,8 +170,15 @@ static DIR *dirsort_fdopendir(vfs_handle_struct *handle, > const char *mask, > uint32 attr) > { >+ struct dirsort_privates *list_head = NULL; > struct dirsort_privates *data = NULL; > >+ if (SMB_VFS_HANDLE_TEST_DATA(handle)) { >+ /* Find the list head of all open directories. */ >+ SMB_VFS_HANDLE_GET_DATA(handle, list_head, struct dirsort_privates, >+ return NULL); >+ } >+ > /* set up our private data about this directory */ > data = talloc_zero(handle->conn, struct dirsort_privates); > if (!data) { >@@ -191,7 +204,9 @@ static DIR *dirsort_fdopendir(vfs_handle_struct *handle, > return NULL; > } > >- SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates, >+ /* Add to the private list of all open directories. */ >+ DLIST_ADD(list_head, data); >+ SMB_VFS_HANDLE_SET_DATA(handle, list_head, NULL, > struct dirsort_privates, return NULL); > > return data->source_directory; >@@ -207,12 +222,20 @@ static struct dirent *dirsort_readdir(vfs_handle_struct *handle, > SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, > return NULL); > >+ while(data && (data->source_directory != dirp)) { >+ data = data->next; >+ } >+ if (data == NULL) { >+ return NULL; >+ } >+ > if (get_sorted_dir_mtime(handle, data, ¤t_mtime) == false) { > return NULL; > } > > /* throw away cache and re-read the directory if we've changed */ >- if (timespec_compare(¤t_mtime, &data->mtime) > 1) { >+ if (timespec_compare(¤t_mtime, &data->mtime)) { >+ SMB_VFS_NEXT_REWINDDIR(handle, data->source_directory); > open_and_sort_dir(handle, data); > } > >@@ -226,10 +249,53 @@ static struct dirent *dirsort_readdir(vfs_handle_struct *handle, > static void dirsort_seekdir(vfs_handle_struct *handle, DIR *dirp, > long offset) > { >+ struct timespec current_mtime; > struct dirsort_privates *data = NULL; >+ > SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, return); > >+ /* Find the entry holding dirp. */ >+ while(data && (data->source_directory != dirp)) { >+ data = data->next; >+ } >+ if (data == NULL) { >+ return; >+ } >+ if (offset > data->number_of_entries) { >+ return; >+ } > data->pos = offset; >+ >+ if (get_sorted_dir_mtime(handle, data, ¤t_mtime) == false) { >+ return; >+ } >+ >+ if (timespec_compare(¤t_mtime, &data->mtime)) { >+ /* Directory changed. We must re-read the >+ cache and search for the name that was >+ previously stored at the offset being >+ requested, otherwise after the re-sort >+ we will point to the wrong entry. The >+ OS/2 incremental delete code relies on >+ this. */ >+ unsigned int i; >+ char *wanted_name = talloc_strdup(handle->conn, >+ data->directory_list[offset].d_name); >+ if (wanted_name == NULL) { >+ return; >+ } >+ SMB_VFS_NEXT_REWINDDIR(handle, data->source_directory); >+ open_and_sort_dir(handle, data); >+ /* Now search for where we were. */ >+ data->pos = 0; >+ for (i = 0; i < data->number_of_entries; i++) { >+ if(strcmp(wanted_name, data->directory_list[i].d_name) == 0) { >+ data->pos = i; >+ break; >+ } >+ } >+ TALLOC_FREE(wanted_name); >+ } > } > > static long dirsort_telldir(vfs_handle_struct *handle, DIR *dirp) >@@ -238,6 +304,13 @@ static long dirsort_telldir(vfs_handle_struct *handle, DIR *dirp) > SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, > return -1); > >+ /* Find the entry holding dirp. */ >+ while(data && (data->source_directory != dirp)) { >+ data = data->next; >+ } >+ if (data == NULL) { >+ return -1; >+ } > return data->pos; > } > >@@ -246,9 +319,40 @@ static void dirsort_rewinddir(vfs_handle_struct *handle, DIR *dirp) > struct dirsort_privates *data = NULL; > SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, return); > >+ /* Find the entry holding dirp. */ >+ while(data && (data->source_directory != dirp)) { >+ data = data->next; >+ } >+ if (data == NULL) { >+ return; >+ } > data->pos = 0; > } > >+static int dirsort_closedir(vfs_handle_struct *handle, DIR *dirp) >+{ >+ struct dirsort_privates *list_head = NULL; >+ struct dirsort_privates *data = NULL; >+ int ret; >+ >+ SMB_VFS_HANDLE_GET_DATA(handle, list_head, struct dirsort_privates, return -1); >+ /* Find the entry holding dirp. */ >+ for(data = list_head; data && (data->source_directory != dirp); data = data->next) { >+ ; >+ } >+ if (data == NULL) { >+ return -1; >+ } >+ /* Remove from the list and re-store the list head. */ >+ DLIST_REMOVE(list_head, data); >+ SMB_VFS_HANDLE_SET_DATA(handle, list_head, NULL, >+ struct dirsort_privates, return -1); >+ >+ ret = SMB_VFS_NEXT_CLOSEDIR(handle, dirp); >+ TALLOC_FREE(data); >+ return ret; >+} >+ > static struct vfs_fn_pointers vfs_dirsort_fns = { > .opendir_fn = dirsort_opendir, > .fdopendir_fn = dirsort_fdopendir, >@@ -256,6 +360,7 @@ static struct vfs_fn_pointers vfs_dirsort_fns = { > .seekdir_fn = dirsort_seekdir, > .telldir_fn = dirsort_telldir, > .rewind_dir_fn = dirsort_rewinddir, >+ .closedir_fn = dirsort_closedir, > }; > > NTSTATUS vfs_dirsort_init(void) >-- >1.9.0.rc1.175.g0b1dcb5 > > >From 76183716c85114ff3cd9e603eead1148645f69b8 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Tue, 11 Feb 2014 10:39:04 -0800 >Subject: [PATCH 2/2] s3: vfs_dirsort module. > >Add raw.search torture test on a share definition with: > >vfs objects = dirsort > >https://bugzilla.samba.org/show_bug.cgi?id=10406 > >Signed-off-by: Jeremy Allison <jra@samba.org> > >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >(cherry picked from commit 30cc8f41da58b87ff575860b7cde640520829923) >--- > selftest/target/Samba3.pm | 4 ++++ > source3/selftest/tests.py | 5 +++++ > 2 files changed, 9 insertions(+) > >diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm >index 792bbca..59a9f79 100755 >--- a/selftest/target/Samba3.pm >+++ b/selftest/target/Samba3.pm >@@ -933,6 +933,10 @@ sub provision($$$$$$) > [tmp] > path = $shrdir > comment = smb username is [%U] >+[tmpsort] >+ path = $shrdir >+ comment = Load dirsort module >+ vfs objects = dirsort acl_xattr fake_acls xattr_tdb streams_depot > [tmpenc] > path = $shrdir > comment = encrypt smb username is [%U] >diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py >index a968665..2965aae 100755 >--- a/source3/selftest/tests.py >+++ b/source3/selftest/tests.py >@@ -340,6 +340,11 @@ for t in tests: > plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/aio -U$USERNAME%$PASSWORD', 'aio') > plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') > plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD') >+ elif t == "raw.search": >+ plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') >+# test the dirsort module. >+ plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmpsort -U$USERNAME%$PASSWORD') >+ plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD') > else: > plansmbtorture4testsuite(t, "s3dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD') > plansmbtorture4testsuite(t, "plugin_s4_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD') >-- >1.9.0.rc1.175.g0b1dcb5 >
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:
abartlet
:
review+
Actions:
View
Attachments on
bug 10406
:
9621
| 9678 |
9679