diff mbox series

[next] jbd2: Avoid dozens of -Wflex-array-member-not-at-end warnings

Message ID ZxvyavDjXDaV9cNg@kspp
State Superseded
Headers show
Series [next] jbd2: Avoid dozens of -Wflex-array-member-not-at-end warnings | expand

Commit Message

Gustavo A. R. Silva Oct. 25, 2024, 7:32 p.m. UTC
-Wflex-array-member-not-at-end was introduced in GCC-14, and we
are getting ready to enable it, globally.

Use the `DEFINE_RAW_FLEX()` helper for an on-stack definition of
a flexible structure (`struct shash_desc`) where the size of the
flexible-array member (`__ctx`) is known at compile-time, and
refactor the rest of the code, accordingly.

So, with this, fix 77 of the following warnings:

include/linux/jbd2.h:1800:35: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]

Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
 include/linux/jbd2.h | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

Comments

Jan Kara Oct. 31, 2024, 12:33 p.m. UTC | #1
On Fri 25-10-24 13:32:58, Gustavo A. R. Silva wrote:
> -Wflex-array-member-not-at-end was introduced in GCC-14, and we
> are getting ready to enable it, globally.
> 
> Use the `DEFINE_RAW_FLEX()` helper for an on-stack definition of
> a flexible structure (`struct shash_desc`) where the size of the
> flexible-array member (`__ctx`) is known at compile-time, and
> refactor the rest of the code, accordingly.
> 
> So, with this, fix 77 of the following warnings:
> 
> include/linux/jbd2.h:1800:35: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> 
> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> ---
>  include/linux/jbd2.h | 13 +++++--------
>  1 file changed, 5 insertions(+), 8 deletions(-)
> 
> diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
> index 8aef9bb6ad57..ce4560e62d3b 100644
> --- a/include/linux/jbd2.h
> +++ b/include/linux/jbd2.h
> @@ -1796,22 +1796,19 @@ static inline unsigned long jbd2_log_space_left(journal_t *journal)
>  static inline u32 jbd2_chksum(journal_t *journal, u32 crc,
>  			      const void *address, unsigned int length)
>  {
> -	struct {
> -		struct shash_desc shash;
> -		char ctx[JBD_MAX_CHECKSUM_SIZE];
> -	} desc;
> +	DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx, 1);

Am I missing some magic here or the 1 above should be
JBD_MAX_CHECKSUM_SIZE?

								Honza
Gustavo A. R. Silva Oct. 31, 2024, 3:54 p.m. UTC | #2
On 31/10/24 06:33, Jan Kara wrote:
> On Fri 25-10-24 13:32:58, Gustavo A. R. Silva wrote:
>> -Wflex-array-member-not-at-end was introduced in GCC-14, and we
>> are getting ready to enable it, globally.
>>
>> Use the `DEFINE_RAW_FLEX()` helper for an on-stack definition of
>> a flexible structure (`struct shash_desc`) where the size of the
>> flexible-array member (`__ctx`) is known at compile-time, and
>> refactor the rest of the code, accordingly.
>>
>> So, with this, fix 77 of the following warnings:
>>
>> include/linux/jbd2.h:1800:35: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>>
>> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
>> ---
>>   include/linux/jbd2.h | 13 +++++--------
>>   1 file changed, 5 insertions(+), 8 deletions(-)
>>
>> diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
>> index 8aef9bb6ad57..ce4560e62d3b 100644
>> --- a/include/linux/jbd2.h
>> +++ b/include/linux/jbd2.h
>> @@ -1796,22 +1796,19 @@ static inline unsigned long jbd2_log_space_left(journal_t *journal)
>>   static inline u32 jbd2_chksum(journal_t *journal, u32 crc,
>>   			      const void *address, unsigned int length)
>>   {
>> -	struct {
>> -		struct shash_desc shash;
>> -		char ctx[JBD_MAX_CHECKSUM_SIZE];
>> -	} desc;
>> +	DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx, 1);
> 
> Am I missing some magic here or the 1 above should be
> JBD_MAX_CHECKSUM_SIZE?

This seems to be 32-bit code, and the element type of the flex-array
member `__ctx` is `void *`. Therefore, we have:

`sizeof(ctx) == 4` when `char ctx[JBD_MAX_CHECKSUM_SIZE];`

To maintain the same size, we tell `DEFINE_RAW_FLEX()` to allocate `1`
element for the flex array, as in 32-bit `sizeof(void *) == 4`.

