Skip to content

Commit 9e630bc

Browse files
Avinash Repakadavem330
authored andcommitted
RDS: RDMA: Fix the NULL-ptr deref in rds_ib_get_mr
Registration of a memory region(MR) through FRMR/fastreg(unlike FMR) needs a connection/qp. With a proxy qp, this dependency on connection will be removed, but that needs more infrastructure patches, which is a work in progress. As an intermediate fix, the get_mr returns EOPNOTSUPP when connection details are not populated. The MR registration through sendmsg() will continue to work even with fast registration, since connection in this case is formed upfront. This patch fixes the following crash: kasan: GPF could be caused by NULL-ptr deref or user memory access general protection fault: 0000 [#1] SMP KASAN Modules linked in: CPU: 1 PID: 4244 Comm: syzkaller468044 Not tainted 4.16.0-rc6+ #361 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:rds_ib_get_mr+0x5c/0x230 net/rds/ib_rdma.c:544 RSP: 0018:ffff8801b059f890 EFLAGS: 00010202 RAX: dffffc0000000000 RBX: ffff8801b07e1300 RCX: ffffffff8562d96e RDX: 000000000000000d RSI: 0000000000000001 RDI: 0000000000000068 RBP: ffff8801b059f8b8 R08: ffffed0036274244 R09: ffff8801b13a1200 R10: 0000000000000004 R11: ffffed0036274243 R12: ffff8801b13a1200 R13: 0000000000000001 R14: ffff8801ca09fa9c R15: 0000000000000000 FS: 00007f4d050af700(0000) GS:ffff8801db300000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f4d050aee78 CR3: 00000001b0d9b006 CR4: 00000000001606e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: __rds_rdma_map+0x710/0x1050 net/rds/rdma.c:271 rds_get_mr_for_dest+0x1d4/0x2c0 net/rds/rdma.c:357 rds_setsockopt+0x6cc/0x980 net/rds/af_rds.c:347 SYSC_setsockopt net/socket.c:1849 [inline] SyS_setsockopt+0x189/0x360 net/socket.c:1828 do_syscall_64+0x281/0x940 arch/x86/entry/common.c:287 entry_SYSCALL_64_after_hwframe+0x42/0xb7 RIP: 0033:0x4456d9 RSP: 002b:00007f4d050aedb8 EFLAGS: 00000246 ORIG_RAX: 0000000000000036 RAX: ffffffffffffffda RBX: 00000000006dac3c RCX: 00000000004456d9 RDX: 0000000000000007 RSI: 0000000000000114 RDI: 0000000000000004 RBP: 00000000006dac38 R08: 00000000000000a0 R09: 0000000000000000 R10: 0000000020000380 R11: 0000000000000246 R12: 0000000000000000 R13: 00007fffbfb36d6f R14: 00007f4d050af9c0 R15: 0000000000000005 Code: fa 48 c1 ea 03 80 3c 02 00 0f 85 cc 01 00 00 4c 8b bb 80 04 00 00 48 b8 00 00 00 00 00 fc ff df 49 8d 7f 68 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 9c 01 00 00 4d 8b 7f 68 48 b8 00 00 00 00 00 RIP: rds_ib_get_mr+0x5c/0x230 net/rds/ib_rdma.c:544 RSP: ffff8801b059f890 ---[ end trace 7e1cea13b85473b0 ]--- Reported-by: [email protected] Signed-off-by: Santosh Shilimkar <[email protected]> Signed-off-by: Avinash Repaka <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7effaf0 commit 9e630bc

File tree

6 files changed

+39
-20
lines changed

6 files changed

+39
-20
lines changed

net/rds/ib_frmr.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,11 @@ struct rds_ib_mr *rds_ib_reg_frmr(struct rds_ib_device *rds_ibdev,
344344
struct rds_ib_frmr *frmr;
345345
int ret;
346346

347+
if (!ic) {
348+
/* TODO: Add FRWR support for RDS_GET_MR using proxy qp*/
349+
return ERR_PTR(-EOPNOTSUPP);
350+
}
351+
347352
do {
348353
if (ibmr)
349354
rds_ib_free_frmr(ibmr, true);

net/rds/ib_mr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ void rds_ib_get_mr_info(struct rds_ib_device *rds_ibdev,
115115
struct rds_info_rdma_connection *iinfo);
116116
void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *);
117117
void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
118-
struct rds_sock *rs, u32 *key_ret);
118+
struct rds_sock *rs, u32 *key_ret,
119+
struct rds_connection *conn);
119120
void rds_ib_sync_mr(void *trans_private, int dir);
120121
void rds_ib_free_mr(void *trans_private, int invalidate);
121122
void rds_ib_flush_mrs(void);

net/rds/ib_rdma.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -537,11 +537,12 @@ void rds_ib_flush_mrs(void)
537537
}
538538

539539
void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
540-
struct rds_sock *rs, u32 *key_ret)
540+
struct rds_sock *rs, u32 *key_ret,
541+
struct rds_connection *conn)
541542
{
542543
struct rds_ib_device *rds_ibdev;
543544
struct rds_ib_mr *ibmr = NULL;
544-
struct rds_ib_connection *ic = rs->rs_conn->c_transport_data;
545+
struct rds_ib_connection *ic = NULL;
545546
int ret;
546547

547548
rds_ibdev = rds_ib_get_device(rs->rs_bound_addr);
@@ -550,6 +551,9 @@ void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
550551
goto out;
551552
}
552553

554+
if (conn)
555+
ic = conn->c_transport_data;
556+
553557
if (!rds_ibdev->mr_8k_pool || !rds_ibdev->mr_1m_pool) {
554558
ret = -ENODEV;
555559
goto out;
@@ -559,17 +563,18 @@ void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
559563
ibmr = rds_ib_reg_frmr(rds_ibdev, ic, sg, nents, key_ret);
560564
else
561565
ibmr = rds_ib_reg_fmr(rds_ibdev, sg, nents, key_ret);
562-
if (ibmr)
563-
rds_ibdev = NULL;
564-
565-
out:
566-
if (!ibmr)
566+
if (IS_ERR(ibmr)) {
567+
ret = PTR_ERR(ibmr);
567568
pr_warn("RDS/IB: rds_ib_get_mr failed (errno=%d)\n", ret);
569+
} else {
570+
return ibmr;
571+
}
568572

573+
out:
569574
if (rds_ibdev)
570575
rds_ib_dev_put(rds_ibdev);
571576

572-
return ibmr;
577+
return ERR_PTR(ret);
573578
}
574579

575580
void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *pool)

net/rds/rdma.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages,
170170
}
171171

172172
static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
173-
u64 *cookie_ret, struct rds_mr **mr_ret)
173+
u64 *cookie_ret, struct rds_mr **mr_ret,
174+
struct rds_conn_path *cp)
174175
{
175176
struct rds_mr *mr = NULL, *found;
176177
unsigned int nr_pages;
@@ -269,7 +270,8 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
269270
* Note that dma_map() implies that pending writes are
270271
* flushed to RAM, so no dma_sync is needed here. */
271272
trans_private = rs->rs_transport->get_mr(sg, nents, rs,
272-
&mr->r_key);
273+
&mr->r_key,
274+
cp ? cp->cp_conn : NULL);
273275

274276
if (IS_ERR(trans_private)) {
275277
for (i = 0 ; i < nents; i++)
@@ -330,7 +332,7 @@ int rds_get_mr(struct rds_sock *rs, char __user *optval, int optlen)
330332
sizeof(struct rds_get_mr_args)))
331333
return -EFAULT;
332334

333-
return __rds_rdma_map(rs, &args, NULL, NULL);
335+
return __rds_rdma_map(rs, &args, NULL, NULL, NULL);
334336
}
335337

336338
int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen)
@@ -354,7 +356,7 @@ int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen)
354356
new_args.cookie_addr = args.cookie_addr;
355357
new_args.flags = args.flags;
356358

357-
return __rds_rdma_map(rs, &new_args, NULL, NULL);
359+
return __rds_rdma_map(rs, &new_args, NULL, NULL, NULL);
358360
}
359361

360362
/*
@@ -782,7 +784,8 @@ int rds_cmsg_rdma_map(struct rds_sock *rs, struct rds_message *rm,
782784
rm->m_rdma_cookie != 0)
783785
return -EINVAL;
784786

785-
return __rds_rdma_map(rs, CMSG_DATA(cmsg), &rm->m_rdma_cookie, &rm->rdma.op_rdma_mr);
787+
return __rds_rdma_map(rs, CMSG_DATA(cmsg), &rm->m_rdma_cookie,
788+
&rm->rdma.op_rdma_mr, rm->m_conn_path);
786789
}
787790

788791
/*

net/rds/rds.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,8 @@ struct rds_message {
464464
struct scatterlist *op_sg;
465465
} data;
466466
};
467+
468+
struct rds_conn_path *m_conn_path;
467469
};
468470

469471
/*
@@ -544,7 +546,8 @@ struct rds_transport {
544546
unsigned int avail);
545547
void (*exit)(void);
546548
void *(*get_mr)(struct scatterlist *sg, unsigned long nr_sg,
547-
struct rds_sock *rs, u32 *key_ret);
549+
struct rds_sock *rs, u32 *key_ret,
550+
struct rds_connection *conn);
548551
void (*sync_mr)(void *trans_private, int direction);
549552
void (*free_mr)(void *trans_private, int invalidate);
550553
void (*flush_mrs)(void);

net/rds/send.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,13 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
11691169
rs->rs_conn = conn;
11701170
}
11711171

1172+
if (conn->c_trans->t_mp_capable)
1173+
cpath = &conn->c_path[rds_send_mprds_hash(rs, conn)];
1174+
else
1175+
cpath = &conn->c_path[0];
1176+
1177+
rm->m_conn_path = cpath;
1178+
11721179
/* Parse any control messages the user may have included. */
11731180
ret = rds_cmsg_send(rs, rm, msg, &allocated_mr);
11741181
if (ret) {
@@ -1192,11 +1199,6 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
11921199
goto out;
11931200
}
11941201

1195-
if (conn->c_trans->t_mp_capable)
1196-
cpath = &conn->c_path[rds_send_mprds_hash(rs, conn)];
1197-
else
1198-
cpath = &conn->c_path[0];
1199-
12001202
if (rds_destroy_pending(conn)) {
12011203
ret = -EAGAIN;
12021204
goto out;

0 commit comments

Comments
 (0)