From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj2-f28.google.com (mail-pj2-f28.google.com [74.125.227.156]) (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 995C932779D for ; Thu, 24 Sep 2026 07:08:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.156 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790233685; cv=none; b=XOGMIxvlieZS2MiLn+K4PSyYEljliNP7f9yw8xh7uTDJJkL6GSJCxvlIeDWKcS+cjRSOBG+GoC7qRDNgo0W7CGj0VqAyrOPXuL99xsjVMsR1BGHoWMRHD6XKIpUASwsOk36flg8BCnzvQ8d7Q9aedY3GnXWRV6iUr0QAAd4fCBA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790233685; c=relaxed/simple; bh=vcPUZbFrBI9CL60zx721prFO1FCW3vFMLr0evu9pNyo=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=oFe5UzQ1DgJnXbT5lNdvXtDAapIAXiRBYOBQfGUbEgcbY74lPrwLfx/pcdBHctpwyoEIIBDzIrSQKzT3BqaUXj3doBXgDUjwYbxi58I/3n1rVkCkiqihFkjoptQBhcmXsGMirYf8vIx19FnWkVEH2+OIHe6QSRdodYW7w8gPOTo= 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=rjsiEF9J; arc=none smtp.client-ip=74.125.227.156 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="rjsiEF9J" Received: by mail-pj2-f28.google.com with SMTP id d9443c01a7336-2d91c22d27dso6717205ad.1 for ; Thu, 24 Sep 2026 00:08:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790233679; x=1790838479; 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=A5R0eORI8KBwokh6UjkxTkUhIY7LnGT/YgU3s5d7Wnk=; b=rjsiEF9JoDc8Xmw2s7hjfQwfQTHYDY9krWnuwLiU7m4ZQvdg0pnsjLM3z0nKUoYkDI r+Jjb+FY5JTts1ZVscxfj/ubs2CTHbjXNhtIzsllBw8DpOOGPtQ/bUyXzYyOK4MeTktC DLsu9kE/1bXISxdCgpbFalxuKXkYMGcoUq/dZL0rzP1wuuizNv2zeQIoMXB2ZTijOg4u uiVew1fShdhz5q2w8BrLCAaRbohaIsZDHbU+1VeQrAqMckq5iqHPYRRmIayQC87j02hI IWwQODcLQ8KgTNkEGeWhLrWg7lc7aCegkCx9EQy5tQfEk8MzXCsROK5FOJO3sZ6gWAjd p3YQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790233679; x=1790838479; 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=A5R0eORI8KBwokh6UjkxTkUhIY7LnGT/YgU3s5d7Wnk=; b=tocLtu5Aq6TKyWE83HbRePaOsxppS/QkYd1OgDES9od7BEuEc9P63USd5JAdeqX9bH mg3TR79lqh/EFU12K9xVxAs9BJn9oCPHJCw9UxgZy3gb0t1au8cy/WpZNF/ZATEqCrZn vMm9y6LVb2WjE4c23+Etxt99+MhE/iQnfjvrgiV4LJk7xGHMjJT7ljIeOqNW8kf2qi8K hiccFlhiW1JTgO9xUos/oZE6VCNK1vgPVrjVdrJh4wNYe93e/C5D4AfbCdrxIS0YAkuK hyVC/gk29trttU2eU7owvWJAvJHYzACeDDjCNR+e37ldgcces0veL8JBQJMMVjmG++eF 9EDg== X-Forwarded-Encrypted: i=1; AKwUvBys5RynMeLw5TWbhpM5sS/3aP5MSGKj3p4ONftjUbEgcpYIK/QkjA0Da7NOiqi/j5x/R38EfHLcBqLs7o0=@vger.kernel.org X-Gm-Message-State: AFuF++lcd0hMQj4cwhu9g5YEZ5xyBnBds+h7pP/Xu1/dKOeuQgcZb5ir FgTDhjKFhezobqGyq+q+xyDlq1sysIn/K6mbn44WUwn1KZ7P3rxzStT+ X-Gm-Gg: AYBFou1khCt9EICy81YsT17irXeoI+uB2K0SDbvE+n+O+qGe5AP4bKLh4/1QM8cdbQT Id+PniQzQY1uVin1RHf8Sem9wcK2c9mlUEYg/aixySeB0AlwLevs+vCA9hugq4J0yu9unsy1R/W hRd2RKvmKX8bP2Y5ZA55d6HmlsM8avmVH0f/avQSLB9Q3jocSDzucS25Exo5tUcOzluo4O+sWF8 a433qUIpULtj+zsFlKdEuauQh+5xlaNenCn0Div0C+hjIDdd8Ubtg4mk1VGYKpQ52jif+dLeds2 aWCNrG93sRWoe3HhM4rpKEuXrfQKke+LAEADA/Xa13hK8vf3l8KYu06T9iOCmVvxwdH2T4zQL7S JrB8A9tMfq4ebc9WLhbfG8BUdHIUZRCc4f3IT5ZDnmvDwq1Lb2xsGAmr8KYYd8uN1k0JrTS61uR MkmDikx8zYAVsXOnNcXfw/sfGVPll5HZxa+OUWmWzANn3l3bbDPb1gpHi2HGGZzs1qk0r5E9twp 25QtF2vC1gqxTdKIwgwDodVgHhMtflsqEf8+hTaTHhVtuwZV2dS4QkfHovdZM3EYxC94G2vDqNl 4RyM9nujDw== X-Received: by 2002:a17:903:94e:b0:2dd:4f83:eef9 with SMTP id d9443c01a7336-2df7da60be9mr14149235ad.4.1790233678960; Thu, 24 Sep 2026 00:07:58 -0700 (PDT) Received: from phui-2.c.googlers.com.com (67.51.127.34.bc.googleusercontent.com. [34.127.51.67]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2df6afc80easm21832025ad.30.2026.09.24.00.07.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Sep 2026 00:07:58 -0700 (PDT) From: Hui Peng To: slava@dubeyko.com, glaubitz@physik.fu-berlin.de, frank.li@vivo.com Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Hui Peng Subject: [PATCH v2] hfsplus: validate inline xattr record size against entrylength Date: Thu, 24 Sep 2026 07:07:57 +0000 Message-ID: <20260924070757.2646279-1-benquike@gmail.com> X-Mailer: git-send-email 2.56.0.rc1.310.g51773c2048-goog Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit In __hfsplus_getxattr(), record_length is read from the on-disk hfsplus_attr_inline_data header and only checked against HFSPLUS_MAX_INLINE_DATA_SIZE without verifying that fd.entrylength is large enough to hold the inline header and record_length bytes of raw_bytes. A corrupted attribute B-tree node where record_length exceeds fd.entrylength causes hfs_bnode_read() to read past the end of the B-tree record (and potentially across the bnode boundary). Validate fd.entrylength before reading xattr_record_type, length, and raw_bytes. Tested in QEMU against Linux 7.3.0-rc3 by mounting a crafted HFS+ image containing an inline xattr record where record_length (100) exceeded fd.entrylength (4): on the unfixed kernel, __hfsplus_getxattr() read past the end of the B-tree record; whereas with this fix applied, __hfsplus_getxattr() rejects the malformed record with "invalid xattr record size" (-EIO). Fixes: 127e5f5ae51e ("hfsplus: rework functionality of getting, setting and deleting of extended attributes") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Hui Peng --- Changes in v2: - Drop the hidden_dir cleanup hunk (already covered by Deepanshu Kartikey's patch series) and focus solely on the __hfsplus_getxattr() entrylength validation, as requested by Viacheslav Dubeyko. fs/hfsplus/xattr.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index 21a1c196c71f..10aae766ea42 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -649,15 +649,28 @@ ssize_t __hfsplus_getxattr(struct inode *inode, const char *name, goto out; } + if (fd.entrylength < sizeof(xattr_record_type)) { + pr_err("invalid xattr record size\n"); + res = -EIO; + goto out; + } hfs_bnode_read(fd.bnode, &xattr_record_type, fd.entryoffset, sizeof(xattr_record_type)); record_type = be32_to_cpu(xattr_record_type); if (record_type == HFSPLUS_ATTR_INLINE_DATA) { + if (fd.entrylength < offsetof(struct hfsplus_attr_inline_data, + raw_bytes)) { + pr_err("invalid xattr record size\n"); + res = -EIO; + goto out; + } record_length = hfs_bnode_read_u16(fd.bnode, fd.entryoffset + offsetof(struct hfsplus_attr_inline_data, length)); - if (record_length > HFSPLUS_MAX_INLINE_DATA_SIZE) { + if (record_length > HFSPLUS_MAX_INLINE_DATA_SIZE || + offsetof(struct hfsplus_attr_inline_data, raw_bytes) + + record_length > fd.entrylength) { pr_err("invalid xattr record size\n"); res = -EIO; goto out; -- 2.55.0.1082.g2b9226bbc0-goog