Petr Pavlu 851ec1
From: Chuck Lever <chuck.lever@oracle.com>
Petr Pavlu 851ec1
Date: Wed, 6 Apr 2022 13:51:32 -0400
Petr Pavlu 851ec1
Subject: SUNRPC: Fix the svc_deferred_event trace class
Petr Pavlu 851ec1
Git-commit: 4d5004451ab2218eab94a30e1841462c9316ba19
Petr Pavlu 851ec1
Patch-mainline: v5.18-rc3
Petr Pavlu 851ec1
References: git-fixes
Petr Pavlu 851ec1
Petr Pavlu 851ec1
Fix a NULL deref crash that occurs when an svc_rqst is deferred
Petr Pavlu 851ec1
while the sunrpc tracing subsystem is enabled. svc_revisit() sets
Petr Pavlu 851ec1
dr->xprt to NULL, so it can't be relied upon in the tracepoint to
Petr Pavlu 851ec1
provide the remote's address.
Petr Pavlu 851ec1
Petr Pavlu 851ec1
Unfortunately we can't revert the "svc_deferred_class" hunk in
Petr Pavlu 851ec1
commit ece200ddd54b ("sunrpc: Save remote presentation address in
Petr Pavlu 851ec1
svc_xprt for trace events") because there is now a specific check
Petr Pavlu 851ec1
of event format specifiers for unsafe dereferences. The warning
Petr Pavlu 851ec1
that check emits is:
Petr Pavlu 851ec1
Petr Pavlu 851ec1
  event svc_defer_recv has unsafe dereference of argument 1
Petr Pavlu 851ec1
Petr Pavlu 851ec1
A "%pISpc" format specifier with a "struct sockaddr *" is indeed
Petr Pavlu 851ec1
flagged by this check.
Petr Pavlu 851ec1
Petr Pavlu 851ec1
Instead, take the brute-force approach used by the svcrdma_qp_error
Petr Pavlu 851ec1
tracepoint. Convert the dr::addr field into a presentation address
Petr Pavlu 851ec1
in the TP_fast_assign() arm of the trace event, and store that as
Petr Pavlu 851ec1
a string. This fix can be backported to -stable kernels.
Petr Pavlu 851ec1
Petr Pavlu 851ec1
In the meantime, commit c6ced22997ad ("tracing: Update print fmt
Petr Pavlu 851ec1
check to handle new __get_sockaddr() macro") is now in v5.18, so
Petr Pavlu 851ec1
this wonky fix can be replaced with __sockaddr() and friends
Petr Pavlu 851ec1
properly during the v5.19 merge window.
Petr Pavlu 851ec1
Petr Pavlu 851ec1
Fixes: ece200ddd54b ("sunrpc: Save remote presentation address in svc_xprt for trace events")
Petr Pavlu 851ec1
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Petr Pavlu 851ec1
Acked-by: Petr Pavlu <petr.pavlu@suse.com>
Petr Pavlu 851ec1
---
Petr Pavlu 851ec1
 include/trace/events/sunrpc.h | 7 ++++---
Petr Pavlu 851ec1
 1 file changed, 4 insertions(+), 3 deletions(-)
Petr Pavlu 851ec1
Petr Pavlu 851ec1
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
Petr Pavlu 851ec1
index ab8ae1f6ba84..4eb706fa5825 100644
Petr Pavlu 851ec1
--- a/include/trace/events/sunrpc.h
Petr Pavlu 851ec1
+++ b/include/trace/events/sunrpc.h
Petr Pavlu 851ec1
@@ -2017,16 +2017,17 @@ DECLARE_EVENT_CLASS(svc_deferred_event,
Petr Pavlu 851ec1
 
Petr Pavlu 851ec1
 	TP_STRUCT__entry(
Petr Pavlu 851ec1
 		__field(u32, xid)
Petr Pavlu 851ec1
-		__string(addr, dr->xprt->xpt_remotebuf)
Petr Pavlu 851ec1
+		__array(__u8, addr, INET6_ADDRSTRLEN + 10)
Petr Pavlu 851ec1
 	),
Petr Pavlu 851ec1
 
Petr Pavlu 851ec1
 	TP_fast_assign(
Petr Pavlu 851ec1
 		__entry->xid = be32_to_cpu(*(__be32 *)(dr->args +
Petr Pavlu 851ec1
 						       (dr->xprt_hlen>>2)));
Petr Pavlu 851ec1
-		__assign_str(addr, dr->xprt->xpt_remotebuf);
Petr Pavlu 851ec1
+		snprintf(__entry->addr, sizeof(__entry->addr) - 1,
Petr Pavlu 851ec1
+			 "%pISpc", (struct sockaddr *)&dr->addr);
Petr Pavlu 851ec1
 	),
Petr Pavlu 851ec1
 
Petr Pavlu 851ec1
-	TP_printk("addr=%s xid=0x%08x", __get_str(addr), __entry->xid)
Petr Pavlu 851ec1
+	TP_printk("addr=%s xid=0x%08x", __entry->addr, __entry->xid)
Petr Pavlu 851ec1
 );
Petr Pavlu 851ec1
 
Petr Pavlu 851ec1
 DEFINE_EVENT(svc_deferred_event, svc_drop_deferred,
Petr Pavlu 851ec1