From nobody Tue Dec 2 00:25:34 2025 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (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 7032F2BDC14 for ; Mon, 24 Nov 2025 17:28:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764005302; cv=none; b=HtsJhnhMhYh2uIs2cWSFoIiP1HDtjI8JgNfcJpjeeSMhx4XSLFWo4TEKT8VIi5o/zCqAfI+uHlK+w4qQzpujLz7Prafn+OgR2zJkLSah9W0JAsElGFoXZkOL9AxUolle1NO8BWwmEPC/uZsJGZgfP76vDKe9cvMNcNdNJ4jgvgk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764005302; c=relaxed/simple; bh=3oH/wAdy55TtrwLg5CcQw140ZRAqpfNOOtj3sU8BhII=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=PgxGzaj0eNG+pknhRqtaschbcogz5YEFyP1VBNijoDW+Ij5SMbO8z4XxTgFm6MlJ7sZ5mch1x2zd+YkpPKh/ruHR0KGwoB5Ewj/1ljB0Z0MGmrJXrdz72ViDscP5G/YsWDMNSrbdPDuaTOyf2nEhEhZGTO0FiU1lf3TKuXkTbsY= 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=E1I1gbpy; arc=none smtp.client-ip=209.85.221.53 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="E1I1gbpy" Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-429ce7e79f8so2623714f8f.0 for ; Mon, 24 Nov 2025 09:28:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764005299; x=1764610099; 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; bh=3J1OuptE+eXhtOMpZOrEy7V0/XXBCdvwVjX11ZxUQz0=; b=E1I1gbpy47nkdJIL6XhroKF/kG2vpQ0+CKcwofmDB1ddlTnnrkowo89VcdRRE2Rfbj RoFYT7jW+DmPiBpOUtVppOV26ItR0Gcrt8gxyeO3T8i/U1ga3nCE/TK/darksiF9Rhfm /SS/mhjwe2cQK4XVyOcxf8umSUNBJ14e7YNteGCGoWKIo9WL7FoFLjMbypXtpsXFP/qF +PEpItsvAa/khzzItU2u4WuAOMA0zpZDLuY14fkG5QDqPoBwS4nLdEWyzCEEJwO61Y4X Xo6afsCSQCnaDD+A4d0vkQ3wQHVLDO/5Ufz0fam8ZOj+oGOYamIUyPVwWQEFHr3OoTR3 r/oA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764005299; x=1764610099; 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; bh=3J1OuptE+eXhtOMpZOrEy7V0/XXBCdvwVjX11ZxUQz0=; b=KeKCnuapMEvVVZM4Cur+KBeeYp0u2xe8qK29L03AQEHGzO5t3yowr4H8Q4aEGuUGKn 6v5g8F3OgCeC4RCtZaLcS1vREBG7Ur5zLWcg3sAgYQf9lg77I0kr0vOu/LuEoHL5pKB/ 6wjWrDr+PPt+WbVqMs1t48iSHfvPD4f/x9AidFAzG4HrMBPKeQhWan5PLB22SQZOYkPg /5NviEYUZeEpielYasZWy9WJYH5j5myO+owuWEzqhRk0+lMaj9TxxE24k4qJHaVoKUTB 6hME+CR9beyyaJCqlRUUAM6neYj69Gx6scBKnrgC9GeeJmeNnVfcyBAHLmuH2qa60fd7 l70A== X-Gm-Message-State: AOJu0Yz572eVVHcFENKkLUPESrbFxkd66EpPAOKWEcJRcZWkgoBgzqYk dWjLMNWIHzNt6q+TXYVoCuBe9CUHUk2PG9iycSJcqSZrRrSJkkrbL0aw X-Gm-Gg: ASbGncsWVhgrgyMPM/IO1Cv5V0MSzIzgaKbjHL5cELP5cJKC8X67j9+2iUFlWFJGtDW Revl1kVNYxehhC0E+Ho+gFGNqJW6MIXKqVCJgTyRzWMNmpkVZOqfzNONaozyax2m/sLPoUQ3QGO lazt4VQRlSgBT8pt49zCt7HIHUnQ1OWNN3SQLgs76UFWUrnMhiZ9Q865xm4RdmKZj5mqotnNJ4u RX+oeg+CRZC1ZPFKbmxWEKRuehT6yihsLUbbs5jaEKz9fXhnZmagJAN8bS3/k/icHjs7ni1+u/H Or0y9fv+xZq2oGqFDxwzVydbfYuHRW7ArwiIB6hq0lXxQjFybNWgVZC/F0AHr0nUA4pJEBIU9sM mmZH7YpPOKxuny4vdCK2CcPOe0YT93GmrQi21+JrJWcC+5+AXgNKCwaVe5f7L6jCiRhIx8bv3X7 8cSevEMySYvbJtJjm9sZzhdw== X-Google-Smtp-Source: AGHT+IFYcHtKnTQuGnZVQa/KwkYM+ou4ckUgNPHvgqeID7aDViND63oKXSIlG5aX5GpVhrDgW43P8w== X-Received: by 2002:a5d:5888:0:b0:42c:a449:d6a5 with SMTP id ffacd0b85a97d-42cc1d27b05mr12919046f8f.34.1764005298543; Mon, 24 Nov 2025 09:28:18 -0800 (PST) Received: from localhost.localdomain ([46.10.223.24]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fa35c2sm28315690f8f.25.2025.11.24.09.28.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Nov 2025 09:28:18 -0800 (PST) From: "Nikola Z. Ivanov" To: aivazian.tigran@gmail.com Cc: linux-kernel@vger.kernel.org, skhan@linuxfoundation.org, david.hunter.linux@gmail.com, khalid@kernel.org, linux-kernel-mentees@lists.linuxfoundation.org, "Nikola Z. Ivanov" , syzbot+f51a2a34984e4d8888fd@syzkaller.appspotmail.com Subject: [PATCH] bfs: Fix calculation of offset when moving blocks Date: Mon, 24 Nov 2025 19:28:15 +0200 Message-ID: <20251124172815.100111-1-zlatistiv@gmail.com> X-Mailer: git-send-email 2.51.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" bfs_move_blocks performs an incorrect calculation when looping over the blocks that are to be moved. When looping over the section of blocks: for (i =3D start; i <=3D end; i++) if(bfs_move_block(i, where + i, sb)) { Here bfs_move_block will not move blocks "start"-"end" to "where"-"where+size" but instead it will add "i" (which is initialized to "start") to "where", adding additional unintended offset. Example reproducer of the bug: dd if=3D/dev/zero of=3D./bfs.img count=3D200 bs=3D1M mkfs.bfs ./bfs.img losetup /dev/loop0 ./bfs.img mount /dev/loop0 /mnt dd if=3D/dev/urandom of=3D/mnt/file0 count=3D75 bs=3D1M dd if=3D/dev/urandom of=3D/mnt/file1 count=3D25 bs=3D1M dd if=3D/dev/urandom of=3D/mnt/file2 count=3D25 bs=3D1M echo 123 >> /mnt/file1 Essentially this will create 3 files, file1 located right between file0 and file2 on-disk. Writing more data to file1 will cause bfs to attempt to move it after file2, where we have enough space to store it, but due to the incorrect calculation it will attempt to move it past the end of device and trigger a NULL pointer dereference in bfs_move_block. Even if we have enough space to account for the unintended offset, the content of file1 will now be garbage due to bfs_get_block expecting file1 to be right after file2. For example: dd if=3D/dev/zero of=3D./bfs.img count=3D200 bs=3D1M mkfs.bfs ./bfs.img losetup /dev/loop0 ./bfs.img mount /dev/loop0 /mnt dd if=3D/dev/urandom of=3D/mnt/file0 count=3D1 bs=3D512 dd if=3D/dev/urandom of=3D/mnt/file1 count=3D1 bs=3D512 dd if=3D/dev/urandom of=3D/mnt/file2 count=3D1 bs=3D512 sync; echo 1 > /proc/sys/vm/drop_caches xxd /mnt/file1 echo 123 >> /mnt/file1 sync; echo 1 > /proc/sys/vm/drop_caches xxd /mnt/file1 The hexdump reveals that our file now contains zeroes, except for the "123\n" we echoed at the end. Fix this by correcting the calculation. Additionally add a check for new =3D=3D NULL inside bfs_move_block and propagate the return value of bfs_move_block as a return value of bfs_move_blocks in case of error. Reported-by: syzbot+f51a2a34984e4d8888fd@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3Df51a2a34984e4d8888fd Signed-off-by: Nikola Z. Ivanov --- The example reproducers might trigger a WARNING() in mark_buffer_dirty, which is observed often when blocks are moved around, syzbot has already hit that bug here: https://syzkaller.appspot.com/bug?extid=3D2327bccb02eef9291c1c I will follow up with a patch for that soon. fs/bfs/file.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/fs/bfs/file.c b/fs/bfs/file.c index d33d6bde992b..649105018014 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -40,6 +40,10 @@ static int bfs_move_block(unsigned long from, unsigned l= ong to, if (!bh) return -EIO; new =3D sb_getblk(sb, to); + if (!new) { + brelse(bh); + return -EIO; + } memcpy(new->b_data, bh->b_data, bh->b_size); mark_buffer_dirty(new); bforget(bh); @@ -51,14 +55,17 @@ static int bfs_move_blocks(struct super_block *sb, unsi= gned long start, unsigned long end, unsigned long where) { unsigned long i; + int err; =20 dprintf("%08lx-%08lx->%08lx\n", start, end, where); - for (i =3D start; i <=3D end; i++) - if(bfs_move_block(i, where + i, sb)) { - dprintf("failed to move block %08lx -> %08lx\n", i, - where + i); - return -EIO; + for (i =3D 0; i <=3D end - start; i++) { + err =3D bfs_move_block(start + i, where + i, sb); + if (err) { + dprintf("failed to move block %08lx -> %08lx\n", + start + i, where + i); + return err; } + } return 0; } =20 --=20 2.51.0