Potential memory corruption in fileio.c:write_file() since
3.0.20 with write cache size
Jeremy Allison
jra at samba.org
Fri Aug 3 16:48:44 GMT 2007
On Fri, Aug 03, 2007 at 08:06:46AM -0700, Jean-Francois Panisset wrote:
> server: Samba 3.0.23c on CentOS5 x86_64
> client: Autodesk Maya 8.5 (a 3D modeling and animation application)
> on Windows XP SP2 32 bit
>
> After upgrading from Fedora Core 4/Samba 3.0.23a, I started
> experiencing mysterious hangs with Samba, which seemed to be
> triggered when writing large scene files from Maya 8.5 in Maya Binary
> format to a Samba share.
>
> After some digging, I came to the following conclusion:
>
> The share in question had:
>
> write cache size = 32768
>
> set in smb.conf. Turns out that when writing out largish files
> (around 50MB), in some cases Maya likes to write a single byte 49152
> bytes past the current end of file. This would trigger the following
> optimization in write_file() in smbd/fileio.c around line 510:
>
> } else if ( (pos >= wcp->file_size) &&
> (n == 1) &&
> (pos < wcp->offset + 2*wcp->alloc_size) &&
> (wcp->file_size == wcp->offset + wcp->data_size)) {
>
> SMB_BIG_UINT new_start = wcp->offset + wcp->data_size;
>
> flush_write_cache(fsp, WRITE_FLUSH);
> wcp->offset = new_start;
> wcp->data_size = pos - new_start + 1;
> memset(wcp->data, '\0', wcp->data_size);
> memcpy(wcp->data + wcp->data_size-1, data, 1);
>
> an optimization which appeared in 3.0.20, and claims to help with
> Microsoft Office behavior. With "write cache size" set to 32768, this
> means that wcp->alloc_size is 32768. If the application tries to
> write 1 byte 49152 bytes past the end of the file, the condition will
> trigger, and the call to memset() will write past the end of the
> 32768 byte long piece of memory allocated for the write cache
> bufferby setup_write_cache(), causing heap corruption. valgrind
> confirms that this is happening. In theory, I should have been seeing
> this with 3.0.23a on FC4 as well, but I guess I just got lucky.
Ok, I've looked carefully at this and I think this is the
correct patch. It's not quite correct to just change the
2*wcp->alloc_size to wcp->alloc_size, the actual test should
be pos < wcp->file_size + wcp->alloc_size I think.
I've attached the patch I plan to commit. Could you test
this in your setup please ? I think it will leave the
optimization correctly in place.
Thanks,
Jeremy.
-------------- next part --------------
Index: smbd/fileio.c
===================================================================
--- smbd/fileio.c (revision 24162)
+++ smbd/fileio.c (working copy)
@@ -509,29 +509,39 @@
write_path = 3;
- } else if ( (pos >= wcp->file_size) &&
+ } else if ( (pos >= wcp->file_size) &&
(n == 1) &&
- (pos < wcp->offset + 2*wcp->alloc_size) &&
- (wcp->file_size == wcp->offset + wcp->data_size)) {
+ (wcp->file_size == wcp->offset + wcp->data_size) &&
+ (pos < wcp->file_size + wcp->alloc_size)) {
/*
- +---------------+
- | Cached data |
- +---------------+
+ End of file ---->|
+
+ +---------------+---------------+
+ | Cached data | Cache buffer |
+ +---------------+---------------+
+
+ |<------- allocated size ---------------->|
+
+--------+
| 1 Byte |
+--------+
MS-Office seems to do this a lot to determine if there's enough
space on the filesystem to write a new file.
+
+ Change to :
+
+ End of file ---->|
+ +-----------------------+--------+
+ | Zeroed Cached data | 1 Byte |
+ +-----------------------+--------+
*/
- SMB_BIG_UINT new_start = wcp->offset + wcp->data_size;
-
flush_write_cache(fsp, WRITE_FLUSH);
- wcp->offset = new_start;
- wcp->data_size = pos - new_start + 1;
+ wcp->offset = wcp->file_size;
+ wcp->data_size = pos - wcp->file_size + 1;
memset(wcp->data, '\0', wcp->data_size);
memcpy(wcp->data + wcp->data_size-1, data, 1);
More information about the samba-technical
mailing list