media: ngene: Fix out-of-bounds bug in ngene_command_config_free_buf()
PATCH 1/1 media: ngene: Fix out-of-bounds bug in ngene_command_config_free_buf()
Fix an 11-year old bug in ngene_command_config_free_buf() while addressing the following warnings caught with -Warray-bounds:
arch/alpha/include/asm/string.h:22:16: warning: '__builtin_memcpy' offset [12, 16] from the object at 'com' is out of the bounds of referenced subobject 'config' with type 'unsigned char' at offset 10 [-Warray-bounds] arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [12, 16] from the object at 'com' is out of the bounds of referenced subobject 'config' with type 'unsigned char' at offset 10 [-Warray-bounds]
The problem is that the original code is trying to copy 6 bytes of data into a one-byte size member _config_ of the wrong structue FW_CONFIGURE_BUFFERS, in a single call to memcpy(). This causes a legitimate compiler warning because memcpy() overruns the length of &com.cmd.ConfigureBuffers.config. It seems that the right structure is FW_CONFIGURE_FREE_BUFFERS, instead, because it contains 6 more members apart from the header _hdr_. Also, the name of the function ngene_command_config_free_buf() suggests that the actual intention is to ConfigureFreeBuffers, instead of ConfigureBuffers (which configuration takes place in the function ngene_command_config_buf(), above).
Fix this by enclosing those 6 members of struct FW_CONFIGURE_FREE_BUFFERS into new struct config, and use &com.cmd.ConfigureFreeBuffers.config as the destination address, instead of &com.cmd.ConfigureBuffers.config, when calling memcpy().
This also helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the FORTIFY_SOURCE routines on memcpy().
--- drivers/media/pci/ngene/ngene-core.c | 2 +- drivers/media/pci/ngene/ngene.h | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-)
drivers/media/pci/ngene/ngene-core.c +1 -1
@@ -385,7 +385,7 @@ static int ngene_command_config_free_buf(struct ngene *dev, u8 *config) com.cmd.hdr.Opcode =CMD_CONFIGURE_FREE_BUFFER ; com.cmd.hdr.Length =6 ; -memcpy (&com.cmd.ConfigureBuffers.config, config,6 ); +memcpy (&com.cmd.ConfigureFreeBuffers.config, config,6 ); com.in_len =6 ; com.out_len =0 ;
drivers/media/pci/ngene/ngene.h +8 -6
@@ -407,12 +407,14 @@ enum _BUFFER_CONFIGS {struct FW_CONFIGURE_FREE_BUFFERS {struct FW_HEADER hdr; -u8 UVI1_BufferLength; -u8 UVI2_BufferLength; -u8 TVO_BufferLength; -u8 AUD1_BufferLength; -u8 AUD2_BufferLength; -u8 TVA_BufferLength; +struct { +u8 UVI1_BufferLength; +u8 UVI2_BufferLength; +u8 TVO_BufferLength; +u8 AUD1_BufferLength; +u8 AUD2_BufferLength; +u8 TVA_BufferLength; + } __packed config; } __attribute__ ((__packed__ ));struct FW_CONFIGURE_UART {
Signature · 1 line
2.27.0
Quoted 27 lines · Gustavo A. R. Silva
Fix an 11-year old bug in
ngene_command_config_free_buf()while addressing the following warnings caught with -Warray-bounds:
arch/alpha/include/asm/string.h:22:16: warning: '__builtin_memcpy' offset [12, 16] from the object at 'com' is out of the bounds of referenced subobject 'config' with type 'unsigned char' at offset 10 [-Warray-bounds]arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [12, 16] from the object at 'com' is out of the bounds of referenced subobject 'config' with type 'unsigned char' at offset 10 [-Warray-bounds]The problem is that the original code is trying to copy 6 bytes of data into a one-byte size member _config_ of the wrong structue
FW_CONFIGURE_BUFFERS, in a single call tomemcpy(). This causes a legitimate compiler warning becausememcpy()overruns the length of &com.cmd.ConfigureBuffers.config. It seems that the right structure isFW_CONFIGURE_FREE_BUFFERS, instead, because it contains 6 more members apart from the header _hdr_. Also, the name of the functionngene_command_config_free_buf()suggests that the actual intention is to ConfigureFreeBuffers, instead of ConfigureBuffers (which configuration takes place in the functionngene_command_config_buf(), above).Fix this by enclosing those 6 members of struct
FW_CONFIGURE_FREE_BUFFERSinto new struct config, and use &com.cmd.ConfigureFreeBuffers.config as the destination address, instead of &com.cmd.ConfigureBuffers.config, when callingmemcpy().This also helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the
FORTIFY_SOURCEroutines onmemcpy().
Quoted 5 lines
Fixes dae52d009fc9 ("V4L/DVB: ngene: Initial check-in")Reported-by kernel test robot <[email protected]>Signed-off-by Gustavo A. R. Silva <[email protected]>
Nice find! Yeah, this looks like a copy/paste bug but it went unnoticed because it's occupying the same memory via the union. Heh.
-Kees
Quoted 46 lines
--- drivers/media/pci/ngene/ngene-core.c | 2 +- drivers/media/pci/ngene/ngene.h | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-)drivers/media/pci/ngene/ngene-core.c +1
-1@@ -385,7 +385,7 @@ static int ngene_command_config_free_buf(struct ngene *dev, u8 *config) com.cmd.hdr.Opcode =CMD_CONFIGURE_FREE_BUFFER ; com.cmd.hdr.Length =6 ; -memcpy (&com.cmd.ConfigureBuffers.config, config,6 ); +memcpy (&com.cmd.ConfigureFreeBuffers.config, config,6 ); com.in_len =6 ; com.out_len =0 ;drivers/media/pci/ngene/ngene.h +8
-6@@ -407,12 +407,14 @@ enum _BUFFER_CONFIGS {struct FW_CONFIGURE_FREE_BUFFERS {struct FW_HEADER hdr; -u8 UVI1_BufferLength; -u8 UVI2_BufferLength; -u8 TVO_BufferLength; -u8 AUD1_BufferLength; -u8 AUD2_BufferLength; -u8 TVA_BufferLength; +struct { +u8 UVI1_BufferLength; +u8 UVI2_BufferLength; +u8 TVO_BufferLength; +u8 AUD1_BufferLength; +u8 AUD2_BufferLength; +u8 TVA_BufferLength; + } __packed config; } __attribute__ ((__packed__ ));struct FW_CONFIGURE_UART {Signature · 1 line
2.27.0
Signature · 1 line
Kees Cook
Hi all,
I'm taking this in my tree[1] for 5.14-rc3.
Thanks
--
Gustavo
[1] https://git.kernel.org/pub/scm/linux/kernel/git/gustavoars/linux.git/log/?h=for-next/array-bounds
Quoted 88 lines · Kees Cook
Quoted 27 lines · Gustavo A. R. Silva
Fix an 11-year old bug in
ngene_command_config_free_buf()while addressing the following warnings caught with -Warray-bounds:
arch/alpha/include/asm/string.h:22:16: warning: '__builtin_memcpy' offset [12, 16] from the object at 'com' is out of the bounds of referenced subobject 'config' with type 'unsigned char' at offset 10 [-Warray-bounds]arch/x86/include/asm/string_32.h:182:25: warning: '__builtin_memcpy' offset [12, 16] from the object at 'com' is out of the bounds of referenced subobject 'config' with type 'unsigned char' at offset 10 [-Warray-bounds]The problem is that the original code is trying to copy 6 bytes of data into a one-byte size member _config_ of the wrong structue
FW_CONFIGURE_BUFFERS, in a single call tomemcpy(). This causes a legitimate compiler warning becausememcpy()overruns the length of &com.cmd.ConfigureBuffers.config. It seems that the right structure isFW_CONFIGURE_FREE_BUFFERS, instead, because it contains 6 more members apart from the header _hdr_. Also, the name of the functionngene_command_config_free_buf()suggests that the actual intention is to ConfigureFreeBuffers, instead of ConfigureBuffers (which configuration takes place in the functionngene_command_config_buf(), above).Fix this by enclosing those 6 members of struct
FW_CONFIGURE_FREE_BUFFERSinto new struct config, and use &com.cmd.ConfigureFreeBuffers.config as the destination address, instead of &com.cmd.ConfigureBuffers.config, when callingmemcpy().This also helps with the ongoing efforts to globally enable -Warray-bounds and get us closer to being able to tighten the
FORTIFY_SOURCEroutines onmemcpy().Quoted 5 lines
Fixes dae52d009fc9 ("V4L/DVB: ngene: Initial check-in")Reported-by kernel test robot <[email protected]>Signed-off-by Gustavo A. R. Silva <[email protected]>Nice find! Yeah, this looks like a copy/paste bug but it went unnoticed because it's occupying the same memory via the union. Heh.
Reviewed-by Kees Cook <[email protected]>-Kees
Quoted 46 lines
--- drivers/media/pci/ngene/ngene-core.c | 2 +- drivers/media/pci/ngene/ngene.h | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-)drivers/media/pci/ngene/ngene-core.c +1
-1@@ -385,7 +385,7 @@ static int ngene_command_config_free_buf(struct ngene *dev, u8 *config) com.cmd.hdr.Opcode =CMD_CONFIGURE_FREE_BUFFER ; com.cmd.hdr.Length =6 ; -memcpy (&com.cmd.ConfigureBuffers.config, config,6 ); +memcpy (&com.cmd.ConfigureFreeBuffers.config, config,6 ); com.in_len =6 ; com.out_len =0 ;drivers/media/pci/ngene/ngene.h +8
-6@@ -407,12 +407,14 @@ enum _BUFFER_CONFIGS {struct FW_CONFIGURE_FREE_BUFFERS {struct FW_HEADER hdr; -u8 UVI1_BufferLength; -u8 UVI2_BufferLength; -u8 TVO_BufferLength; -u8 AUD1_BufferLength; -u8 AUD2_BufferLength; -u8 TVA_BufferLength; +struct { +u8 UVI1_BufferLength; +u8 UVI2_BufferLength; +u8 TVO_BufferLength; +u8 AUD1_BufferLength; +u8 AUD2_BufferLength; +u8 TVA_BufferLength; + } __packed config; } __attribute__ ((__packed__ ));struct FW_CONFIGURE_UART {Signature · 1 line
2.27.0