Module: wine Branch: master Commit: bc8d04d6a502b47ecc219bb2fc1000c391e20189 URL: https://source.winehq.org/git/wine.git/?a=commit;h=bc8d04d6a502b47ecc219bb2f...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Jul 9 10:09:49 2020 +0200
mountmgr: Fix handling of buffer overflows in IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/mountmgr.sys/mountmgr.c | 42 +++++++++++------------------------------- 1 file changed, 11 insertions(+), 31 deletions(-)
diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c index 6393dbf022..1961eab983 100644 --- a/dlls/mountmgr.sys/mountmgr.c +++ b/dlls/mountmgr.sys/mountmgr.c @@ -328,6 +328,7 @@ static NTSTATUS query_unix_drive( void *buff, SIZE_T insize, }
size = sizeof(*output); + if (label) size += (strlenW(label) + 1) * sizeof(WCHAR); if (device) size += strlen(device) + 1; if (mount_point) size += strlen(mount_point) + 1;
@@ -342,54 +343,33 @@ static NTSTATUS query_unix_drive( void *buff, SIZE_T insize, output->device_offset = 0; output->label_offset = 0;
- if (size > outsize) - { - iosb->Information = 0; - if (size >= FIELD_OFFSET( struct mountmgr_unix_drive, size ) + sizeof(output->size)) - { - output->size = size; - iosb->Information = FIELD_OFFSET( struct mountmgr_unix_drive, size ) + sizeof(output->size); - } - if (size >= FIELD_OFFSET( struct mountmgr_unix_drive, type ) + sizeof(output->type)) - { - output->type = type; - iosb->Information = FIELD_OFFSET( struct mountmgr_unix_drive, type ) + sizeof(output->type); - } - status = STATUS_BUFFER_OVERFLOW; - goto done; - } - ptr = (char *)(output + 1);
- if (mount_point) + if (label && ptr + (strlenW(label) + 1) * sizeof(WCHAR) - (char *)output <= outsize) + { + output->label_offset = ptr - (char *)output; + strcpyW( (WCHAR *)ptr, label ); + ptr += (strlenW(label) + 1) * sizeof(WCHAR); + } + if (mount_point && ptr + strlen(mount_point) + 1 - (char *)output <= outsize) { output->mount_point_offset = ptr - (char *)output; strcpy( ptr, mount_point ); ptr += strlen(ptr) + 1; } - else output->mount_point_offset = 0; - - if (device) + if (device && ptr + strlen(device) + 1 - (char *)output <= outsize) { output->device_offset = ptr - (char *)output; strcpy( ptr, device ); ptr += strlen(ptr) + 1; } - else output->device_offset = 0; - - if (label) - { - output->label_offset = ptr - (char *)output; - strcpyW( (WCHAR *)ptr, label ); - ptr += (strlenW(label) + 1) * sizeof(WCHAR); - } - else output->label_offset = 0;
TRACE( "returning %c: dev %s mount %s type %u\n", letter, debugstr_a(device), debugstr_a(mount_point), type );
iosb->Information = ptr - (char *)output; -done: + if (size > outsize) status = STATUS_BUFFER_OVERFLOW; + RtlFreeHeap( GetProcessHeap(), 0, device ); RtlFreeHeap( GetProcessHeap(), 0, mount_point ); RtlFreeHeap( GetProcessHeap(), 0, label );