diff options
author | Jeremy Allison <jra@samba.org> | 2013-04-08 16:40:35 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2013-04-11 09:49:41 -0700 |
commit | cdcb6319127883d724508da3f6140a1e2aca75af (patch) | |
tree | 12c73b62ba2750b543a5a83c718d41930c5fce87 /source3 | |
parent | 53d980bb0e70e40a07092c07d5fbd59fc8957f49 (diff) | |
download | samba-cdcb6319127883d724508da3f6140a1e2aca75af.tar.gz samba-cdcb6319127883d724508da3f6140a1e2aca75af.tar.bz2 samba-cdcb6319127883d724508da3f6140a1e2aca75af.zip |
Protect open_and_sort_dir() from the directory changing size.
Otherwise there could be an error between initial count, allocation
and re-read.
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'source3')
-rw-r--r-- | source3/modules/vfs_dirsort.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c index 1c24bc95c8..3ea720fc11 100644 --- a/source3/modules/vfs_dirsort.c +++ b/source3/modules/vfs_dirsort.c @@ -30,7 +30,7 @@ static int compare_dirent (const struct dirent *da, const struct dirent *db) struct dirsort_privates { long pos; struct dirent *directory_list; - long number_of_entries; + unsigned int number_of_entries; time_t mtime; DIR *source_directory; int fd; @@ -42,9 +42,9 @@ static void free_dirsort_privates(void **datap) { static bool open_and_sort_dir (vfs_handle_struct *handle) { - struct dirent *dp; struct stat dir_stat; unsigned int i; + unsigned int total_count = 0; struct dirsort_privates *data = NULL; SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates, @@ -58,10 +58,10 @@ static bool open_and_sort_dir (vfs_handle_struct *handle) while (SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL) != NULL) { - data->number_of_entries++; + total_count++; } - if (data->number_of_entries == 0) { + if (total_count == 0) { return false; } @@ -73,16 +73,22 @@ static bool open_and_sort_dir (vfs_handle_struct *handle) TALLOC_FREE(data->directory_list); /* destroy previous cache if needed */ data->directory_list = talloc_zero_array(data, struct dirent, - data->number_of_entries); + total_count); if (!data->directory_list) { return false; } - i = 0; - while ((dp = SMB_VFS_NEXT_READDIR(handle, data->source_directory, - NULL)) != NULL) { - data->directory_list[i++] = *dp; + for (i = 0; i < total_count; i++) { + struct dirent *dp = SMB_VFS_NEXT_READDIR(handle, + data->source_directory, + NULL); + if (dp == NULL) { + break; + } + data->directory_list[i] = *dp; } + data->number_of_entries = i; + /* Sort the directory entries by name */ TYPESAFE_QSORT(data->directory_list, data->number_of_entries, compare_dirent); return true; |