Thread (5 messages) flat view 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: Alexey Dobriyan <hidden>
Date: 2025-02-06 17:06:59
Also in: kernel-janitors, lkml

On Thu, Jan 30, 2025 at 07:15:15PM +0300, Dan Carpenter wrote:
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.
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.

Of course one bug could be fixed in multiple ways.
If you look at integer overflows with security implications there is a
5 to 1 ratio of bugs that only affect 32-bit vs bugs that affect
everything because it's just so much easier to overflow a 32-bit size.

aab98e2dbd64 ("ksmbd: fix integer overflows on 32 bit systems")
16ebb6f5b629 ("nfp: bpf: prevent integer overflow in nfp_bpf_event_output()")
09c4a6101532 ("rtc: tps6594: Fix integer overflow on 32bit systems")
55cf2f4b945f ("binfmt_flat: Fix integer overflow bug on 32 bit systems")
fbbd84af6ba7 ("chelsio/chtls: prevent potential integer overflow on 32bit")
bd96a3935e89 ("rdma/cxgb4: Prevent potential integer overflow on 32bit")
d0257e089d1b ("RDMA/uverbs: Prevent integer overflow issue")
This one is good demonstration why BAO is better:
https://godbolt.org/z/14ofdfvhc
3c63d8946e57 ("svcrdma: Address an integer overflow")
7f33b92e5b18 ("NFSD: Prevent a potential integer overflow")
quoted
	int len;
	if (__builtin_mul_overflow(replay_esn->bmp_len, 4, &len)) {
		return true;
	}
	if (__builtin_add_overflow(len, sizeof(*replay_esn), &len)) {
		return true;
	}
This is so ugly...  :/  I'd prefer to just do open code the check at
that point.

static inline int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay_esn)
{
	if (replay_esn->bmp_len > (INT_MAX - sizeof(*replay_esn)) / sizeof(__u32))
		return -EINVAL;
	return sizeof(*replay_esn) + replay_esn->bmp_len * sizeof(__u32);
}
You can't open code if you have something like this:

	X = a * b + c;

Second, the code is now effectively duplicated, once in overflow check,
second time in actual calculation.

BAO and BMO may look chatty but they're doing the right thing.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help