[PATCH 1/1] cachefiles: avoid slab out-of-bounds read when tracing short aux data

Ren Wei <[email protected]> Sun, 28 Jun 2026 19:28:16 +0800
Newsgroups dev.linux.lists.netfs
Message-ID <82edfddccd38dc1ba67bc614f24e8248bab447a1.1782637741.git.xizh2024@lzu.edu.cn>
From: Zihan Xi <[email protected]>

trace_cachefiles_coherency() logs disk-side auxiliary data passed from
cachefiles_set_object_xattr() and cachefiles_check_auxdata(). Both call
sites always used be64_to_cpup(buf->data), reading eight bytes even when
the xattr tail only contains cookie->aux_len bytes.

9p registers FS-Cache cookies with a four-byte qid.version aux payload.
When the cachefiles coherency tracepoint is enabled, the extra read past
the kmalloc() allocation triggers KASAN slab-out-of-bounds reports in
fscache_cookie_worker.

Read at most aux_len bytes into a u64 before passing the value to the
tracepoint.

Fixes: 229105e5cfd9 ("cachefiles: Add auxiliary data trace")
Cc: [email protected]
Reported-by: Yuan Tan <[email protected]>
Reported-by: Xin Liu <[email protected]>
Cc: David Howells <[email protected]>
Cc: [email protected]
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zihan Xi <[email protected]>
Signed-off-by: Ren Wei <[email protected]>
---
 fs/cachefiles/xattr.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c
index f8ae78b3f7b6..a11ea858c046 100644
--- a/fs/cachefiles/xattr.c
+++ b/fs/cachefiles/xattr.c
@@ -28,6 +28,18 @@ struct cachefiles_xattr {
 static const char cachefiles_xattr_cache[] =
 	XATTR_USER_PREFIX "CacheFiles.cache";
 
+static u64 cachefiles_disk_aux_for_trace(const void *data, unsigned int len)
+{
+	u64 aux = 0;
+
+	if (len == 0)
+		return 0;
+	if (len >= sizeof(u64))
+		return be64_to_cpup(data);
+	memcpy(&aux, data, len);
+	return aux;
+}
+
 struct cachefiles_vol_xattr {
 	__be32	reserved;	/* Reserved, should be 0 */
 	__u8	data[];		/* netfs volume coherency data */
@@ -77,7 +89,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object)
 		trace_cachefiles_vfs_error(object, file_inode(file), ret,
 					   cachefiles_trace_setxattr_error);
 		trace_cachefiles_coherency(object, file_inode(file)->i_ino,
-					   be64_to_cpup((__be64 *)buf->data),
+					   cachefiles_disk_aux_for_trace(buf->data, len),
 					   buf->content,
 					   cachefiles_coherency_set_fail);
 		if (ret != -ENOMEM)
@@ -86,7 +98,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object)
 				"Failed to set xattr with error %d", ret);
 	} else {
 		trace_cachefiles_coherency(object, file_inode(file)->i_ino,
-					   be64_to_cpup((__be64 *)buf->data),
+					   cachefiles_disk_aux_for_trace(buf->data, len),
 					   buf->content,
 					   cachefiles_coherency_set_ok);
 	}
@@ -148,7 +160,7 @@ int cachefiles_check_auxdata(struct cachefiles_object *object, struct file *file
 
 out:
 	trace_cachefiles_coherency(object, file_inode(file)->i_ino,
-				   be64_to_cpup((__be64 *)buf->data),
+				   cachefiles_disk_aux_for_trace(buf->data, len),
 				   buf->content, why);
 	kfree(buf);
 	return ret;
-- 
2.43.0