From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f53.google.com (mail-pj1-f53.google.com [209.85.216.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 629C33BED38 for ; Wed, 1 Jul 2026 21:57:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.53 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782943027; cv=none; b=j0YJGo9bAvEqxPML9YIZQ6OKTjuT7Vt0uzxY6387u7mVxJgzoWNYxBVw45JKAWZYNbsKsVMXUgDK7py5Xm7TPBITMBc4+ZlciNNMayKfgg5nbjpSkoQAMuAktUk/Qd1IQtRh5EefYQAw598Q84ItElbcMfM0gxqaYk00Hrb/S7Q= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782943027; c=relaxed/simple; bh=KPumDn2GjdQPm0LS5/sSuBsslzZOMkK8+3ZwIlhCdKw=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=hL4I1nQ6l4GKwqPNAnrl4ijcjyNvdkPHdCVI+V8syHrbqUYy+A/bX1U/pnB/VdfinfJup2nkvHzG6sfKZXAmeaTtqiYdZTzMCDir34kvFwo3x1mwdZ+x2ibTNhxQk36/EUiDPUSrTY0c4fQzD7vRwxrkHsXJP895z64IMz7DMBs= 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=g0yo3eQ5; arc=none smtp.client-ip=209.85.216.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="g0yo3eQ5" Received: by mail-pj1-f53.google.com with SMTP id 98e67ed59e1d1-37d55e8d3e3so862583a91.0 for ; Wed, 01 Jul 2026 14:57:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1782943024; x=1783547824; 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=KzF4tC59yWjJERniX/8DDZTIMRVB2I0lDsDT4R0DPyM=; b=g0yo3eQ5J0xqN3V30t6bQFyOOuyw69VW8yQiumVc8tSRrSjqghlQvlOlZUyRCdHtBx 3noxxKuv6ucwwaHPTy03B+XA5F+IQqdRyysZcvUY8Jd9EM3kUZHSFwppBGQ0XAQ2ww+C Ei6Azn3t9V5Z77sK4eTknoxvF67dI2O+2+hYXFxLShZCzVV/SoXYZEfzqqE+f14Udhp0 xMvhpznbNM5oP1rtjHjkAok7/lRSzISru2bj0Dxb6+UXxWrtpUmJc6qUmnlOB1GyUUt4 tKm/VhJAYQa9+u0fQdtDSZeMO3PjF8n99IPeJqgNs5lbIfDInOoHXPgJVzReQZEb9v7S 2Rwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782943024; x=1783547824; 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=KzF4tC59yWjJERniX/8DDZTIMRVB2I0lDsDT4R0DPyM=; b=SYzRIM3UbgJHbrpXigHcIFt6+os2JOIKhfcpxSjKUXAGXSPed8U42obXDUBCVOF5PM ZL4SknwGn5Gw+WQZs29WmTUo0YaYhzQYcHWTC133JTRwxYJC24VX647HO9Y5jw4y1pRg QnBCBw8O4DJn+6znGEs4pcYeq4K3hYq8s/fqPlIZcdTu5u4Cfe2zZHIypg2KnNCUVd5S zgpnQPLt46M9IE6UmDGD2cdbrEldRLM/csuGnJwJyIN0YDhmAld+E+AZdD/P1dHVFIAC A+PPX0wfG+wSHQ5DOjPXig5WbFD+BnUZR7HrPjdvrhbrbzlNhi6pizMsHotxvgXjR8IV YWJw== X-Forwarded-Encrypted: i=1; AHgh+RqOM0xs6Pe3i5C67N55YfHAUXn8J2YBO7W2r/VDQF4WBYlrOU1l9drRWxPPRr2lWyDnYd5f+Zmqrs2ieq0=@vger.kernel.org X-Gm-Message-State: AOJu0YwDOtpNF5CPTPTZmHIkE8dWnJrYv5C8/NXB9uHLCLQK8Wypjr+N X64FU0NgGV9DQt3iGcJDWRbPI+Tji6JK+bpM+SzCLatez07uJsPpxAY5GEijdaZQ X-Gm-Gg: AfdE7ckfAZmpm8n8KHo6q72X18SzzxzTh4QhhpwPKuYWYVZWWC1vxZRpsEDaFVHQDBw DlY+5zd/RAXmyxN2tTLbFsc+j0iF3NftAjeKA5DEpSBK2Do5Yj90oSTKaIw5ozBxGrHcrT0VDdX p2WcpH2jw4JnPHj8b4usQsorWZYYbA5eHI+b+tTni60R/SMhy02IS+ZgaJ6jJAeAZUM42Rv2GvT 4qLjNp2yg2BwkWwovBduC0g86X1UPRGO40Jh7KQBEVt8KoW7rs0FnwCWD7eSXkMzCL1XhrARTVh XN3bsKZ+FrGgzXro53SGovL6FmNgpo5A+yCplMAvqgFbPBmgkhnGJDa1k0/S41kd9BQj0A8L+U7 fiLgYPQaBz8eRYNHgb0/qsgmkHfAii4f4Ij3HrgFQQFViGBJ27EZl1NAzPF2JayqolXFoaGySjj N3wXCNbS0U7pieVuO0N8AFIdJpy8sM1euM9n48muUznnzDODq+XKlaM1s6buDnhsE= X-Received: by 2002:a17:90b:1dcc:b0:37f:c232:f075 with SMTP id 98e67ed59e1d1-380aa1d454cmr2810009a91.12.1782943024451; Wed, 01 Jul 2026 14:57:04 -0700 (PDT) Received: from DESKTOP-L3Q0GIV.localdomain ([203.230.195.19]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-380de05f20bsm64533a91.7.2026.07.01.14.57.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Jul 2026 14:57:04 -0700 (PDT) From: =?UTF-8?q?=EC=9D=B4=EC=83=81=ED=98=B8?= To: Kees Cook , Al Viro Cc: =?UTF-8?q?=EC=9D=B4=EC=83=81=ED=98=B8?= , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] ufs: reject malformed cylinder summary geometry Date: Thu, 2 Jul 2026 06:57:00 +0900 Message-ID: <20260701215700.822003-1-kudo3228@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ufs_read_cylinder_structures() allocates uspi->s_cssize bytes for the cylinder summary area, but it calculates the number of fragments to copy using the on-disk fs_fshift value and then copies a full s_fsize bytes for every fragment: size = uspi->s_cssize; blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift; base = space = kmalloc(size, GFP_NOFS); ... memcpy(space, bh->b_data, uspi->s_fsize); ufs_fill_super() validates fs_fsize, but not the sibling fs_fshift and fs_cssize fields. A crafted writable UFS/FFS image can therefore set an inconsistent fs_fshift, or set fs_cssize to a value that does not match the number of cylinder groups, causing the loop to copy past the end of the allocated cylinder summary buffer. Reject inconsistent cylinder summary geometry before writable mount. This preserves the existing read/write paths for valid filesystems and fails malformed superblocks before ufs_read_cylinder_structures() can overrun the kmalloc(s_cssize) buffer. This matches normal producer output: UFS/FFS tools derive fs_fshift from fs_fsize and round the cylinder summary table size up to a fragment boundary. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: 이상호 --- Notes: - Public third-party writeup for the same issue: https://psn.af/k/17/ - Unpatched CONFIG_UFS_FS_WRITE=y KASAN replay reproduces the ufs_read_cylinder_structures slab-out-of-bounds write. - Patched replay rejects the malformed image with EINVAL before the vulnerable copy loop; no UFS KASAN signature appears. - The same patch applies cleanly with git apply --check to checked mainline/stable refs: origin/master, linux-6.18.y, linux-6.12.y, linux-6.6.y, linux-6.1.y, linux-5.15.y, and linux-5.10.y. - A latest-master raw-source patchcheck also reports vulnerable_shape=present and patch_status=applies for fs/ufs/super.c. - Full logs and reproducer image are available privately on request. fs/ufs/super.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index c4831a8b9b3f..c295b637920a 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -725,6 +725,7 @@ static int ufs_fill_super(struct super_block *sb, struct fs_context *fc) struct ufs_buffer_head * ubh; struct inode *inode; unsigned block_size, super_block_size; + u64 expected_cssize; unsigned flags; unsigned super_block_offset; unsigned maxsymlen; @@ -1139,6 +1140,19 @@ static int ufs_fill_super(struct super_block *sb, struct fs_context *fc) uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr); uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize); + if (uspi->s_fshift != ilog2(uspi->s_fsize)) { + pr_err("%s(): fragment size/shift mismatch (%u/%u)\n", + __func__, uspi->s_fsize, uspi->s_fshift); + goto failed; + } + expected_cssize = (u64)uspi->s_ncg * sizeof(struct ufs_csum); + expected_cssize = (expected_cssize + uspi->s_fsize - 1) & + ~((u64)uspi->s_fsize - 1); + if (!uspi->s_cssize || uspi->s_cssize != expected_cssize) { + pr_err("%s(): invalid cylinder summary size %u (expected %llu)\n", + __func__, uspi->s_cssize, expected_cssize); + goto failed; + } uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize); uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak); uspi->s_nsect = fs32_to_cpu(sb, usb1->fs_nsect); -- 2.43.0