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)
next prev 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