USB: ene_usb6250: Allocate enough memory for full object
Subsystems (2)
PATCH 1/1 USB: ene_usb6250: Allocate enough memory for full object
The allocation of PageBuffer is 512 bytes in size, but the dereferencing of struct ms_bootblock_idi (also size 512) happens at a calculated offset within the allocation, which means the object could potentially extend beyond the end of the allocation. Avoid this case by just allocating enough space to catch any accesses beyond the end. Seen with GCC 13:
../drivers/usb/storage/ene_ub6250.c: In function 'ms_lib_process_bootblock':../drivers/usb/storage/ene_ub6250.c:1050:44: warning: array subscript 'struct ms_bootblock_idi[0]' is partly outside array bounds of 'unsigned char[512]' [-Warray-bounds=]
1050 | if (le16_to_cpu(idi->wIDIgeneralConfiguration) != MS_IDI_GENERAL_CONF)
| ^~../include/uapi/linux/byteorder/little_endian.h:37:51: note: in definition of macro '__le16_to_cpu'
37 | #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
| ^../drivers/usb/storage/ene_ub6250.c:1050:29: note: in expansion of macro 'le16_to_cpu'
1050 | if (le16_to_cpu(idi->wIDIgeneralConfiguration) != MS_IDI_GENERAL_CONF)
| ^~~~~~~~~~~
In file included from ../drivers/usb/storage/ene_ub6250.c:5:
In function 'kmalloc',
inlined from 'ms_lib_process_bootblock' at ../drivers/usb/storage/ene_ub6250.c:942:15:
../include/linux/slab.h:580:24: note: at offset [256, 512] into object of size 512 allocated by 'kmalloc_trace'
580 | return kmalloc_trace(
| ^~~~~~~~~~~~~~
581 | kmalloc_caches[kmalloc_type(flags)][index],
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
582 | flags, size);
| ~~~~~~~~~~~~--- drivers/usb/storage/ene_ub6250.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/storage/ene_ub6250.c +1 -1
@@ -939,7 +939,7 @@ static int ms_lib_process_bootblock(struct us_data *us, u16 PhyBlock, u8 *PageDastruct ms_lib_type_extdat ExtraData;struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; - PageBuffer =kmalloc (MS_BYTES_PER_PAGE ,GFP_KERNEL ); + PageBuffer =kzalloc (MS_BYTES_PER_PAGE *2 ,GFP_KERNEL );if (PageBuffer ==NULL )return (u32)-1 ;
Signature · 1 line
2.34.1
Alan Stern
maintainerQuoted 5 lines · Kees Cook
The allocation of PageBuffer is 512 bytes in size, but the dereferencing of struct
ms_bootblock_idi(also size 512) happens at a calculated offset within the allocation, which means the object could potentially extend beyond the end of the allocation. Avoid this case by just allocating enough space to catch any accesses beyond the end. Seen with GCC 13:
In principle, it would be better to add a runtime check for overflow. Doing it this way means that the code could read an invalid value.
In fact, I get the impression that this code tries to load a data structure which might straddle a page boundary by reading in just the first page. Either that, or else EntryOffset is always a multiple of 512 so the error cannot arise.
In any event, it's doubtful that there are very many devices of this sort still in use, so it probably doesn't matter.
Alan Stern
Quoted 47 lines
../drivers/usb/storage/ene_ub6250.c: In function 'ms_lib_process_bootblock':../drivers/usb/storage/ene_ub6250.c:1050:44: warning: array subscript 'struct ms_bootblock_idi[0]' is partly outside array bounds of 'unsigned char[512]' [-Warray-bounds=]
1050 | if (le16_to_cpu(idi->wIDIgeneralConfiguration)!=MS_IDI_GENERAL_CONF)
| ^~../include/uapi/linux/byteorder/little_endian.h:37:51: note: in definition of macro '__le16_to_cpu'
37 | #define__le16_to_cpu(x)((__force__u16)(__le16)(x))
| ^../drivers/usb/storage/ene_ub6250.c:1050:29: note: in expansion of macro 'le16_to_cpu'
1050 | if (le16_to_cpu(idi->wIDIgeneralConfiguration)!=MS_IDI_GENERAL_CONF)| ^~~~~~~~~~~ In file included from ../drivers/usb/storage/ene_ub6250.c:5: In function 'kmalloc', inlined from 'ms_lib_process_bootblock' at ../drivers/usb/storage/ene_ub6250.c:942:15: ../include/linux/slab.h:580:24: note: at offset [256, 512] into object of size 512 allocated by 'kmalloc_trace' 580 | return kmalloc_trace( | ^~~~~~~~~~~~~~ 581 | kmalloc_caches[kmalloc_type(flags)][index], | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 582 | flags, size); | ~~~~~~~~~~~~Cc Alan Stern <[email protected]>Cc Greg Kroah-Hartman <[email protected]>Signed-off-by Kees Cook <[email protected]>--- drivers/usb/storage/ene_ub6250.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/usb/storage/ene_ub6250.c +1
-1@@ -939,7 +939,7 @@ static int ms_lib_process_bootblock(struct us_data *us, u16 PhyBlock, u8 *PageDastruct ms_lib_type_extdat ExtraData;struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra; - PageBuffer =kmalloc (MS_BYTES_PER_PAGE ,GFP_KERNEL ); + PageBuffer =kzalloc (MS_BYTES_PER_PAGE *2 ,GFP_KERNEL );if (PageBuffer ==NULL )return (u32)-1 ;Signature · 1 line
2.34.1
Quoted 7 lines · Alan Stern
Quoted 5 lines · Kees Cook
The allocation of PageBuffer is 512 bytes in size, but the dereferencing of struct
ms_bootblock_idi(also size 512) happens at a calculated offset within the allocation, which means the object could potentially extend beyond the end of the allocation. Avoid this case by just allocating enough space to catch any accesses beyond the end. Seen with GCC 13:
Quoted 7 lines
In principle, it would be better to add a runtime check for overflow. Doing it this way means that the code could read an invalid value.
In fact, I get the impression that this code tries to load a data structure which might straddle a page boundary by reading in just the first page. Either that, or else EntryOffset is always a multiple of 512 so the error cannot arise.
Yeah, I couldn't figure it out. It seems like it might move in non-512-byte steps too sometimes? Doubling the allocation (and zero-fill it) seemed the safest way to cover it.
-Kees
Signature · 1 line
Kees Cook
Alan Stern
maintainerQuoted 11 lines · Kees Cook
Quoted 10 lines · Alan Stern
Quoted 5 lines · Kees Cook
The allocation of PageBuffer is 512 bytes in size, but the dereferencing of struct
ms_bootblock_idi(also size 512) happens at a calculated offset within the allocation, which means the object could potentially extend beyond the end of the allocation. Avoid this case by just allocating enough space to catch any accesses beyond the end. Seen with GCC 13:In principle, it would be better to add a runtime check for overflow. Doing it this way means that the code could read an invalid value.
Quoted 8 lines
Quoted 4 lines
In fact, I get the impression that this code tries to load a data structure which might straddle a page boundary by reading in just the first page. Either that, or else EntryOffset is always a multiple of 512 so the error cannot arise.
Yeah, I couldn't figure it out. It seems like it might move in non-512-byte steps too sometimes? Doubling the allocation (and zero-fill it) seemed the safest way to cover it.
It hardly seems to matter at this point. I doubt that any significant number of laptops still in operation use the ENE UB6250 reader. The driver was originally written in 2010, and official support for the hardware under Windows apparently ended with Windows 7.
Alan Stern