--
Gustavo
Jan Kara Oct. 31, 2024, 9:32 p.m. UTC | #3
On Thu 31-10-24 09:54:36, Gustavo A. R. Silva wrote:
> On 31/10/24 06:33, Jan Kara wrote:
> > On Fri 25-10-24 13:32:58, Gustavo A. R. Silva wrote:
> > > -Wflex-array-member-not-at-end was introduced in GCC-14, and we
> > > are getting ready to enable it, globally.
> > > 
> > > Use the `DEFINE_RAW_FLEX()` helper for an on-stack definition of
> > > a flexible structure (`struct shash_desc`) where the size of the
> > > flexible-array member (`__ctx`) is known at compile-time, and
> > > refactor the rest of the code, accordingly.
> > > 
> > > So, with this, fix 77 of the following warnings:
> > > 
> > > include/linux/jbd2.h:1800:35: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
> > > 
> > > Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> > > ---
> > >   include/linux/jbd2.h | 13 +++++--------
> > >   1 file changed, 5 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
> > > index 8aef9bb6ad57..ce4560e62d3b 100644
> > > --- a/include/linux/jbd2.h
> > > +++ b/include/linux/jbd2.h
> > > @@ -1796,22 +1796,19 @@ static inline unsigned long jbd2_log_space_left(journal_t *journal)
> > >   static inline u32 jbd2_chksum(journal_t *journal, u32 crc,
> > >   			      const void *address, unsigned int length)
> > >   {
> > > -	struct {
> > > -		struct shash_desc shash;
> > > -		char ctx[JBD_MAX_CHECKSUM_SIZE];
> > > -	} desc;
> > > +	DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx, 1);
> > 
> > Am I missing some magic here or the 1 above should be
> > JBD_MAX_CHECKSUM_SIZE?
> 
> This seems to be 32-bit code, and the element type of the flex-array
> member `__ctx` is `void *`. Therefore, we have:

Why do you think the code is 32-bit? It is used regardless of the
architecture...

> `sizeof(ctx) == 4` when `char ctx[JBD_MAX_CHECKSUM_SIZE];`
> 
> To maintain the same size, we tell `DEFINE_RAW_FLEX()` to allocate `1`
> element for the flex array, as in 32-bit `sizeof(void *) == 4`.

So I agree we end up allocating enough space on stack but it is pretty
subtle and if JBD_MAX_CHECKSUM_SIZE definition changes, we have a problem.
I think we need something like (JBD_MAX_CHECKSUM_SIZE + sizeof(*desc->__ctx)
- 1) / sizeof(*desc->__ctx))?

								Honza
Gustavo A. R. Silva Oct. 31, 2024, 11:31 p.m. UTC | #4
On 31/10/24 15:32, Jan Kara wrote:
> On Thu 31-10-24 09:54:36, Gustavo A. R. Silva wrote:
>> On 31/10/24 06:33, Jan Kara wrote:
>>> On Fri 25-10-24 13:32:58, Gustavo A. R. Silva wrote:
>>>> -Wflex-array-member-not-at-end was introduced in GCC-14, and we
>>>> are getting ready to enable it, globally.
>>>>
>>>> Use the `DEFINE_RAW_FLEX()` helper for an on-stack definition of
>>>> a flexible structure (`struct shash_desc`) where the size of the
>>>> flexible-array member (`__ctx`) is known at compile-time, and
>>>> refactor the rest of the code, accordingly.
>>>>
>>>> So, with this, fix 77 of the following warnings:
>>>>
>>>> include/linux/jbd2.h:1800:35: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>>>>
>>>> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
>>>> ---
>>>>    include/linux/jbd2.h | 13 +++++--------
>>>>    1 file changed, 5 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
>>>> index 8aef9bb6ad57..ce4560e62d3b 100644
>>>> --- a/include/linux/jbd2.h
>>>> +++ b/include/linux/jbd2.h
>>>> @@ -1796,22 +1796,19 @@ static inline unsigned long jbd2_log_space_left(journal_t *journal)
>>>>    static inline u32 jbd2_chksum(journal_t *journal, u32 crc,
>>>>    			      const void *address, unsigned int length)
>>>>    {
>>>> -	struct {
>>>> -		struct shash_desc shash;
>>>> -		char ctx[JBD_MAX_CHECKSUM_SIZE];
>>>> -	} desc;
>>>> +	DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx, 1);
>>>
>>> Am I missing some magic here or the 1 above should be
>>> JBD_MAX_CHECKSUM_SIZE?
>>
>> This seems to be 32-bit code, and the element type of the flex-array
>> member `__ctx` is `void *`. Therefore, we have:
> 
> Why do you think the code is 32-bit? It is used regardless of the
> architecture...

Right, sorry, I got a bit confused...

> 
>> `sizeof(ctx) == 4` when `char ctx[JBD_MAX_CHECKSUM_SIZE];`
>>
>> To maintain the same size, we tell `DEFINE_RAW_FLEX()` to allocate `1`
>> element for the flex array, as in 32-bit `sizeof(void *) == 4`.
> 
> So I agree we end up allocating enough space on stack but it is pretty
> subtle and if JBD_MAX_CHECKSUM_SIZE definition changes, we have a problem.
> I think we need something like (JBD_MAX_CHECKSUM_SIZE + sizeof(*desc->__ctx)
> - 1) / sizeof(*desc->__ctx))?

I see. Well, in that case it'd be something more like:

-       struct {
-               struct shash_desc shash;
-               char ctx[JBD_MAX_CHECKSUM_SIZE];
-       } desc;
+       DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx,
+                       (JBD_MAX_CHECKSUM_SIZE +
+                        sizeof(*((struct shash_desc *)0)->__ctx)) /
+                        sizeof(*((struct shash_desc *)0)->__ctx));

