[next] staging: greybus: Add __counted_by for struct apr_rx_buf and use struct_size()

Message ID ZSR2O6zGyT/VX6ve@work
State New
Headers
Series [next] staging: greybus: Add __counted_by for struct apr_rx_buf and use struct_size() |

Commit Message

Gustavo A. R. Silva Oct. 9, 2023, 9:52 p.m. UTC
  Prepare for the coming implementation by GCC and Clang of the __counted_by
attribute. Flexible array members annotated with __counted_by can have
their accesses bounds-checked at run-time via CONFIG_UBSAN_BOUNDS (for
array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family
functions).

While there, use struct_size() helper, instead of the open-coded
version, to calculate the size for the allocation of the whole
flexible structure, including of course, the flexible-array member.

This code was found with the help of Coccinelle, and audited and
fixed manually.

Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
 drivers/staging/greybus/raw.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
  

Comments

Kees Cook Oct. 9, 2023, 11:08 p.m. UTC | #1
On Mon, Oct 09, 2023 at 03:52:59PM -0600, Gustavo A. R. Silva wrote:
> Prepare for the coming implementation by GCC and Clang of the __counted_by
> attribute. Flexible array members annotated with __counted_by can have
> their accesses bounds-checked at run-time via CONFIG_UBSAN_BOUNDS (for
> array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family
> functions).
> 
> While there, use struct_size() helper, instead of the open-coded
> version, to calculate the size for the allocation of the whole
> flexible structure, including of course, the flexible-array member.
> 
> This code was found with the help of Coccinelle, and audited and
> fixed manually.
> 
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>

Looks right, "len" is updated before accessing "data[]".

Reviewed-by: Kees Cook <keescook@chromium.org>
  
Alex Elder Oct. 10, 2023, 2:01 a.m. UTC | #2
On 10/9/23 4:52 PM, Gustavo A. R. Silva wrote:
> Prepare for the coming implementation by GCC and Clang of the __counted_by
> attribute. Flexible array members annotated with __counted_by can have
> their accesses bounds-checked at run-time via CONFIG_UBSAN_BOUNDS (for
> array indexing) and CONFIG_FORTIFY_SOURCE (for strcpy/memcpy-family
> functions).
> 
> While there, use struct_size() helper, instead of the open-coded
> version, to calculate the size for the allocation of the whole
> flexible structure, including of course, the flexible-array member.
> 
> This code was found with the help of Coccinelle, and audited and
> fixed manually.

Looks good to me, and I like the use of struct_size().

Reviewed-by: Alex Elder <elder@linaro.org>

> 
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> ---
>   drivers/staging/greybus/raw.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c
> index a00978c8e1d2..b9c6eff7cdc1 100644
> --- a/drivers/staging/greybus/raw.c
> +++ b/drivers/staging/greybus/raw.c
> @@ -29,7 +29,7 @@ struct gb_raw {
>   struct raw_data {
>   	struct list_head entry;
>   	u32 len;
> -	u8 data[];
> +	u8 data[] __counted_by(len);
>   };
>   
>   static const struct class raw_class = {
> @@ -73,7 +73,7 @@ static int receive_data(struct gb_raw *raw, u32 len, u8 *data)
>   		goto exit;
>   	}
>   
> -	raw_data = kmalloc(sizeof(*raw_data) + len, GFP_KERNEL);
> +	raw_data = kmalloc(struct_size(raw_data, data, len), GFP_KERNEL);
>   	if (!raw_data) {
>   		retval = -ENOMEM;
>   		goto exit;
  

Patch

diff --git a/drivers/staging/greybus/raw.c b/drivers/staging/greybus/raw.c
index a00978c8e1d2..b9c6eff7cdc1 100644
--- a/drivers/staging/greybus/raw.c
+++ b/drivers/staging/greybus/raw.c
@@ -29,7 +29,7 @@  struct gb_raw {
 struct raw_data {
 	struct list_head entry;
 	u32 len;
-	u8 data[];
+	u8 data[] __counted_by(len);
 };
 
 static const struct class raw_class = {
@@ -73,7 +73,7 @@  static int receive_data(struct gb_raw *raw, u32 len, u8 *data)
 		goto exit;
 	}
 
-	raw_data = kmalloc(sizeof(*raw_data) + len, GFP_KERNEL);
+	raw_data = kmalloc(struct_size(raw_data, data, len), GFP_KERNEL);
 	if (!raw_data) {
 		retval = -ENOMEM;
 		goto exit;