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: 480e3e532e ("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>
This commit is contained in:
Bryam Vargas 2026-06-19 04:38:20 -05:00 committed by Christian Brauner
parent 704d48d81d
commit 18227a6bc9
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2

View File

@ -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;