SUNRPC: Fix the svc_deferred_event trace class
[ Upstream commit 4d5004451ab2218eab94a30e1841462c9316ba19 ] Fix a NULL deref crash that occurs when an svc_rqst is deferred while the sunrpc tracing subsystem is enabled. svc_revisit() sets dr->xprt to NULL, so it can't be relied upon in the tracepoint to provide the remote's address. Unfortunately we can't revert the "svc_deferred_class" hunk in commitece200ddd5
("sunrpc: Save remote presentation address in svc_xprt for trace events") because there is now a specific check of event format specifiers for unsafe dereferences. The warning that check emits is: event svc_defer_recv has unsafe dereference of argument 1 A "%pISpc" format specifier with a "struct sockaddr *" is indeed flagged by this check. Instead, take the brute-force approach used by the svcrdma_qp_error tracepoint. Convert the dr::addr field into a presentation address in the TP_fast_assign() arm of the trace event, and store that as a string. This fix can be backported to -stable kernels. In the meantime, commit c6ced22997ad ("tracing: Update print fmt check to handle new __get_sockaddr() macro") is now in v5.18, so this wonky fix can be replaced with __sockaddr() and friends properly during the v5.19 merge window. Fixes:ece200ddd5
("sunrpc: Save remote presentation address in svc_xprt for trace events") Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
af12dd7123
commit
85ee17ca21
@@ -1874,17 +1874,18 @@ DECLARE_EVENT_CLASS(svc_deferred_event,
|
|||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
__field(const void *, dr)
|
__field(const void *, dr)
|
||||||
__field(u32, xid)
|
__field(u32, xid)
|
||||||
__string(addr, dr->xprt->xpt_remotebuf)
|
__array(__u8, addr, INET6_ADDRSTRLEN + 10)
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
__entry->dr = dr;
|
__entry->dr = dr;
|
||||||
__entry->xid = be32_to_cpu(*(__be32 *)(dr->args +
|
__entry->xid = be32_to_cpu(*(__be32 *)(dr->args +
|
||||||
(dr->xprt_hlen>>2)));
|
(dr->xprt_hlen>>2)));
|
||||||
__assign_str(addr, dr->xprt->xpt_remotebuf);
|
snprintf(__entry->addr, sizeof(__entry->addr) - 1,
|
||||||
|
"%pISpc", (struct sockaddr *)&dr->addr);
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_printk("addr=%s dr=%p xid=0x%08x", __get_str(addr), __entry->dr,
|
TP_printk("addr=%s dr=%p xid=0x%08x", __entry->addr, __entry->dr,
|
||||||
__entry->xid)
|
__entry->xid)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user