From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (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 568273FB075 for ; Tue, 7 Jul 2026 13:59:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783432784; cv=none; b=kj14oyKyaOEVNHtHUWDjjuR1i3sU9u1DVJVt92ThKe4c79GEPe4scHZDxydUnSJ39ePkhlFLQHJucLK+DV45ne72pYtj1WZG90YohWv9zeU6W5GDZrzKVgCiv3SYeC1DLVPSGoMCY1APnSwyyNAkmx9DZXWVnHj254o6NfHRHlA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783432784; c=relaxed/simple; bh=zT/PJSB/X9vWE4hZBw6qbsjL+iFNmQr/XBpWHwP3Uo0=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=mXMRuOUwbI/eeHZHEi1bPmFmY0m8bseIyzh92AzgPcwhmcEaCu+2qFG+0S1XUE+WBaJqDj/vIyyZ2s6ChwXbD3NNQejLBtVzP3cznzXziVM6Dno0r6kHUfjxrafNb4d+ZwzZSSDlfIj3/d3wFkWWaY56vn9QCnRYdZhuHCfUwYc= 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=Ww9MUtLC; arc=none smtp.client-ip=209.85.215.178 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="Ww9MUtLC" Received: by mail-pg1-f178.google.com with SMTP id 41be03b00d2f7-c9b373d5af0so3178942a12.2 for ; Tue, 07 Jul 2026 06:59:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783432782; x=1784037582; 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=LGFuF2FyGr+a/8CunO9g6M8NWPaHjvODP/XSRSVCSC0=; b=Ww9MUtLCmSunDhe0ZJMPva+bLaZ+u5uDrBzjEGZMyTeqOqQDneAP4cWchiv+FqJ+21 +EFH1y0NGuqt39N86TtwF0PDlfRDIHBPqkfJ7k6lj2XsbKkEK9tKLNOzRliUuq7X4UEy y/bMQGBkzTzP+sBq8BUFoXCgzYUVrrYRFc0RIUW4AnS/iIqtbUw8HJRZDPVQVSbcqpTF drheLGAzPMT0U/7qM637/AEMeKTBodbxftWTpXZ4etvjdp9HiBVAXXUoXw8r2fiqHv3g 5SYYuSf1dTTyeCV4DkliA8rSnaAas9x4mGKzdSFNYY1dVoclHETzr+v617p9aD3vIfA8 suSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783432782; x=1784037582; 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=LGFuF2FyGr+a/8CunO9g6M8NWPaHjvODP/XSRSVCSC0=; b=nuT75NwdkTpW1LWYm2+107Y72aMS5Yt0uM+K5EynD4PjhjUWLIA65zOmh8ApBjYqUs Xj0FJezeOYVaFTyadheY+5QZEAuLTst7AsgZPhwGW6v/eOPC3hGrICZC0I4pd5raCLJr ejI9N9WOeL0t2v3S3DSEhIf8c0PXw+4EKgkm8NdVwQa1/cmbysK3WKIpndarINsL7kYA cCQAmGglldEYhTtnqwkVggmNc4prKmezmQMokeXCF+EudiZlBgMtmwm38QE1AgFV55Sd bqzq3WH1ZlJO+VTkc+4oEgDlyt3tpn1dXhkI5PuWCit1jTARPb+mgFHTAcTAO8KMg5Xk TdYA== X-Forwarded-Encrypted: i=1; AHgh+RoA8TksRcdvHl2Trq/yTzuWDLzRENfHJf4NO3kBRaDn2+xyHLVgPxyVB8WFXZ83KmUynuVunwI+spDgGnU=@vger.kernel.org X-Gm-Message-State: AOJu0Yzuleoz7fH6SNrHkYNPbt6OvHDEQicwfIWmzBX2NGyPRBWPpMYC 4MK03MR01ah2nnOStYAE5w9Ry5+IB6aTg7GYbKTOlByGqRJG72mj0sNf X-Gm-Gg: AfdE7ck8GERK+QW60QTAAmHqG5Um1hFxjFKlBqpCVsZZY9Yrex9A1iNGtb4cfsMkKQo H9I0dXoSczQCMQ6wCz7AwxPoaA6l2Ewbx4tJ/nkql4UPW5eM61wHLjZh5wZjuzolgXsKFdYII2L CYPR8iXFkYaQXay3jQUeElFuOaOI7w2pKb3B6dQBmcpaLiajXla1QSfGzjxQCa1IOwlCazHU7nl LCTTOlQvyVV50MOTqwc0OA8LjcfXotjJWLUC2eDNjznlBlMiKBUB0TmkNkxnXWSereO+HCE1JQL R+cLob+dCmuC+buWJgjSl6lVH12QHq2l/S/Z+xuiplOtFRKeg4QulB5gvKddXwxXj+qX+TQCtr+ PiIQxC0EQkCEGrKiUhaQK3yDlnp94V4L1F+3kZVcqZQLXT193/QmmqTcZK6Hdkq8IqsWD1ffVr5 5G4+9A X-Received: by 2002:a05:6a20:d494:b0:398:7ed3:a001 with SMTP id adf61e73a8af0-3c08ec61813mr5974200637.2.1783432781480; Tue, 07 Jul 2026 06:59:41 -0700 (PDT) Received: from beelink.. ([186.22.57.86]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3117483dec6sm9233205eec.11.2026.07.07.06.59.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Jul 2026 06:59:41 -0700 (PDT) From: Aldo Ariel Panzardo To: linux-xfs@vger.kernel.org, Carlos Maiolino Cc: "Darrick J . Wong" , Dave Chinner , linux-kernel@vger.kernel.org, Aldo Ariel Panzardo Subject: [PATCH] xfs: bound da-node entry count against the correct geometry Date: Tue, 7 Jul 2026 10:59:30 -0300 Message-ID: <20260707135930.3214701-1-qwe.aldo@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-Transfer-Encoding: 8bit xfs_da3_node_verify() bounds the node entry count against the larger of the directory and attribute geometries because it does not know which tree the block belongs to. When the directory block size exceeds the fs block size (e.g. mkfs.xfs -n size=64k -b size=4k), the attribute node buffer is a single fs block holding only m_attr_geo->node_ents entries, but a crafted attr node may claim a count up to m_dir_geo->node_ents. xfs_da3_node_lookup_int() then reads btree[] entries past the buffer during its binary search -- an out-of-bounds read via getxattr/listxattr on a mounted crafted image. The node buffer size identifies its geometry, so bound the count against that geometry's node_ents rather than the maximum of the two. Fixes: 7ab610f9e0f1 ("xfs: move node entry counts to xfs_da_geometry") Signed-off-by: Aldo Ariel Panzardo --- fs/xfs/libxfs/xfs_da_btree.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c index 9debb95d86fa..897c31147a46 100644 --- a/fs/xfs/libxfs/xfs_da_btree.c +++ b/fs/xfs/libxfs/xfs_da_btree.c @@ -240,12 +240,18 @@ xfs_da3_node_verify( return __this_address; /* - * we don't know if the node is for and attribute or directory tree, - * so only fail if the count is outside both bounds + * The block was read using either the attribute or the directory + * geometry; its buffer size tells us which one, so bound the entry + * count against that geometry's node_ents. Only failing when the + * count exceeds max(dir, attr) let a crafted attr node claim a + * dir-sized count and overrun the smaller attr buffer. */ - if (ichdr.count > mp->m_dir_geo->node_ents && - ichdr.count > mp->m_attr_geo->node_ents) + if (BBTOB(bp->b_length) == mp->m_attr_geo->blksize) { + if (ichdr.count > mp->m_attr_geo->node_ents) + return __this_address; + } else if (ichdr.count > mp->m_dir_geo->node_ents) { return __this_address; + } /* XXX: hash order check? */ -- 2.43.0