ubifs_scan_a_node() validates the padding length of a UBIFS_PAD_NODE with: if (pad_len < 0 || offs + node_len + pad_len > c->leb_size) offs, node_len and pad_len are all signed 32-bit ints, so the sum can overflow. ubifs_check_node() has already bounded node_len (28 bytes for a pad node) and guarantees offs + node_len <= c->leb_size, but pad_len is taken straight from the image. With offs = 0x20 and pad_len = 0x7fffffc4: offs + node_len + pad_len = 0x80000000 (INT_MIN) -> passes the check node_len + pad_len = 0x7fffffe0 (positive, 8-byte aligned) so the following alignment check also passes and ubifs_scan_a_node() returns 0x7fffffe0. ubifs_scan() then does offs += ret, buf += ret and len -= ret, leaving buf 2 GiB past the scan buffer and len negative. The trailing empty-space loop (for (; len; offs++, buf++, len--)) dereferences buf and faults on unmapped memory: BUG: unable to handle page fault for address: ff799130402f9000 #PF: supervisor read access in kernel mode RIP: 0010:ubifs_scan+0x24f/0x2a0 Call Trace: ubifs_replay_journal+0x13e/0x18a0 ubifs_get_tree+0x5f7/0x2410 vfs_get_tree+0x2a/0x100 path_mount+0x36d/0xcf0 __x64_sys_mount+0x12b/0x160 On an unclean image the same wrapped length reaches ubifs_recover_leb(), where clean_buf() computes c->leb_size - empty_offs with empty_offs == INT_MIN; this sign-extends to a huge size_t and the following memset(*buf, 0xff, ...) writes out of bounds. In practice the read fault above is hit first. Bound pad_len by the remaining space instead: pad_len > c->leb_size - offs - node_len offs + node_len <= c->leb_size already holds after ubifs_check_node(), so the right-hand side cannot underflow, and the comparison no longer depends on a sum that can overflow. Built and boot-tested on Linux 7.4.0-rc1 under QEMU with nandsim (128 MiB Samsung, 128 KiB PEB, 2 KiB page). On the unpatched kernel, mounting the crafted image oopses in ubifs_scan(); with the fix the pad node is rejected ("bad pad node at LEB 3:32") and mount fails cleanly with -EUCLEAN, while a normally-built UBIFS image still mounts and scans without error. Fixes: 1e51764a3c2a ("UBIFS: add new flash file system") Cc: stable@vger.kernel.org Signed-off-by: Mark Payne --- fs/ubifs/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c index cbff2d800e27..441b2f04a0ae 100644 --- a/fs/ubifs/scan.c +++ b/fs/ubifs/scan.c @@ -86,7 +86,7 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum, /* Validate the padding node */ if (pad_len < 0 || - offs + node_len + pad_len > c->leb_size) { + pad_len > c->leb_size - offs - node_len) { if (!quiet) { ubifs_err(c, "bad pad node at LEB %d:%d", lnum, offs); -- 2.43.0