mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 14:34:41 +02:00
cachefiles: Fix potential UAF/KASAN warning
Currently, trace_cachefiles_coherency() is being passed a pointer to a
__be64 lain over the coherency data in struct cachefiles_xattr so that it
can display the first 8 bytes. However, the data is of variable length and
could even be 0 bytes. This could lead to a UAF or KASAN warning.
Fix this by making sure the buffer has room for at least 8 bytes and that
those 8 bytes are pre-cleared.
Further, those bytes are not 8-byte aligned, so fix the tracepoint to
extract the data as four 2-byte words (they are 2-byte aligned) and
reassemble the __be64. The compiler will convert this into a single 8-byte
load where the CPU supports it.
Fixes: 229105e5cf ("cachefiles: Add auxiliary data trace")
Link: https://sashiko.dev/#/patchset/20260810144746.574036-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://patch.msgid.link/20260827134304.2075713-11-dhowells@redhat.com
Acked-by: Paulo Alcantara <pc@manguebit.org>
cc: Paulo Alcantara <pc@manguebit.org>
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
parent
e00827a4d0
commit
a67632c8c2
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/quotaops.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define CACHEFILES_COOKIE_TYPE_DATA 1
|
||||
|
|
@ -50,7 +51,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object)
|
|||
|
||||
_enter("%x,#%d", object->debug_id, len);
|
||||
|
||||
buf = kmalloc(sizeof(struct cachefiles_xattr) + len, GFP_KERNEL);
|
||||
buf = kmalloc(sizeof(struct cachefiles_xattr) + max(len, sizeof(__be64)), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -60,6 +61,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object)
|
|||
buf->content = object->content_info;
|
||||
if (test_bit(FSCACHE_COOKIE_LOCAL_WRITE, &object->cookie->flags))
|
||||
buf->content = CACHEFILES_CONTENT_DIRTY;
|
||||
put_unaligned_be64(0, (__be64 *)buf->data);
|
||||
if (len > 0)
|
||||
memcpy(buf->data, fscache_get_aux(object->cookie), len);
|
||||
|
||||
|
|
@ -77,8 +79,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),
|
||||
buf->content,
|
||||
buf->data, buf->content,
|
||||
cachefiles_coherency_set_fail);
|
||||
if (ret != -ENOMEM)
|
||||
cachefiles_io_error_obj(
|
||||
|
|
@ -86,8 +87,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),
|
||||
buf->content,
|
||||
buf->data, buf->content,
|
||||
cachefiles_coherency_set_ok);
|
||||
}
|
||||
|
||||
|
|
@ -110,9 +110,10 @@ int cachefiles_check_auxdata(struct cachefiles_object *object, struct file *file
|
|||
int ret = -ESTALE;
|
||||
|
||||
tlen = sizeof(struct cachefiles_xattr) + len;
|
||||
buf = kmalloc(tlen, GFP_KERNEL);
|
||||
buf = kmalloc(sizeof(struct cachefiles_xattr) + max(len, sizeof(__be64)), GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
put_unaligned_be64(0, (__be64 *)buf->data);
|
||||
|
||||
xlen = cachefiles_inject_read_error();
|
||||
if (xlen == 0)
|
||||
|
|
@ -148,8 +149,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),
|
||||
buf->content, why);
|
||||
buf->data, buf->content, why);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ TRACE_EVENT(cachefiles_rename,
|
|||
TRACE_EVENT(cachefiles_coherency,
|
||||
TP_PROTO(struct cachefiles_object *obj,
|
||||
ino_t ino,
|
||||
u64 disk_aux,
|
||||
const void *disk_aux,
|
||||
enum cachefiles_content content,
|
||||
enum cachefiles_coherency_trace why),
|
||||
|
||||
|
|
@ -389,12 +389,27 @@ TRACE_EVENT(cachefiles_coherency,
|
|||
),
|
||||
|
||||
TP_fast_assign(
|
||||
union {
|
||||
__be16 s[4];
|
||||
__be64 ll;
|
||||
} x;
|
||||
|
||||
__entry->obj = obj->debug_id;
|
||||
__entry->why = why;
|
||||
__entry->content = content;
|
||||
__entry->ino = ino;
|
||||
__entry->aux = be64_to_cpup((__be64 *)obj->cookie->inline_aux);
|
||||
__entry->disk_aux = disk_aux;
|
||||
|
||||
/* cachefiles_xattr::data is 2-byte aligned but not 8-byte aligned. */
|
||||
if (disk_aux) {
|
||||
x.s[0] = ((__be16 *)disk_aux)[0];
|
||||
x.s[1] = ((__be16 *)disk_aux)[1];
|
||||
x.s[2] = ((__be16 *)disk_aux)[2];
|
||||
x.s[3] = ((__be16 *)disk_aux)[3];
|
||||
__entry->disk_aux = be64_to_cpu(x.ll);
|
||||
} else {
|
||||
__entry->disk_aux = 0;
|
||||
}
|
||||
),
|
||||
|
||||
TP_printk("o=%08x %s B=%llx c=%u aux=%llx dsk=%llx",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user