From f574296be7f46eb60beca851240b526df232f480 Mon Sep 17 00:00:00 2001 From: Yifei Gao Date: Mon, 3 Aug 2026 01:07:55 +0000 Subject: [PATCH 1/4] orangefs: fix double-free of trailer_buf on readdir copy failure On a readdir downcall, orangefs_devreq_write_iter() frees op->downcall.trailer_buf with vfree() when copy_from_iter_full() fails, but does not clear the pointer before goto Efault. The waiter in do_readdir() is then woken with a negative status and frees the same pointer again on its r < 0 path, causing a deterministic double-free. A client holding /dev/pvfs2-req triggers it by sending a readdir downcall whose declared trailer_size exceeds the bytes it supplies. Clear the pointer after freeing so the readdir-side vfree() becomes a no-op. Fixes: 382f4581e67f ("orangefs: rewrite readdir to fix several bugs") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Yifei Gao Signed-off-by: Mike Marshall --- fs/orangefs/devorangefs-req.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c index 33ee8cb32f83..e5c60da7e677 100644 --- a/fs/orangefs/devorangefs-req.c +++ b/fs/orangefs/devorangefs-req.c @@ -474,6 +474,7 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, op->downcall.trailer_size, iter)) { gossip_err("%s: failed to copy trailer.\n", __func__); vfree(op->downcall.trailer_buf); + op->downcall.trailer_buf = NULL; goto Efault; } From 5f13fae5580a835d1d9fb22f9b87b4affb2db846 Mon Sep 17 00:00:00 2001 From: Tal Zussman Date: Sun, 9 Aug 2026 16:07:10 -0400 Subject: [PATCH 2/4] orangefs: use folio_pos() and folio_size() in orangefs_page_mkwrite() orangefs_page_mkwrite() records the faulted range with page_offset(vmf->page) and PAGE_SIZE, although the write range it sets is attached to the folio and the rest of the function already operates on folios. Use folio_pos() and folio_size() instead. This gets rid of two calls to page_offset(), removing two calls to compound_head(). No functional change. orangefs folios are always order-0, so the values are identical. However, if orangefs ever enables large folios, this change is necessary for correctness with the current write range tracking scheme. Tracking only a single page of a larger folio would leave the rest of the folio's dirty data outside the range that gets written back, leading to data loss. Signed-off-by: Tal Zussman Signed-off-by: Mike Marshall --- fs/orangefs/inode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c index 7143b64b5b25..cd3273c88e03 100644 --- a/fs/orangefs/inode.c +++ b/fs/orangefs/inode.c @@ -652,8 +652,8 @@ vm_fault_t orangefs_page_mkwrite(struct vm_fault *vmf) wr = folio_get_private(folio); if (uid_eq(wr->uid, current_fsuid()) && gid_eq(wr->gid, current_fsgid())) { - wr->pos = page_offset(vmf->page); - wr->len = PAGE_SIZE; + wr->pos = folio_pos(folio); + wr->len = folio_size(folio); goto okay; } else { if (orangefs_launder_folio(folio)) { @@ -667,8 +667,8 @@ vm_fault_t orangefs_page_mkwrite(struct vm_fault *vmf) ret = VM_FAULT_LOCKED|VM_FAULT_RETRY; goto out; } - wr->pos = page_offset(vmf->page); - wr->len = PAGE_SIZE; + wr->pos = folio_pos(folio); + wr->len = folio_size(folio); wr->uid = current_fsuid(); wr->gid = current_fsgid(); folio_attach_private(folio, wr); From 7471e16ce146692e3ceff809c2f7a20e11cf2c54 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 21 Dec 2025 13:47:13 +0100 Subject: [PATCH 3/4] orangefs: Remove commented out code in find_cached_xattr The code has been commented out since 2017 - remove it. Signed-off-by: Thorsten Blum Signed-off-by: Mike Marshall --- fs/orangefs/xattr.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c index b6d116302de4..885fd3bd5a3d 100644 --- a/fs/orangefs/xattr.c +++ b/fs/orangefs/xattr.c @@ -72,11 +72,6 @@ static struct orangefs_cached_xattr *find_cached_xattr(struct inode *inode, if (hlist_empty(h)) return NULL; hlist_for_each_entry_safe(cx, tmp, h, node) { -/* if (!time_before(jiffies, cx->timeout)) { - hlist_del(&cx->node); - kfree(cx); - continue; - }*/ if (!strcmp(cx->key, key)) return cx; } From d410cd5303ec59c7cf23dd61423752ce8e9ecb59 Mon Sep 17 00:00:00 2001 From: Zhiling Zou Date: Fri, 24 Jul 2026 02:01:46 +0800 Subject: [PATCH 4/4] orangefs: skip leading spaces before parsing client debug masks orangefs_prepare_cdm_array() sizes each client debug keyword buffer with strcspn(cds_head, " "), but then parses the keyword with %s. The %s conversion skips leading whitespace, while strcspn() does not. If a client debug entry starts with a space, the allocation can be sized for an empty keyword while sscanf() copies the following non-empty token. This can write past the end of the allocated keyword buffer. Skip leading spaces before computing the keyword length so the allocation matches the string parsed by sscanf(). Fixes: f7be4ee07fb7 ("Orangefs: kernel client part 4") Cc: stable@vger.kernel.org Reported-by: Vega Assisted-by: Codex:gpt-5.4 Signed-off-by: Zhiling Zou Signed-off-by: Ren Wei Signed-off-by: Mike Marshall --- fs/orangefs/orangefs-debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c index 69bd73a2b556..9f94919a6bc6 100644 --- a/fs/orangefs/orangefs-debugfs.c +++ b/fs/orangefs/orangefs-debugfs.c @@ -569,6 +569,7 @@ static int orangefs_prepare_cdm_array(char *debug_array_string) cds_delimiter = strchr(cds_head, '\n'); *cds_delimiter = '\0'; + cds_head = skip_spaces(cds_head); keyword_len = strcspn(cds_head, " "); cdm_array[i].keyword = kzalloc(keyword_len + 1, GFP_KERNEL);