Notice that `desc` is created inside `DEFINE_RAW_FLEX()`

Thanks
--
Gustavo
Jan Kara Nov. 1, 2024, 10:15 a.m. UTC | #5
On Thu 31-10-24 17:31:34, Gustavo A. R. Silva wrote:
> On 31/10/24 15:32, Jan Kara wrote:
> > 
> > > `sizeof(ctx) == 4` when `char ctx[JBD_MAX_CHECKSUM_SIZE];`
> > > 
> > > To maintain the same size, we tell `DEFINE_RAW_FLEX()` to allocate `1`
> > > element for the flex array, as in 32-bit `sizeof(void *) == 4`.
> > 
> > So I agree we end up allocating enough space on stack but it is pretty
> > subtle and if JBD_MAX_CHECKSUM_SIZE definition changes, we have a problem.
> > I think we need something like (JBD_MAX_CHECKSUM_SIZE + sizeof(*desc->__ctx)
> > - 1) / sizeof(*desc->__ctx))?
> 
> I see. Well, in that case it'd be something more like:
> 
> -       struct {
> -               struct shash_desc shash;
> -               char ctx[JBD_MAX_CHECKSUM_SIZE];
> -       } desc;
> +       DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx,
> +                       (JBD_MAX_CHECKSUM_SIZE +
> +                        sizeof(*((struct shash_desc *)0)->__ctx)) /
> +                        sizeof(*((struct shash_desc *)0)->__ctx));
> 
> Notice that `desc` is created inside `DEFINE_RAW_FLEX()`
  Right. Thanks for fixing this. The cleanest option then probably is:

	DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx,
		DIV_ROUND_UP(JBD_MAX_CHECKSUM_SIZE,
			     sizeof(*((struct shash_desc *)0)->__ctx)))

									Honza
Gustavo A. R. Silva Nov. 1, 2024, 8:46 p.m. UTC | #6
On 01/11/24 04:15, Jan Kara wrote:
> On Thu 31-10-24 17:31:34, Gustavo A. R. Silva wrote:
>> On 31/10/24 15:32, Jan Kara wrote:
>>>
>>>> `sizeof(ctx) == 4` when `char ctx[JBD_MAX_CHECKSUM_SIZE];`
>>>>
>>>> To maintain the same size, we tell `DEFINE_RAW_FLEX()` to allocate `1`
>>>> element for the flex array, as in 32-bit `sizeof(void *) == 4`.
>>>
>>> So I agree we end up allocating enough space on stack but it is pretty
>>> subtle and if JBD_MAX_CHECKSUM_SIZE definition changes, we have a problem.
>>> I think we need something like (JBD_MAX_CHECKSUM_SIZE + sizeof(*desc->__ctx)
>>> - 1) / sizeof(*desc->__ctx))?
>>
>> I see. Well, in that case it'd be something more like:
>>
>> -       struct {
>> -               struct shash_desc shash;
>> -               char ctx[JBD_MAX_CHECKSUM_SIZE];
>> -       } desc;
>> +       DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx,
>> +                       (JBD_MAX_CHECKSUM_SIZE +
>> +                        sizeof(*((struct shash_desc *)0)->__ctx)) /
>> +                        sizeof(*((struct shash_desc *)0)->__ctx));
>>
>> Notice that `desc` is created inside `DEFINE_RAW_FLEX()`
>    Right. Thanks for fixing this. The cleanest option then probably is:
> 
> 	DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx,
> 		DIV_ROUND_UP(JBD_MAX_CHECKSUM_SIZE,
> 			     sizeof(*((struct shash_desc *)0)->__ctx)))

OK. There you go v2:

https://lore.kernel.org/linux-hardening/ZyU94w0IALVhc9Jy@kspp/

Thanks a lot for the feedback. :)
--
Gustavo
diff mbox series

Patch

diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 8aef9bb6ad57..ce4560e62d3b 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -1796,22 +1796,19 @@  static inline unsigned long jbd2_log_space_left(journal_t *journal)
 static inline u32 jbd2_chksum(journal_t *journal, u32 crc,
 			      const void *address, unsigned int length)
 {
-	struct {
-		struct shash_desc shash;
-		char ctx[JBD_MAX_CHECKSUM_SIZE];
-	} desc;
+	DEFINE_RAW_FLEX(struct shash_desc, desc, __ctx, 1);
 	int err;
 
 	BUG_ON(crypto_shash_descsize(journal->j_chksum_driver) >
 		JBD_MAX_CHECKSUM_SIZE);
 
-	desc.shash.tfm = journal->j_chksum_driver;
-	*(u32 *)desc.ctx = crc;
+	desc->tfm = journal->j_chksum_driver;
+	*(u32 *)desc->__ctx = crc;
 
-	err = crypto_shash_update(&desc.shash, address, length);
+	err = crypto_shash_update(desc, address, length);
 	BUG_ON(err);
 
-	return *(u32 *)desc.ctx;
+	return *(u32 *)desc->__ctx;
 }
 
 /* Return most recent uncommitted transaction */