mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-12 06:57:57 +04:00
mtd: validate trx->len in trx_fixup()
trx_fixup() computed the CRC32 range from the on-flash TRX header
without validating it:
scan = ptr + offsetof(struct trx_header, flag_version);
trx->crc32 = crc32buf(scan, trx->len - (scan - ptr));
trx->len is read from the mmap()ed partition and is only sanity checked
in trx_check(), which is a separate entry point. A trx->len larger than
the partition therefore makes crc32buf() walk that many bytes past the
end of the mapping and crash mtd with SIGSEGV.
The mirror case of a trx->len below the 12 byte offset does not overread
in practice: crc32buf() takes a size_t but passes it to crc32(), which
takes an int len and loops on "while (--len >= 0)". The wrapped value
truncates to a negative int, so the loop body never runs and a zero
length CRC32 is written instead. Values at or above 0x8000000c truncate
the same way. Only the range from sizeof(struct trx_header) to roughly
0x8000000b stays positive through the truncation and reads out of
bounds, which is exactly the range a plausible bad length falls into.
Bound trx->len on both sides before computing the range, using the same
lower limit trx_check() already applies. Both comparisons are unsigned,
so the wrapping cases are rejected as well.
trx_fixup() runs as root on the contents of the flash, so this is a
robustness fix rather than a privilege boundary: it is reachable through
"mtd jffs2write" and the jffs2_replaced path of "mtd write", not through
"mtd fixtrx", which uses mtd_fixtrx() and derives its length from
erasesize instead. The practical benefit is not crashing on a truncated
or corrupted header during sysupgrade.
Link: https://github.com/openwrt/openwrt/security/advisories/GHSA-wch3-f5gc-mw2h
Reported-by: @tonoyx91
Reported-by: @0xROI
Fixes: bbd9eb4669 ("clean up mtd, fix up trx header when integrating jffs2 data on broadcom devices")
Assisted-by: Claude:claude-opus-5
Link: https://github.com/openwrt/openwrt/pull/25284
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
1 parent
83c18c360e
commit
e056c32ed0
2 files changed
+6
-1
No files matched your search
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=mtd
|
||||
PKG_RELEASE:=28
|
||||
PKG_RELEASE:=29
|
||||
|
||||
PKG_BUILD_DIR := $(KERNEL_BUILD_DIR)/$(PKG_NAME)
|
||||
STAMP_PREPARED := $(STAMP_PREPARED)_$(call confvar,CONFIG_MTD_REDBOOT_PARTS)
|
||||
|
||||
@@ -97,6 +97,11 @@ trx_fixup(int fd, const char *name)
|
||||
goto err2;
|
||||
}
|
||||
|
||||
if (trx->len < sizeof(struct trx_header) || trx->len > len) {
|
||||
fprintf(stderr, "Invalid TRX header length: %u\n", trx->len);
|
||||
goto err2;
|
||||
}
|
||||
|
||||
scan = ptr + offsetof(struct trx_header, flag_version);
|
||||
trx->crc32 = crc32buf(scan, trx->len - (scan - ptr));
|
||||
msync(ptr, sizeof(struct trx_header), MS_SYNC|MS_INVALIDATE);
|
||||
|
||||
Reference in new issue
Block a user