Thread (5 messages) 5 messages, 2 authors, 2025-03-07

Re: less size_t please (was Re: [PATCH net] xfrm: fix integer overflow in xfrm_replay_state_esn_len())

From: Dan Carpenter <hidden>
Date: 2025-03-07 13:43:45
Also in: kernel-janitors, lkml

On Thu, Feb 06, 2025 at 08:06:55PM +0300, Alexey Dobriyan wrote:
On Thu, Jan 30, 2025 at 07:15:15PM +0300, Dan Carpenter wrote:
quoted
On Thu, Jan 30, 2025 at 04:44:42PM +0300, Alexey Dobriyan wrote:
quoted
quoted
-static inline unsigned int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay_esn)
+static inline size_t xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay_esn)
 {
-	return sizeof(*replay_esn) + replay_esn->bmp_len * sizeof(__u32);
+	return size_add(sizeof(*replay_esn), size_mul(replay_esn->bmp_len, sizeof(__u32)));
Please don't do this.

You can (and should!) make calculations and check for overflow at the
same time. It's very efficient.
quoted
1) Use size_add() and size_mul().  This change is necessary for 32bit systems.
This bloats code on 32-bit.
I'm not sure I understand.  On 32-bit systems a size_t and an unsigned
int are the same size.  Did you mean to say 64-bit?
It looks like yes.
quoted
Declaring sizes as u32 leads to integer overflows like this one.
No, the problem is unchecked C addition and mixing types which confuses
people (in the opposite direction too -- there were fake CVEs because
someone thought "size_t len" in write hooks could be big enough).

The answer is to use single type as much as possible and using checked
additions on-the-go at every binary operator if possible.
In the write_hooks examples, we fixed those by moving to size_t.

64bit types are safer because 2**64 is a superset of 2**32.  Anything
which can overflow 64bits can overflow 32bits.  So obviously 64bits is
safer.

But it's surprising the extent of it.  We avoid using ulong types in
UAPI because it's a headache for 32bit support.  So normally we get
an u32 number_items from the user.  That's 4 billion.  It's a small
number and it's actually pretty hard for it to lead to an integer
overflow on 64bit systems.  The struct_size() function is basically
not needed if you're on 64bit and you declare your length variables as
size_t.

The rest of the kernel has an assumption that sizes are saved in size_t.
The size_add() and struct_size() macros rely on it.  In networking there
are a number of functions like sock_kmalloc() which truncate the size
parameter to int and they just make me itch to look at.

regards,
dan carpenter
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help