While looking at the crash reported in https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=275597, I found some suspicious code in the VFS readdir handers. 1. The crash is caused by the code in cap_readdir (source3/modules/vfs_cap.c), which is problematic because the line: memcpy(newdirent, result, sizeof(struct dirent)); fails if (char *)result + sizeof(struct dirent) - 1 is in unmapped memory. On FreeBSD and Linux, the d_name field in struct dirent is an array of 256 bytes but testing shows that readdir() only guarantees that memory up to (char *)result + result->d_reclen is readable. 2. Possibly the same thing can happen in open_and_sort_dir (source3/modules/vfs_dirsort.c) when it does: data->directory_list[total_count] = *dp; and in shadow_copy_fdopendir and possibly other places. 3. Conversely, on Solaris, the d_name field in struct dirent is an array of 1 byte so the copying code in 2 will not copy the name (as reported for dirsort in bug 8466). 4. The code in cap_readdir allocates newdirent of size sizeof(struct dirent) + newnamelen, so that is double-counting the name bytes on FreeBSD and Linux.
Created attachment 18225 [details] Downstream patch for 4.16