summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorBryam Vargas <hexlabsecurity@proton.me>2026-06-19 04:38:20 -0500
committerChristian Brauner <brauner@kernel.org>2026-07-01 15:26:27 +0200
commit18227a6bc98bd0ba96ed3ce9d5b28776a5a28dfc (patch)
treef92cc68e2ec4abef8f22254187023e7a6a9c9229 /fs
parent704d48d81dc41470e108811c32c577ada66192d4 (diff)
downloadlinux-18227a6bc98bd0ba96ed3ce9d5b28776a5a28dfc.tar.gz
linux-18227a6bc98bd0ba96ed3ce9d5b28776a5a28dfc.zip
orangefs: keep the readdir entry size 64-bit in fill_from_part()
fill_from_part() computes the size of a directory entry in size_t but stores it in a __u32. An entry length near U32_MAX wraps it to a small value, bypasses the bounds check, and is then used to index the entry, reading far past the directory part -- an out-of-bounds read that oopses the kernel. Compute the size as a u64 so it cannot truncate; the bounds check then rejects the entry. The trailer is supplied by the userspace client. Fixes: 480e3e532e31 ("orangefs: support very large directories") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Link: https://patch.msgid.link/20260619-b4-disp-50d2bd59-v1-1-ce332969b4a2@proton.me Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/orangefs/dir.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/orangefs/dir.c b/fs/orangefs/dir.c
index 6e2ebc8b9867..115b2c2f5269 100644
--- a/fs/orangefs/dir.c
+++ b/fs/orangefs/dir.c
@@ -191,7 +191,8 @@ static int fill_from_part(struct orangefs_dir_part *part,
{
const int offset = sizeof(struct orangefs_readdir_response_s);
struct orangefs_khandle *khandle;
- __u32 *len, padlen;
+ __u32 *len;
+ u64 padlen;
loff_t i;
char *s;
i = ctx->pos & ~PART_MASK;
@@ -215,8 +216,8 @@ static int fill_from_part(struct orangefs_dir_part *part,
* len is the size of the string itself. padlen is the
* total size of the encoded string.
*/
- padlen = (sizeof *len + *len + 1) +
- (8 - (sizeof *len + *len + 1)%8)%8;
+ padlen = (u64)sizeof *len + *len + 1;
+ padlen += (8 - padlen % 8) % 8;
if (part->len < i + padlen + sizeof *khandle)
goto next;
s = (void *)part + offset + i + sizeof *len;