Thread (15 messages) 15 messages, 1 author, 2h ago
HOTtoday
Revisions (2)
  1. v2 [diff vs current]
  2. v3 current

[PATCH net v3 09/14] afs: Fix UAF in afs_make_call()

From: David Howells <dhowells@redhat.com>
Date: 2026-07-13 08:11:17
Also in: lkml
Subsystem: afs filesystem, filesystems (vfs and infrastructure), the rest, tracing · Maintainers: David Howells, Marc Dionne, Alexander Viro, Christian Brauner, Linus Torvalds, Steven Rostedt, Masami Hiramatsu

There's a potential UAF in afs_make_call() in the event that an
asynchronous call is being sent, but the call fails in some way (e.g. it
gets aborted from the server).  The problem is that afs_make_call() tries
to abort a call if the rxrpc send fails, but the asynchronous notification
from rxrpc may have caused the afs_call to be torn down.

Fix this making afs_make_op_call() give the op->call its own ref rather
than transferring the caller's ref to it and then dropping the ref when
afs_make_call() returns.

This also means that the afs_make_call() func never loses its ref on the
call now.

Fixes: e49c7b2f6de7 ("afs: Build an abstraction around an "operation" concept")
Link: https://sashiko.dev/#/patchset/20260702144919.172295-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <redacted>
cc: Eric Dumazet <edumazet@google.com>
cc: "David S. Miller" <davem@davemloft.net>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
---
 fs/afs/internal.h          | 3 ++-
 fs/afs/rxrpc.c             | 3 ---
 include/trace/events/afs.h | 2 ++
 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 4901d0acbe14..645fe2f12dc5 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1417,7 +1417,7 @@ static inline void afs_make_op_call(struct afs_operation *op, struct afs_call *c
 {
 	struct afs_addr_list *alist = op->estate->addresses;
 
-	op->call	= call;
+	op->call	= afs_get_call(call, afs_call_trace_get_op_call);
 	op->type	= call->type;
 	call->op	= op;
 	call->key	= op->key;
@@ -1425,6 +1425,7 @@ static inline void afs_make_op_call(struct afs_operation *op, struct afs_call *c
 	call->peer	= rxrpc_kernel_get_peer(alist->addrs[op->addr_index].peer);
 	call->service_id = op->server->service_id;
 	afs_make_call(call, gfp);
+	afs_put_call(call, afs_call_trace_put_made_call);
 }
 
 static inline void afs_extract_begin(struct afs_call *call, void *buf, size_t size)
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index a1b9ced4e0f4..6dc6fd853832 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -382,8 +382,6 @@ void afs_make_call(struct afs_call *call, gfp_t gfp)
 	if (ret < 0)
 		goto error_do_abort;
 
-	/* We lost our ref on call if MSG_MORE was not set and ret >= 0. */
-
 	if (write_iter) {
 		msg.msg_iter = *call->write_iter;
 		msg.msg_flags &= ~MSG_MORE;
@@ -393,7 +391,6 @@ void afs_make_call(struct afs_call *call, gfp_t gfp)
 					     call->rxcall, &msg,
 					     iov_iter_count(&msg.msg_iter),
 					     afs_notify_end_request_tx);
-		/* We lost our ref on call if ret >= 0. */
 
 		trace_afs_sent_data(debug_id, &msg, ret);
 		if (ret < 0)
diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h
index df397c11df85..a1963e21f034 100644
--- a/include/trace/events/afs.h
+++ b/include/trace/events/afs.h
@@ -122,8 +122,10 @@ enum yfs_cm_operation {
 #define afs_call_traces \
 	EM(afs_call_trace_alloc,		"ALLOC      ") \
 	EM(afs_call_trace_free,			"FREE       ") \
+	EM(afs_call_trace_get_op_call,		"GET op     ") \
 	EM(afs_call_trace_get_make_async_call,	"GET a-make ") \
 	EM(afs_call_trace_put_async_complete,	"PUT a-cmpl ") \
+	EM(afs_call_trace_put_made_call,	"PUT made   ") \
 	EM(afs_call_trace_put_discard_prealloc,	"PUT dis-pre") \
 	EM(afs_call_trace_put_get_capabilities,	"PUT get-cap") \
 	EM(afs_call_trace_put_giveupcallbacks,	"PUT gvup-cb") \
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help