Messages in this thread |  | | From | Andy Shevchenko <> | Date | Sat, 17 Dec 2022 13:43:40 +0200 | Subject | Re: [PATCH v3] [next] pcmcia: synclink_cs: replace 1-element array with flex-array member |
| |
On Sat, Dec 17, 2022 at 12:59 AM Paulo Miguel Almeida <paulo.miguel.almeida.rodenas@gmail.com> wrote: > > One-element arrays are deprecated, and we are replacing them with > flexible array members instead. So, replace one-element array with > flexible-array member in struct RXBUF and refactor the rest of the code > accordingly. While at it, fix an edge case which could cause > rx_buf_count to be 0 when max_frame_size was set to the maximum > allowed value (65535). > > It's worth mentioning that struct RXBUF was allocating 1 byte "too much" > for what is required (ignoring bytes added by padding). > > This helps with the ongoing efforts to tighten the FORTIFY_SOURCE > routines on memcpy() and help us make progress towards globally > enabling -fstrict-flex-arrays=3 [1].
...
> static int rx_alloc_buffers(MGSLPC_INFO *info) > { > /* each buffer has header and data */ > - info->rx_buf_size = sizeof(RXBUF) + info->max_frame_size; > + if (check_add_overflow(sizeof(RXBUF), info->max_frame_size, &info->rx_buf_size)) > + return -EINVAL; > > - /* calculate total allocation size for 8 buffers */ > - info->rx_buf_total_size = info->rx_buf_size * 8;
> + /* try to alloc as many buffers that can fit within RXBUF_MAX_SIZE (up to 8) */ > + if (check_mul_overflow(info->rx_buf_size, 8, &info->rx_buf_total_size)) > + return -EINVAL;
This check is implied by kcalloc(). But to make it effective we probably need to get a count first.
> - /* limit total allocated memory */ > - if (info->rx_buf_total_size > 0x10000) > - info->rx_buf_total_size = 0x10000; > + if (info->rx_buf_total_size > RXBUF_MAX_SIZE) > + info->rx_buf_total_size = RXBUF_MAX_SIZE;
If max_frame_size > 8192 - sizeof(RXBUF), we bump into this condition...
> /* calculate number of buffers */ > info->rx_buf_count = info->rx_buf_total_size / info->rx_buf_size;
...which means that rx_buf_count < 8... (and if max_frame_size > RXBUF_MAX_SIZE - sizeof(RXBUF), count becomes 0, I don't know if below clamp_val() is the only place to guarantee that)
> - info->rx_buf = kmalloc(info->rx_buf_total_size, GFP_KERNEL); > + info->rx_buf = kcalloc(info->rx_buf_count, info->rx_buf_size, GFP_KERNEL);
...hence rx_buf size will be less than rx_buf_total_size.
That is probably not an issue per se, but I'm wondering if the (bigger) value of rx_buf_total_size is the problem further in the code.
> if (info->rx_buf == NULL) > return -ENOMEM;
Maybe something like
static int rx_alloc_buffers(MGSLPC_INFO *info) { /* Prevent count from being 0 */ if (->max_frame_size > MAX_FRAME_SIZE) return -EINVAL; ... count = ...; ... rx_total_size = ... rx_buf = kcalloc(...);
Then you don't need to check overflow with check_add_overflow() and check_mul_overflow() will be inside the kcalloc.
...
> - if (info->max_frame_size < 4096) > - info->max_frame_size = 4096; > - else if (info->max_frame_size > 65535) > - info->max_frame_size = 65535; > + if (info->max_frame_size < MGSLPC_MIN_FRAME_SIZE) > + info->max_frame_size = MGSLPC_MIN_FRAME_SIZE; > + else if (info->max_frame_size > MGSLPC_MAX_FRAME_SIZE) > + info->max_frame_size = MGSLPC_MAX_FRAME_SIZE;
You can use clamp_val() macro here.
-- With Best Regards, Andy Shevchenko
|  |