From nobody Thu Sep 24 16:56:52 2026 Received: from mail-pz2-f12.google.com (mail-pz2-f12.google.com [74.125.228.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0DDA13B2D39 for ; Tue, 22 Sep 2026 05:48:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.228.12 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790056139; cv=none; b=Uc9wkE8lL/fVcSkNNMV55tX62TvMtv/xdOHATJUw+c+pXxGZuFCA9MBVnqB3P/0FktdccMmLsYsCJHkfvT9m5A+By13O0Oiw/oFLABcMXnhAMXAkw3Jc6GMcML86pFrCLemYtRe8TWKkQCSKCHBjmscCkLsMJoBVpSBrrk51FSk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790056139; c=relaxed/simple; bh=GnebkRYN2Yq3glKz9FYmVBvCKtzjN4BYOu13gMAeubI=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=HFBCsGKeMRZpY55Wd6hLDDYXRHaqkb+FbW07Fl+heGpxNwYpgbU0Ed7PAipbV14PtlB0iwucYDLYZW3rLaC0lG/U9TNFpIuZNnk8eTCxXab+gz4N6Qr/9anyquiZkb5uzuPxjOCoOx7HK0uibi2zqOzQ7GIqWwJfLHqCkcFWlZ0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WnP6EGQ2; arc=none smtp.client-ip=74.125.228.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WnP6EGQ2" Received: by mail-pz2-f12.google.com with SMTP id 41be03b00d2f7-cc4aa0f1a94so2603940a12.2 for ; Mon, 21 Sep 2026 22:48:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790056137; x=1790660937; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=3yMlMFl92yRdWmVLrvdNriN9ZvlaK00DMIcQJuB/tCU=; b=WnP6EGQ2NIwrVZCC6nIVuP8tAxmopRWIdbfGWtL9dBuUQL5vanNhZvdWroRNliUqwO r3WGXY3p87BlUKqOKQCSHz/YgG+/ytdjies9gy5LDcxACxDMvbMJEOQWJaT57Ko25M5Y GgZ40KJZA7A248lUuJTknnM1OXhORoTLzy7wib3hbXNPjzJ/OXp+259f4U6rOoPM9QzS jLx21sASuoZIlCr8Hc8PZZv5Hd9bm5CSNdbbs0b2cQzA2GN/a9po7p+8Xf07MlI6sN3N f4nXySKnjCQaE2zqFMx1K07Rg4MxbSpblh0NVijcu/JXuLoX7ij9uCDhJnOjEwiB6wqq pptw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790056137; x=1790660937; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=3yMlMFl92yRdWmVLrvdNriN9ZvlaK00DMIcQJuB/tCU=; b=wQNTWXSyUHWbqlwm+DINWCKoe+OaqtdkDMKycLMyBtficmmn5ayQ+exqucPgvoTwQk hsElvX2vQKBrXeald/0I4JCffZk7boCnCxaVnotmVKivASOSGNivthf7us5NP12NWg4/ KaRZT6QC2ByP74fbkotLoTlMNp66wt/P0ct9XgkT/YvfFNDEiju6qy5NlgCYNbR47yQo qTkvjzGHeA3Ee3Fz1XEoid3rD8jWAQz7fX168dED4lA6vcoO2GhOu3iYtX+Riih/fsOc bxmcs68DahDCS2xKPtetYOlTqQCOvxv38oJW4KvrYT90Ws5yzgc1bSfYxjBSAzFXx1mA 37RQ== X-Forwarded-Encrypted: i=1; AKwUvBwPvhvGMvmxZa4OadAIGnKAkKYmzOIDUdR621k+d00Ciu+iWRS3Dw7zOY/iTFNCPQlIbKLCxKI016VDM5Y=@vger.kernel.org X-Gm-Message-State: AFuF++lCGG9CqUUwwgmRjbkQP89CkMTc9F6D62KNMI1SrtKxGuI91FNK +SuuTEEVwH0/TuS/h+n3GTuTrjUxZ3Qotn8B4aCI3ShBULVBU7FMpRXo X-Gm-Gg: AYBFou3N6pKLslA/5a/uL7oZah4NyYBldLxe7KT0k44rEwxsJPl7t5CpdFVtMvpOL73 6VE4OMfGXLL+pug493hocjZ/ayFTVPhJMk61l5616HWADmy+iSEl7Fib34bTzqtbpybT0tt186j xGtQt2CQslte27VKqj8U0ivXv9CatNlJhV8NrG8QOgQ/hMA8nFvNOZJ0hTGHgT4yyp5O9DWCpDV fz7EtCy2/8ISrQF0TbyG0odAr/qyBMRsYxvsxpZlLFfqormhriqxaYfE+1vjv/9lYgdoPiH4CtA XXC/+OGSacS84wj2KR7cPKSX6yFCvJ6xbz8fe/S557a2jliQkhq+yRkHcGp6vDzst67qKHkoyJ3 rpfOPf4YisPAPGPTUA5onW2VR0xok7wC/yPeV0pQwtzfI+SNu/p2zVTQBSr54O9ZmE4l+Lkm/CH bwJIW+nGzXxyc+eQEd6DE9JGTjJORSyysuovFtbm6/ymCGCfCQH5WrtDIhKkvmC3K01SDFZpsw5 YF9FRlshCjpL6VPWzvN3KyVz33ZhgXvY4QrnIrAPcmkck8gZW1vdS8eEW9dBqiryKSF3oQKyeYv wySZtRy0AwfN2W1m6ATWAjxiarUYYtuW6Uzg9B004rWAkY1DYWVxh66LW8RgJWjZvlwREUmIjA= = X-Received: by 2002:a17:90b:1fc3:b0:39e:6a81:5a96 with SMTP id 98e67ed59e1d1-3a073295901mr55758a91.42.1790056136975; Mon, 21 Sep 2026 22:48:56 -0700 (PDT) Received: from spider.bream-herring.ts.net ([103.252.203.158]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3a06e5a5eb4sm1372783a91.14.2026.09.21.22.48.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Sep 2026 22:48:56 -0700 (PDT) From: Matthias Goergens To: Jan Kara Cc: Christian Brauner , Yichong Chen , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] isofs: advance to the next block when a record ends at the block end Date: Tue, 22 Sep 2026 13:48:53 +0800 Message-ID: <20260922054853.469681-1-matthias.goergens@gmail.com> X-Mailer: git-send-email 2.55.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Since commit b2eb2e288604 ("isofs: Drop support of directory entries straddling blocks") some ISO 9660 images list incomplete directories: find returns fewer entries than before, and some of the names readdir does return cannot be looked up. The log fills with iso9660: Corrupted directory entry in block 0 of inode 55232 and on some images the walk reads a byte past the end of a buffer: BUG: KASAN: use-after-free in isofs_readdir+0x93b/0xc40 Affected are images with a directory record ending exactly at the end of a logical block, which ECMA-119 allows and current tools produce. On the Debian 13.7.0 amd64 DVD-1, which has three, find returns 9163 entries instead of 9461: https://cdimage.debian.org/debian-cd/13.7.0/amd64/iso-dvd/debian-13.7.0-a= md64-DVD-1.iso The KASAN report is from a shareware CD with one in its root directory: https://archive.org/download/simtel-1-0295/SIMTEL1_0295.ISO A local one, which lists 46 of its 65 files: mkdir tree for i in $(seq -f '%04g' 1 65); do echo hi > tree/FILE$i.TXT; done xorrisofs -iso-level 1 -o boundary.iso tree/ genisoimage pads the tail of a block instead of filling it exactly, so its images have no such records. That commit removed the reassembly of records crossing a block boundary. Its condition was "offset >=3D bufsize", so it also handled a record ending exactly at the end (offset =3D=3D bufsize): drop the buffer, increment the block, reset the offset. Nothing does that now, so do_isofs_readdir() and isofs_find_entry() read the next record's length byte from bh->b_data + bufsize, one past the buffer. Depending on that byte the walk either treats the rest of the block as padding and skips the next block of entries, or fails the record as corrupt and stops. Straddling records stay rejected: isofs_dir_record_valid() fails them because their length exceeds the remaining space, which is what that commit relied on. One ending exactly at the end fits in its block and is accepted, so it is the advance, not the reassembly, that has to come back. Do it at the top of the loop: do_isofs_readdir() reaches the next iteration from the multi-extent branch, "." and "..", the hidden/associated skip (showassoc is off by default, so no mount option is needed) and the fall-through, and all of them need covering. The record was validated to end within the block, so offset never exceeds bufsize. Fixes: b2eb2e288604 ("isofs: Drop support of directory entries straddling b= locks") Signed-off-by: Matthias Goergens --- Not tagged for stable: b2eb2e288604 is in 7.3-rc1..rc3 and has not appeared in a released kernel. Validated under qemu with KASAN and UBSAN against the images above, using a kernel built from the commit before b2eb2e288604 as the reference for correct behaviour. do_isofs_readdir(), isofs_find_entry() and isofs_read_level3_size() all open-code this same block-end transition. Happy to follow up with a helper that shares it, kept out of here to keep the regression fix minimal. fs/isofs/dir.c | 12 ++++++++++++ fs/isofs/namei.c | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index c7ca7603e97a..00a609c901dd 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -104,6 +104,18 @@ static int do_isofs_readdir(struct inode *inode, struc= t file *file, while (ctx->pos < inode->i_size) { int de_len; =20 + /* + * The previous record was validated to end within its + * block; if it ended exactly at the end, the next record + * starts at the beginning of the next block. + */ + if (offset =3D=3D bufsize) { + brelse(bh); + bh =3D NULL; + block++; + offset =3D 0; + } + if (!bh) { bh =3D isofs_bread(inode, block); if (!bh) diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 010682f5901a..5f5ed36d12e3 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -68,6 +68,18 @@ isofs_find_entry(struct inode *dir, struct dentry *dentr= y, int de_len, match, i, dlen; char *dpnt; =20 + /* + * The previous record was validated to end within its + * block; if it ended exactly at the end, the next record + * starts at the beginning of the next block. + */ + if (offset =3D=3D bufsize) { + brelse(bh); + bh =3D NULL; + block++; + offset =3D 0; + } + if (!bh) { bh =3D isofs_bread(dir, block); if (!bh) --=20 2.55.0