public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: David Laight <David.Laight@ACULAB.COM>
To: 'Vincent MAILHOL' <mailhol.vincent@wanadoo.fr>
Cc: Kees Cook <kees@kernel.org>,
	"Gustavo A . R . Silva" <gustavoars@kernel.org>,
	"linux-hardening@vger.kernel.org"
	<linux-hardening@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: RE: [PATCH v2] overflow: optimize struct_size() calculation
Date: Wed, 11 Sep 2024 16:46:51 +0000	[thread overview]
Message-ID: <43ac488d0a83486ca6d969643c7b531d@AcuMS.aculab.com> (raw)
In-Reply-To: <CAMZ6Rq+6EKoFEHMZhp_2dq2DPEP6zZgzDy0M3tegKK9wOphA6g@mail.gmail.com>

...
> > [1] Both the '+' and '*' have extra code to detect overflow and return
> >   a 'big' value that will cause kmalloc() to return NULL.
> > I've not looked at the generated code but it is likely to be horrid
> >   (especially the check for multiply overflowing).
> > In this case there are enough constants that the alternative check:
> >         if (count > (MAX_SIZE - sizeof (*s)) / sizeof (s->member))
> >                 size = MAX_SIZE;
> >         else
> >                 size = sizeof (*s) + count * sizeof (s->member);
> > is fine and only has one conditional in it.
> > In some cases the compiler may already know that the count is small enough.
> 
> Indeed. If count is small enough, the code isn't that horrid. If I
> take this example:
> 
>   size_t foo(u32 count)
>   {
>           return struct_size_t(struct s, fam, count);
>   }
> 
> I got this code:

What happens if the flex-array is larger than 1 byte - so a multiply is needed.
Probably worth testing something that isn't a power of 2.
Also check 32bit archs -godbolt can help.

	David

> 
>   0000000000000010 <foo>:
>     10:   f3 0f 1e fa             endbr64
>     14:   89 f8                   mov    %edi,%eax
>     16:   48 83 c0 10             add    $0x10,%rax
>     1a:   e9 00 00 00 00          jmp    1f <foo+0xf>

Add -d to objdump to get the relocation printed.
(I think this is a build where 'ret' isn't allowed :-)

	David

> 
> Here, no SIZE_MAX because the multiplication can not wraparound
> regardless of the value of count. It is only after changing the type
> of count to u64 that the compiler will emit a comparison:
> 
> 0000000000000010 <foo>:
>   10:   f3 0f 1e fa             endbr64
>   14:   48 8d 47 10             lea    0x10(%rdi),%rax
>   18:   48 83 ff f0             cmp    $0xfffffffffffffff0,%rdi
>   1c:   48 c7 c2 ff ff ff ff    mov    $0xffffffffffffffff,%rdx
>   23:   48 0f 43 c2             cmovae %rdx,%rax
>   27:   e9 00 00 00 00          jmp    2c <foo+0x1c>
> 
> For reference, this is the code after applying my patch, with count as a u32:
> 
>   0000000000000010 <foo>:
>     10:   f3 0f 1e fa             endbr64
>     14:   89 f8                   mov    %edi,%eax
>     16:   ba 10 00 00 00          mov    $0x10,%edx
>     1b:   48 83 c0 0c             add    $0xc,%rax
>     1f:   48 39 d0                cmp    %rdx,%rax
>     22:   48 0f 42 c2             cmovb  %rdx,%rax
>     26:   e9 00 00 00 00          jmp    2b <foo+0x1b>
> 
> and with count as a u64:
> 
>   0000000000000010 <foo>:
>     10:   f3 0f 1e fa             endbr64
>     14:   48 83 c7 0c             add    $0xc,%rdi
>     18:   72 11                   jb     2b <foo+0x1b>
>     1a:   b8 10 00 00 00          mov    $0x10,%eax
>     1f:   48 39 c7                cmp    %rax,%rdi
>     22:   48 0f 43 c7             cmovae %rdi,%rax
>     26:   e9 00 00 00 00          jmp    2b <foo+0x1b>
>     2b:   48 83 c8 ff             or     $0xffffffffffffffff,%rax
>     2f:   e9 00 00 00 00          jmp    34 <foo+0x24>
> 
> Thank you for your comments!
> 
> 
> Yours sincerely,
> Vincent Mailhol

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

  parent reply	other threads:[~2024-09-11 16:47 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-10  2:49 [PATCH v2] overflow: optimize struct_size() calculation Vincent Mailhol
2024-09-11  0:36 ` Kees Cook
2024-09-11  4:45   ` Vincent MAILHOL
2024-09-11 10:22 ` David Laight
     [not found]   ` <CAMZ6Rq+6EKoFEHMZhp_2dq2DPEP6zZgzDy0M3tegKK9wOphA6g@mail.gmail.com>
2024-09-11 16:46     ` David Laight [this message]
2024-09-13  4:45       ` Vincent Mailhol

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=43ac488d0a83486ca6d969643c7b531d@AcuMS.aculab.com \
    --to=david.laight@aculab.com \
    --cc=gustavoars@kernel.org \
    --cc=kees@kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mailhol.vincent@wanadoo.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox