Skip to content

Commit e28b4fc

Browse files
committed
svcrdma: Fix trace point use-after-free race
I hit this while testing nfsd-5.7 with kernel memory debugging enabled on my server: Mar 30 13:21:45 klimt kernel: BUG: unable to handle page fault for address: ffff8887e6c279a8 Mar 30 13:21:45 klimt kernel: #PF: supervisor read access in kernel mode Mar 30 13:21:45 klimt kernel: #PF: error_code(0x0000) - not-present page Mar 30 13:21:45 klimt kernel: PGD 3601067 P4D 3601067 PUD 87c519067 PMD 87c3e2067 PTE 800ffff8193d8060 Mar 30 13:21:45 klimt kernel: Oops: 0000 [#1] SMP DEBUG_PAGEALLOC PTI Mar 30 13:21:45 klimt kernel: CPU: 2 PID: 1933 Comm: nfsd Not tainted 5.6.0-rc6-00040-g881e87a3c6f9 #1591 Mar 30 13:21:45 klimt kernel: Hardware name: Supermicro Super Server/X10SRL-F, BIOS 1.0c 09/09/2015 Mar 30 13:21:45 klimt kernel: RIP: 0010:svc_rdma_post_chunk_ctxt+0xab/0x284 [rpcrdma] Mar 30 13:21:45 klimt kernel: Code: c1 83 34 02 00 00 29 d0 85 c0 7e 72 48 8b bb a0 02 00 00 48 8d 54 24 08 4c 89 e6 48 8b 07 48 8b 40 20 e8 5a 5c 2b e1 41 89 c6 <8b> 45 20 89 44 24 04 8b 05 02 e9 01 00 85 c0 7e 33 e9 5e 01 00 00 Mar 30 13:21:45 klimt kernel: RSP: 0018:ffffc90000dfbdd8 EFLAGS: 00010286 Mar 30 13:21:45 klimt kernel: RAX: 0000000000000000 RBX: ffff8887db8db400 RCX: 0000000000000030 Mar 30 13:21:45 klimt kernel: RDX: 0000000000000040 RSI: 0000000000000000 RDI: 0000000000000246 Mar 30 13:21:45 klimt kernel: RBP: ffff8887e6c27988 R08: 0000000000000000 R09: 0000000000000004 Mar 30 13:21:45 klimt kernel: R10: ffffc90000dfbdd8 R11: 00c068ef00000000 R12: ffff8887eb4e4a80 Mar 30 13:21:45 klimt kernel: R13: ffff8887db8db634 R14: 0000000000000000 R15: ffff8887fc931000 Mar 30 13:21:45 klimt kernel: FS: 0000000000000000(0000) GS:ffff88885bd00000(0000) knlGS:0000000000000000 Mar 30 13:21:45 klimt kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 Mar 30 13:21:45 klimt kernel: CR2: ffff8887e6c279a8 CR3: 000000081b72e002 CR4: 00000000001606e0 Mar 30 13:21:45 klimt kernel: Call Trace: Mar 30 13:21:45 klimt kernel: ? svc_rdma_vec_to_sg+0x7f/0x7f [rpcrdma] Mar 30 13:21:45 klimt kernel: svc_rdma_send_write_chunk+0x59/0xce [rpcrdma] Mar 30 13:21:45 klimt kernel: svc_rdma_sendto+0xf9/0x3ae [rpcrdma] Mar 30 13:21:45 klimt kernel: ? nfsd_destroy+0x51/0x51 [nfsd] Mar 30 13:21:45 klimt kernel: svc_send+0x105/0x1e3 [sunrpc] Mar 30 13:21:45 klimt kernel: nfsd+0xf2/0x149 [nfsd] Mar 30 13:21:45 klimt kernel: kthread+0xf6/0xfb Mar 30 13:21:45 klimt kernel: ? kthread_queue_delayed_work+0x74/0x74 Mar 30 13:21:45 klimt kernel: ret_from_fork+0x3a/0x50 Mar 30 13:21:45 klimt kernel: Modules linked in: ocfs2_dlmfs ocfs2_stack_o2cb ocfs2_dlm ocfs2_nodemanager ocfs2_stackglue ib_umad ib_ipoib mlx4_ib sb_edac x86_pkg_temp_thermal iTCO_wdt iTCO_vendor_support coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel aesni_intel glue_helper crypto_simd cryptd pcspkr rpcrdma i2c_i801 rdma_ucm lpc_ich mfd_core ib_iser rdma_cm iw_cm ib_cm mei_me raid0 libiscsi mei sg scsi_transport_iscsi ioatdma wmi ipmi_si ipmi_devintf ipmi_msghandler acpi_power_meter nfsd nfs_acl lockd auth_rpcgss grace sunrpc ip_tables xfs libcrc32c mlx4_en sd_mod sr_mod cdrom mlx4_core crc32c_intel igb nvme i2c_algo_bit ahci i2c_core libahci nvme_core dca libata t10_pi qedr dm_mirror dm_region_hash dm_log dm_mod dax qede qed crc8 ib_uverbs ib_core Mar 30 13:21:45 klimt kernel: CR2: ffff8887e6c279a8 Mar 30 13:21:45 klimt kernel: ---[ end trace 87971d2ad3429424 ]--- It's absolutely not safe to use resources pointed to by the @send_wr argument of ib_post_send() _after_ that function returns. Those resources are typically freed by the Send completion handler, which can run before ib_post_send() returns. Thus the trace points currently around ib_post_send() in the server's RPC/RDMA transport are a hazard, even when they are disabled. Rearrange them so that they touch the Work Request only _before_ ib_post_send() is invoked. Fixes: bd2abef ("svcrdma: Trace key RDMA API events") Fixes: 4201c74 ("svcrdma: Introduce svc_rdma_send_ctxt") Signed-off-by: Chuck Lever <[email protected]>
1 parent 6221f1d commit e28b4fc

File tree

3 files changed

+46
-23
lines changed

3 files changed

+46
-23
lines changed

include/trace/events/rpcrdma.h

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,30 +1695,27 @@ DECLARE_EVENT_CLASS(svcrdma_sendcomp_event,
16951695

16961696
TRACE_EVENT(svcrdma_post_send,
16971697
TP_PROTO(
1698-
const struct ib_send_wr *wr,
1699-
int status
1698+
const struct ib_send_wr *wr
17001699
),
17011700

1702-
TP_ARGS(wr, status),
1701+
TP_ARGS(wr),
17031702

17041703
TP_STRUCT__entry(
17051704
__field(const void *, cqe)
17061705
__field(unsigned int, num_sge)
17071706
__field(u32, inv_rkey)
1708-
__field(int, status)
17091707
),
17101708

17111709
TP_fast_assign(
17121710
__entry->cqe = wr->wr_cqe;
17131711
__entry->num_sge = wr->num_sge;
17141712
__entry->inv_rkey = (wr->opcode == IB_WR_SEND_WITH_INV) ?
17151713
wr->ex.invalidate_rkey : 0;
1716-
__entry->status = status;
17171714
),
17181715

1719-
TP_printk("cqe=%p num_sge=%u inv_rkey=0x%08x status=%d",
1716+
TP_printk("cqe=%p num_sge=%u inv_rkey=0x%08x",
17201717
__entry->cqe, __entry->num_sge,
1721-
__entry->inv_rkey, __entry->status
1718+
__entry->inv_rkey
17221719
)
17231720
);
17241721

@@ -1783,26 +1780,23 @@ TRACE_EVENT(svcrdma_wc_receive,
17831780
TRACE_EVENT(svcrdma_post_rw,
17841781
TP_PROTO(
17851782
const void *cqe,
1786-
int sqecount,
1787-
int status
1783+
int sqecount
17881784
),
17891785

1790-
TP_ARGS(cqe, sqecount, status),
1786+
TP_ARGS(cqe, sqecount),
17911787

17921788
TP_STRUCT__entry(
17931789
__field(const void *, cqe)
17941790
__field(int, sqecount)
1795-
__field(int, status)
17961791
),
17971792

17981793
TP_fast_assign(
17991794
__entry->cqe = cqe;
18001795
__entry->sqecount = sqecount;
1801-
__entry->status = status;
18021796
),
18031797

1804-
TP_printk("cqe=%p sqecount=%d status=%d",
1805-
__entry->cqe, __entry->sqecount, __entry->status
1798+
TP_printk("cqe=%p sqecount=%d",
1799+
__entry->cqe, __entry->sqecount
18061800
)
18071801
);
18081802

@@ -1870,6 +1864,34 @@ DECLARE_EVENT_CLASS(svcrdma_sendqueue_event,
18701864
DEFINE_SQ_EVENT(full);
18711865
DEFINE_SQ_EVENT(retry);
18721866

1867+
TRACE_EVENT(svcrdma_sq_post_err,
1868+
TP_PROTO(
1869+
const struct svcxprt_rdma *rdma,
1870+
int status
1871+
),
1872+
1873+
TP_ARGS(rdma, status),
1874+
1875+
TP_STRUCT__entry(
1876+
__field(int, avail)
1877+
__field(int, depth)
1878+
__field(int, status)
1879+
__string(addr, rdma->sc_xprt.xpt_remotebuf)
1880+
),
1881+
1882+
TP_fast_assign(
1883+
__entry->avail = atomic_read(&rdma->sc_sq_avail);
1884+
__entry->depth = rdma->sc_sq_depth;
1885+
__entry->status = status;
1886+
__assign_str(addr, rdma->sc_xprt.xpt_remotebuf);
1887+
),
1888+
1889+
TP_printk("addr=%s sc_sq_avail=%d/%d status=%d",
1890+
__get_str(addr), __entry->avail, __entry->depth,
1891+
__entry->status
1892+
)
1893+
);
1894+
18731895
#endif /* _TRACE_RPCRDMA_H */
18741896

18751897
#include <trace/define_trace.h>

net/sunrpc/xprtrdma/svc_rdma_rw.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,6 @@ static int svc_rdma_post_chunk_ctxt(struct svc_rdma_chunk_ctxt *cc)
323323
if (atomic_sub_return(cc->cc_sqecount,
324324
&rdma->sc_sq_avail) > 0) {
325325
ret = ib_post_send(rdma->sc_qp, first_wr, &bad_wr);
326-
trace_svcrdma_post_rw(&cc->cc_cqe,
327-
cc->cc_sqecount, ret);
328326
if (ret)
329327
break;
330328
return 0;
@@ -337,6 +335,7 @@ static int svc_rdma_post_chunk_ctxt(struct svc_rdma_chunk_ctxt *cc)
337335
trace_svcrdma_sq_retry(rdma);
338336
} while (1);
339337

338+
trace_svcrdma_sq_post_err(rdma, ret);
340339
set_bit(XPT_CLOSE, &xprt->xpt_flags);
341340

342341
/* If even one was posted, there will be a completion. */

net/sunrpc/xprtrdma/svc_rdma_sendto.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -322,15 +322,17 @@ int svc_rdma_send(struct svcxprt_rdma *rdma, struct ib_send_wr *wr)
322322
}
323323

324324
svc_xprt_get(&rdma->sc_xprt);
325+
trace_svcrdma_post_send(wr);
325326
ret = ib_post_send(rdma->sc_qp, wr, NULL);
326-
trace_svcrdma_post_send(wr, ret);
327-
if (ret) {
328-
set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
329-
svc_xprt_put(&rdma->sc_xprt);
330-
wake_up(&rdma->sc_send_wait);
331-
}
332-
break;
327+
if (ret)
328+
break;
329+
return 0;
333330
}
331+
332+
trace_svcrdma_sq_post_err(rdma, ret);
333+
set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
334+
svc_xprt_put(&rdma->sc_xprt);
335+
wake_up(&rdma->sc_send_wait);
334336
return ret;
335337
}
336338

0 commit comments

Comments
 (0)