From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f195.google.com (mail-pf1-f195.google.com [209.85.210.195]) (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 CAF263BBFD4 for ; Mon, 15 Jun 2026 07:20:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.195 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781508006; cv=none; b=ZDU2TykMzPAZnOn5fxwk7bXw8eSCW3hruNXJEiRxYMdgUfNhLdxGnwj7s43AYbnFhltHYeVZUr/ar2JyXdDl1da/iejh3nqK8dOoRJMrtSAmf4wLctsWZ4saYYMG2DIn0jPl5Tu8c23nNi40bsF57nnnSnU9u3ljGWIx4iSq624= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781508006; c=relaxed/simple; bh=seOfch1HYvSCVZAcTw41g6xgcUDohrC9UYwVIJNqdbM=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=e93ZmbUwoxPliD/RF9Une/mgSBJbLTsPs1TmAZUJsptsMFcJX94FcwjHlkOTXfE7/USsLM0eSx+1bYHmC3rmkrNAIEFmGwgMnx8BILWCWREjzG2TXGtfNbGmIWCUZYmh0c9XEfUU0Woh/LZFVwNn3BKBWzPqUipxqPs1zE8ZOGc= 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=n9pZw3eH; arc=none smtp.client-ip=209.85.210.195 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="n9pZw3eH" Received: by mail-pf1-f195.google.com with SMTP id d2e1a72fcca58-84230ab8857so1341640b3a.1 for ; Mon, 15 Jun 2026 00:20:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781508004; x=1782112804; 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=frXAoG9W+1/5yVm6iJaF2YLozS+IttKmuZ56CDlLO0U=; b=n9pZw3eHgcA1IwqCsrJpxavWyt1jugELatW7LjKS3BTW1O91P/dt5bsTgJ3QT+YCJL JW/61ql+h2mjwg8WK7mM3XuaznoMuQX4WXBnrnKdVVJmSQeZZjXeFg7DqDBBDl+CjU0F LdEhq9Ua/KBhMcQDoKwRsR/azft5JZ6K6eKblc3USgOgCw6ntrDzXh6J1ijoogO+o6lj CRdheHBqjPpwkVhQZWQ//Cg9vnVYeyQjHL5CIQBFA5eYScNmdEbJfiFLQVnNOhZyMKR6 z0QMMjHQAlAvHve8LKxnczUJsq30EwBlwMZMU62Y3SXafe5iCbd1GqQYBkRYfn1AJ9mz jS2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781508004; x=1782112804; 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=frXAoG9W+1/5yVm6iJaF2YLozS+IttKmuZ56CDlLO0U=; b=C1M31A69m2YE74AuLRAQHigz+zjNA97uDeBmIQLYeyAQxbt3fi93hIJF19RbUfFX0X C0MkU1pl39+aKwbAOmsenXjL8e11m/xFSrNAXjZfN4rahTBEPwkL6/rL2dsxIpuxa+uE kPnxyM1GZx+MlYGStcpT8KZNCfwCnjSoHMANMVyuADzfy9p+ImEsSOhpDWScw2oZH5jx 608QuZoqwqlH6RTkLi+sVY/w3MdpvdvrnBCAcxGBXmSBFZaE7TdiWOVq+8z9aUB/Xnq2 PS/3rPU6Bg+S1m7MemfgCZaoZ/5ZN6g7PxB7wKI+rrU5Jw1uxCYDKqr+FVHyKJJ/AhaX 2t9w== X-Forwarded-Encrypted: i=1; AFNElJ/ApVoa8RO5FFUKyQQzTfd79M6mZpvzeBaq4AV9qWFHy3MifHgi+XGfjXzSA8BA2wl5VINchZ+19lAqDhw=@vger.kernel.org X-Gm-Message-State: AOJu0YxaQddiKPKmMkJSMZ0gQo4bXkK97xwPokv1Bw8N9Az5/M6XCja6 Gq6Fxg+nCv7C9EPJG5lbriPRz3Zyqz718MBzkDT2YqZQeHMgYXBSAPrl X-Gm-Gg: Acq92OF2y67APv/vS/9LS1ijU40RO/3vU3VnAum5iedBvATmv7mPH9s6hhjcmHE2y9t nLGbEQYjAaIhJKXBKHxPdAv1aIWEWbZoEWngZhcT4Vx0SSo6IsRD8vcSlFwh/PId5NVfYSCqq+R tXJx49hWWlStwOokTeswKuBzGTYLlSQ7zJwoZJ5nkj58eV2/psULoXukGsg4b7S0BIxRP8uK2Fu KYX35ZIygjhjdrPN6BOQYJE6On3F5so7UG1yEBDZlsRw49wWALq5dIoB6um8267rDKRe7BuUHDa REuCLju98xhRttzST6tQQx0VNuzCQyMJncE/DEKJOr0JTaWBjjoEJrD2+05Npiq8GQoiDa8dB/z VE1GuGzq0PEkKDUQ2JBMhU46iAAabY08MUxWCmFz0KbI/NxvAnERSCSzbZnVJFzXpro4gwwczAj 0NHfmyMuG3aNfUWzNN9mhZDCfmrP14pO4/rXxY0mfqHu5od4g1TQ6YStn9ad9YsdLBbkMkJqJCc 90T7Q== X-Received: by 2002:a05:6a00:238c:b0:835:41f3:f440 with SMTP id d2e1a72fcca58-8434cdfe0ffmr14740566b3a.14.1781508002630; Mon, 15 Jun 2026 00:20:02 -0700 (PDT) Received: from localhost ([111.228.63.84]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8434acf23a7sm8791736b3a.22.2026.06.15.00.19.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Jun 2026 00:20:02 -0700 (PDT) From: Zhang Cen To: Jaegeuk Kim , Chao Yu Cc: linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org, zerocling0077@gmail.com, 2045gemini@gmail.com, Zhang Cen Subject: [PATCH v3] f2fs: validate ACL entry sizes in f2fs_acl_from_disk() Date: Mon, 15 Jun 2026 15:19:54 +0800 Message-Id: <20260615071954.4118409-1-rollkingzzc@gmail.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit f2fs_acl_count() only validates the aggregate ACL xattr length. A malformed ACL can still place ACL_USER or ACL_GROUP in a slot that only contains struct f2fs_acl_entry_short bytes, and f2fs_acl_from_disk() then reads entry->e_id before verifying that a full entry fits. Require a short entry before reading e_tag and e_perm, and require a full entry before reading e_id for ACL_USER and ACL_GROUP. Return -EFSCORRUPTED from these new truncated-entry checks, while keeping the pre-existing -EINVAL paths unchanged. Validation reproduced this kernel report: KASAN slab-out-of-bounds in __f2fs_get_acl+0x6fb/0x7e0 RIP: 0033:0x7f4b835ea7aa The buggy address belongs to the object at ffff888114589960 which belongs to the cache kmalloc-8 of size 8 The buggy address is located 0 bytes to the right of allocated 8-byte region [ffff888114589960, ffff888114589968) Read of size 4 Call trace: dump_stack_lvl+0x66/0xa0 (?:?) print_report+0xce/0x630 (?:?) __f2fs_get_acl+0x6fb/0x7e0 (fs/f2fs/acl.c:169) srso_alias_return_thunk+0x5/0xfbef5 (?:?) __virt_addr_valid+0x224/0x430 (?:?) kasan_report+0xe0/0x110 (?:?) __f2fs_get_acl+0x5/0x7e0 (fs/f2fs/acl.c:169) __get_acl+0x281/0x380 (?:?) vfs_get_acl+0x10b/0x190 (?:?) do_get_acl+0x2a/0x410 (?:?) do_get_acl+0x9/0x410 (?:?) do_getxattr+0xe8/0x260 (?:?) filename_getxattr+0xd1/0x140 (?:?) do_getname+0x2d/0x2d0 (?:?) path_getxattrat+0x16c/0x200 (?:?) lock_release+0xc8/0x290 (?:?) cgroup_update_frozen+0x9d/0x320 (?:?) lockdep_hardirqs_on_prepare+0xea/0x1a0 (?:?) trace_hardirqs_on+0x1a/0x170 (?:?) _raw_spin_unlock_irq+0x28/0x50 (?:?) do_syscall_64+0x115/0x6a0 (arch/x86/entry/syscall_64.c:87) entry_SYSCALL_64_after_hwframe+0x77/0x7f (?:?) Fixes: af48b85b8cd3 ("f2fs: add xattr and acl functionalities") Assisted-by: Codex:gpt-5.5 Signed-off-by: Zhang Cen --- Changes in v3: - Keep the pre-existing -EINVAL error paths unchanged. - Return -EFSCORRUPTED only from the newly added truncated-entry checks. Changes in v2: - Wrap the new ACL entry-size checks in unlikely(). - Return -EFSCORRUPTED for malformed on-disk ACL blobs. fs/f2fs/acl.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index fa8d81a30fb91..d3253549173e6 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c @@ -47,6 +47,7 @@ static inline int f2fs_acl_count(size_t size) static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size) { int i, count; + int err = -EINVAL; struct posix_acl *acl; struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value; struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1); @@ -70,8 +71,11 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size) for (i = 0; i < count; i++) { - if ((char *)entry > end) + if (unlikely((char *)entry + + sizeof(struct f2fs_acl_entry_short) > end)) { + err = -EFSCORRUPTED; goto fail; + } acl->a_entries[i].e_tag = le16_to_cpu(entry->e_tag); acl->a_entries[i].e_perm = le16_to_cpu(entry->e_perm); @@ -86,6 +90,11 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size) break; case ACL_USER: + if (unlikely((char *)entry + + sizeof(struct f2fs_acl_entry) > end)) { + err = -EFSCORRUPTED; + goto fail; + } acl->a_entries[i].e_uid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id)); @@ -93,6 +102,11 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size) sizeof(struct f2fs_acl_entry)); break; case ACL_GROUP: + if (unlikely((char *)entry + + sizeof(struct f2fs_acl_entry) > end)) { + err = -EFSCORRUPTED; + goto fail; + } acl->a_entries[i].e_gid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id)); @@ -108,7 +122,7 @@ static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size) return acl; fail: posix_acl_release(acl); - return ERR_PTR(-EINVAL); + return ERR_PTR(err); } static void *f2fs_acl_to_disk(struct f2fs_sb_info *sbi, -- 2.43.0