From nobody Mon Feb 9 04:30:59 2026 Received: from mail115-171.sinamail.sina.com.cn (mail115-171.sinamail.sina.com.cn [218.30.115.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1233B364046 for ; Thu, 5 Feb 2026 08:33:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=218.30.115.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770280416; cv=none; b=RBjf7qtbxtYjsbvWTyQaHCNZ9B8XZCm3wuWiTpPGyIt35HTLrQTVkq0gEwVdDLJN38xbf+qgXwYYnDRCDyGzTxAt0aexGJsMJP6YzCb65gtUJpGFMmerZs7oEzLPvSaxhZyWBE4osiGXbcDZtdgMNAS9e4bc959qPLaMlWvjcGM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770280416; c=relaxed/simple; bh=gbbhikzvubqB/8G/3oDW4QIusEY8RtwoT9paPhj9Qvg=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=Njn8kNMfVdAFgZR5VX6hD0yH2EXBXToDuazJy+WTvGkWpcfeT9hzk4Xn3q6JPpCdIkfGG+3Bu/aklmYP1OYFJI5KscwWNFWVy1V9aonAHXyt6rikhCbl/ug8+ElQeHP65eDJR69+/1vyr3fzqcP26nYWH6EnhQUfgAKHEk+sRho= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sina.cn; spf=pass smtp.mailfrom=sina.cn; dkim=pass (1024-bit key) header.d=sina.cn header.i=@sina.cn header.b=Ixam7Zkq; arc=none smtp.client-ip=218.30.115.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=sina.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=sina.cn Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=sina.cn header.i=@sina.cn header.b="Ixam7Zkq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sina.cn; s=201208; t=1770280415; bh=4msyyaTdA7+MLTi59JzT42QQWuTGGjQCjniA0lGrM3A=; h=From:Subject:Date:Message-Id; b=Ixam7Zkq8YYlLHLA3N6pzpuh43rJYHVdxOEMXLp+sbbECwKNqHi+VBvMV+IgSoQyP Z8Ljw4+owPLNmv3pk0NpK+rc/IaVHgC0Qq4dN3vMK1+Ev3poXlMnd4ZR4VniXayhOn fWZsgDZNp04I/Jc1i65t30DXqb30ZWxr/2HLbTjA= X-SMAIL-HELO: NTT-kernel-dev Received: from unknown (HELO NTT-kernel-dev)([60.247.85.88]) by sina.cn (10.185.250.24) with ESMTP id 698455B100001357; Thu, 5 Feb 2026 16:32:55 +0800 (CST) X-Sender: jianqkang@sina.cn X-Auth-ID: jianqkang@sina.cn Authentication-Results: sina.cn; spf=none smtp.mailfrom=jianqkang@sina.cn; dkim=none header.i=none; dmarc=none action=none header.from=jianqkang@sina.cn X-SMAIL-MID: 77787310747974 X-SMAIL-UIID: 5EF18411531649878E0132F651235EE7-20260205-163255-1 From: Jianqiang kang To: gregkh@linuxfoundation.org, stable@vger.kernel.org, k.chen@smail.nju.edu.cn Cc: patches@lists.linux.dev, linux-kernel@vger.kernel.org, slava@dubeyko.com, sashal@kernel.org, yang.chenzhi@vivo.com, frank.li@vivo.com, penguin-kernel@I-love.SAKURA.ne.jp, liushixin2@huawei.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 6.12.y] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc() Date: Thu, 5 Feb 2026 16:32:49 +0800 Message-Id: <20260205083249.2883473-1-jianqkang@sina.cn> 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: quoted-printable Content-Type: text/plain; charset="utf-8" From: Kang Chen [ Upstream commit bea3e1d4467bcf292c8e54f080353d556d355e26 ] BUG: KASAN: slab-out-of-bounds in hfsplus_uni2asc+0xa71/0xb90 fs/hfsplus/un= icode.c:186 Read of size 2 at addr ffff8880289ef218 by task syz.6.248/14290 CPU: 0 UID: 0 PID: 14290 Comm: syz.6.248 Not tainted 6.16.4 #1 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/= 2014 Call Trace: __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x116/0x1b0 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 [inline] print_report+0xca/0x5f0 mm/kasan/report.c:482 kasan_report+0xca/0x100 mm/kasan/report.c:595 hfsplus_uni2asc+0xa71/0xb90 fs/hfsplus/unicode.c:186 hfsplus_listxattr+0x5b6/0xbd0 fs/hfsplus/xattr.c:738 vfs_listxattr+0xbe/0x140 fs/xattr.c:493 listxattr+0xee/0x190 fs/xattr.c:924 filename_listxattr fs/xattr.c:958 [inline] path_listxattrat+0x143/0x360 fs/xattr.c:988 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xcb/0x4c0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7fe0e9fae16d Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 = 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff f= f 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007fe0eae67f98 EFLAGS: 00000246 ORIG_RAX: 00000000000000c3 RAX: ffffffffffffffda RBX: 00007fe0ea205fa0 RCX: 00007fe0e9fae16d RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000200000000000 RBP: 00007fe0ea0480f0 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 00007fe0ea206038 R14: 00007fe0ea205fa0 R15: 00007fe0eae48000 Allocated by task 14290: kasan_save_stack+0x24/0x50 mm/kasan/common.c:47 kasan_save_track+0x14/0x30 mm/kasan/common.c:68 poison_kmalloc_redzone mm/kasan/common.c:377 [inline] __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394 kasan_kmalloc include/linux/kasan.h:260 [inline] __do_kmalloc_node mm/slub.c:4333 [inline] __kmalloc_noprof+0x219/0x540 mm/slub.c:4345 kmalloc_noprof include/linux/slab.h:909 [inline] hfsplus_find_init+0x95/0x1f0 fs/hfsplus/bfind.c:21 hfsplus_listxattr+0x331/0xbd0 fs/hfsplus/xattr.c:697 vfs_listxattr+0xbe/0x140 fs/xattr.c:493 listxattr+0xee/0x190 fs/xattr.c:924 filename_listxattr fs/xattr.c:958 [inline] path_listxattrat+0x143/0x360 fs/xattr.c:988 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xcb/0x4c0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f When hfsplus_uni2asc is called from hfsplus_listxattr, it actually passes in a struct hfsplus_attr_unistr*. The size of the corresponding structure is different from that of hfsplus_u= nistr, so the previous fix (94458781aee6) is insufficient. The pointer on the unicode buffer is still going beyond the allocated memor= y. This patch introduces two warpper functions hfsplus_uni2asc_xattr_str and hfsplus_uni2asc_str to process two unicode buffers, struct hfsplus_attr_unistr* and struct hfsplus_unistr* respectively. When ustrlen value is bigger than the allocated memory size, the ustrlen value is limited to an safe size. Fixes: 94458781aee6 ("hfsplus: fix slab-out-of-bounds read in hfsplus_uni2a= sc()") Signed-off-by: Kang Chen Reviewed-by: Viacheslav Dubeyko Signed-off-by: Viacheslav Dubeyko Link: https://lore.kernel.org/r/20250909031316.1647094-1-k.chen@smail.nju.e= du.cn Signed-off-by: Viacheslav Dubeyko Signed-off-by: Jianqiang kang --- fs/hfsplus/dir.c | 2 +- fs/hfsplus/hfsplus_fs.h | 8 ++++++-- fs/hfsplus/unicode.c | 24 +++++++++++++++++++----- fs/hfsplus/xattr.c | 6 +++--- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 33154c720a4e..d23f8c4cd717 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -204,7 +204,7 @@ static int hfsplus_readdir(struct file *file, struct di= r_context *ctx) fd.entrylength); type =3D be16_to_cpu(entry.type); len =3D NLS_MAX_CHARSET_SIZE * HFSPLUS_MAX_STRLEN; - err =3D hfsplus_uni2asc(sb, &fd.key->cat.name, strbuf, &len); + err =3D hfsplus_uni2asc_str(sb, &fd.key->cat.name, strbuf, &len); if (err) goto out; if (type =3D=3D HFSPLUS_FOLDER) { diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 6c19935d6f50..6122bbd5a837 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -519,8 +519,12 @@ int hfsplus_strcasecmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2); int hfsplus_strcmp(const struct hfsplus_unistr *s1, const struct hfsplus_unistr *s2); -int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *u= str, - char *astr, int *len_p); +int hfsplus_uni2asc_str(struct super_block *sb, + const struct hfsplus_unistr *ustr, char *astr, + int *len_p); +int hfsplus_uni2asc_xattr_str(struct super_block *sb, + const struct hfsplus_attr_unistr *ustr, + char *astr, int *len_p); int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, int max_unistr_len, const char *astr, int len); int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str); diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c index ebd326799f35..11e08a4a18b2 100644 --- a/fs/hfsplus/unicode.c +++ b/fs/hfsplus/unicode.c @@ -143,9 +143,8 @@ static u16 *hfsplus_compose_lookup(u16 *p, u16 cc) return NULL; } =20 -int hfsplus_uni2asc(struct super_block *sb, - const struct hfsplus_unistr *ustr, - char *astr, int *len_p) +static int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_un= istr *ustr, + int max_len, char *astr, int *len_p) { const hfsplus_unichr *ip; struct nls_table *nls =3D HFSPLUS_SB(sb)->nls; @@ -158,8 +157,8 @@ int hfsplus_uni2asc(struct super_block *sb, ip =3D ustr->unicode; =20 ustrlen =3D be16_to_cpu(ustr->length); - if (ustrlen > HFSPLUS_MAX_STRLEN) { - ustrlen =3D HFSPLUS_MAX_STRLEN; + if (ustrlen > max_len) { + ustrlen =3D max_len; pr_err("invalid length %u has been corrected to %d\n", be16_to_cpu(ustr->length), ustrlen); } @@ -280,6 +279,21 @@ int hfsplus_uni2asc(struct super_block *sb, return res; } =20 +inline int hfsplus_uni2asc_str(struct super_block *sb, + const struct hfsplus_unistr *ustr, char *astr, + int *len_p) +{ + return hfsplus_uni2asc(sb, ustr, HFSPLUS_MAX_STRLEN, astr, len_p); +} + +inline int hfsplus_uni2asc_xattr_str(struct super_block *sb, + const struct hfsplus_attr_unistr *ustr, + char *astr, int *len_p) +{ + return hfsplus_uni2asc(sb, (const struct hfsplus_unistr *)ustr, + HFSPLUS_ATTR_MAX_STRLEN, astr, len_p); +} + /* * Convert one or more ASCII characters into a single unicode character. * Returns the number of ASCII characters corresponding to the unicode cha= r. diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index 18dc3d254d21..c951fa9835aa 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -735,9 +735,9 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *= buffer, size_t size) goto end_listxattr; =20 xattr_name_len =3D NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN; - if (hfsplus_uni2asc(inode->i_sb, - (const struct hfsplus_unistr *)&fd.key->attr.key_name, - strbuf, &xattr_name_len)) { + if (hfsplus_uni2asc_xattr_str(inode->i_sb, + &fd.key->attr.key_name, strbuf, + &xattr_name_len)) { pr_err("unicode conversion failed\n"); res =3D -EIO; goto end_listxattr; --=20 2.34.1