Thread (9 messages) 9 messages, 2 authors, 6d ago

Re: [PATCH v6 3/4] kallsyms: delta-compress lineinfo tables for ~2.7x size reduction

From: sashiko-bot@kernel.org
Date: 2026-07-06 14:40:37

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] lineinfo_read_sleb128 contains a signed left shift that can overflow on malformed or large data, triggering a UBSAN splat in NMI/panic contexts.
--

commit 3756e632dbdf4d6db79f0e2c8a39f6103ac6e8ad
Author: Sasha Levin [off-list ref]

kallsyms: delta-compress lineinfo tables for ~2.7x size reduction

This patch replaces the flat uncompressed parallel arrays for lineinfo with a
block-indexed, delta-encoded, ULEB128/SLEB128 varint compressed format to
significantly reduce size. Entries are grouped into blocks of 64 and decoded
entirely on the stack to ensure safety during NMI or panic contexts.
quoted hunk ↗ jump to hunk
diff --git a/include/linux/mod_lineinfo.h b/include/linux/mod_lineinfo.h
index 9cda3263a0784..a3c7143433020 100644
--- a/include/linux/mod_lineinfo.h
+++ b/include/linux/mod_lineinfo.h
[ ... ]
+/* Read an SLEB128 varint. Same safety guarantees as above. */
+static inline int32_t lineinfo_read_sleb128(const u8 *data, u32 *pos, u32 end)
+{
+	int32_t result = 0;
+	unsigned int shift = 0;
+	u8 byte = 0;
+
+	while (*pos < end) {
+		byte = data[*pos];
+		(*pos)++;
+		result |= (int32_t)(byte & 0x7f) << shift;
[Severity: High]
Can this signed left shift trigger a UBSAN splat on malformed or large data?

For the 5th byte of an SLEB128 varint, shift will be 28. If the decoded byte
has a value greater than 7 (e.g. 0x7F), 127 << 28 evaluates to 3409130496,
which exceeds INT32_MAX.

Since left-shifting into or past the sign bit of a signed integer is
undefined behavior in C, a corrupted or maliciously crafted .mod_lineinfo
section could trigger a CONFIG_UBSAN_SHIFT splat.

If this function is called by lineinfo_search() during an NMI or panic
context, would the resulting UBSAN splat attempt to take locks and call
printk, potentially causing a deadlock or nested panic?

Perhaps the shift should be performed as unsigned:
result |= (int32_t)((u32)(byte & 0x7f) << shift);
+		shift += 7;
+		if (!(byte & 0x80))
+			break;
+		if (shift >= 32) {
+			while (*pos < end && (data[*pos] & 0x80))
+				(*pos)++;
[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260706142914.2398993-1-sashal@kernel.org?part=3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help