From f70968f05de4e7c24d839ca0d3e40f17c8024498 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 1 Apr 2020 23:49:21 +0100 Subject: [PATCH 01/11] i40iw: fix null pointer dereference on a null wqe pointer Currently the null check for wqe is incorrect and lets a null wqe be passed to set_64bit_val and this indexes into the null pointer causing a null pointer dereference. Fix this by fixing the null pointer check to return an error if wqe is null. Link: https://lore.kernel.org/r/20200401224921.405279-1-colin.king@canonical.com Addresses-Coverity: ("dereference after a null check") Fixes: 4b34e23f4eaa ("i40iw: Report correct firmware version") Signed-off-by: Colin Ian King Acked-by: Shiraz Saleem Signed-off-by: Jason Gunthorpe --- drivers/infiniband/hw/i40iw/i40iw_ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/i40iw/i40iw_ctrl.c b/drivers/infiniband/hw/i40iw/i40iw_ctrl.c index e8b4b3743661..688f19667221 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_ctrl.c +++ b/drivers/infiniband/hw/i40iw/i40iw_ctrl.c @@ -1046,7 +1046,7 @@ i40iw_sc_query_rdma_features(struct i40iw_sc_cqp *cqp, u64 header; wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch); - if (wqe) + if (!wqe) return I40IW_ERR_RING_FULL; set_64bit_val(wqe, 32, feat_mem->pa); From 0c6949c3d1b284d90473834f2fb865368a12f30a Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Mon, 6 Apr 2020 20:32:42 +0300 Subject: [PATCH 02/11] RDMA/cm: Fix missing RDMA_CM_EVENT_REJECTED event after receiving REJ message The cm_reset_to_idle() call before formatting event changed the CM_ID state from IB_CM_REQ_RCVD to be IB_CM_IDLE. It caused to wrong value of CM_REJ_MESSAGE_REJECTED field. The result of that was that rdma_reject() calls in the passive side didn't generate RDMA_CM_EVENT_REJECTED event in the active side. Fixes: 81ddb41f876d ("RDMA/cm: Allow ib_send_cm_rej() to be done under lock") Link: https://lore.kernel.org/r/20200406173242.1465911-1-leon@kernel.org Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/cm.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 4794113ecd59..5d729bd9ad90 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -1828,11 +1828,9 @@ static void cm_format_mra(struct cm_mra_msg *mra_msg, static void cm_format_rej(struct cm_rej_msg *rej_msg, struct cm_id_private *cm_id_priv, - enum ib_cm_rej_reason reason, - void *ari, - u8 ari_length, - const void *private_data, - u8 private_data_len) + enum ib_cm_rej_reason reason, void *ari, + u8 ari_length, const void *private_data, + u8 private_data_len, enum ib_cm_state state) { lockdep_assert_held(&cm_id_priv->lock); @@ -1840,7 +1838,7 @@ static void cm_format_rej(struct cm_rej_msg *rej_msg, IBA_SET(CM_REJ_REMOTE_COMM_ID, rej_msg, be32_to_cpu(cm_id_priv->id.remote_id)); - switch(cm_id_priv->id.state) { + switch (state) { case IB_CM_REQ_RCVD: IBA_SET(CM_REJ_LOCAL_COMM_ID, rej_msg, be32_to_cpu(0)); IBA_SET(CM_REJ_MESSAGE_REJECTED, rej_msg, CM_MSG_RESPONSE_REQ); @@ -1905,8 +1903,9 @@ static void cm_dup_req_handler(struct cm_work *work, cm_id_priv->private_data_len); break; case IB_CM_TIMEWAIT: - cm_format_rej((struct cm_rej_msg *) msg->mad, cm_id_priv, - IB_CM_REJ_STALE_CONN, NULL, 0, NULL, 0); + cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, + IB_CM_REJ_STALE_CONN, NULL, 0, NULL, 0, + IB_CM_TIMEWAIT); break; default: goto unlock; @@ -2904,6 +2903,7 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv, u8 ari_length, const void *private_data, u8 private_data_len) { + enum ib_cm_state state = cm_id_priv->id.state; struct ib_mad_send_buf *msg; int ret; @@ -2913,7 +2913,7 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv, (ari && ari_length > IB_CM_REJ_ARI_LENGTH)) return -EINVAL; - switch (cm_id_priv->id.state) { + switch (state) { case IB_CM_REQ_SENT: case IB_CM_MRA_REQ_RCVD: case IB_CM_REQ_RCVD: @@ -2925,7 +2925,8 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv, if (ret) return ret; cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason, - ari, ari_length, private_data, private_data_len); + ari, ari_length, private_data, private_data_len, + state); break; case IB_CM_REP_SENT: case IB_CM_MRA_REP_RCVD: @@ -2934,7 +2935,8 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv, if (ret) return ret; cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason, - ari, ari_length, private_data, private_data_len); + ari, ari_length, private_data, private_data_len, + state); break; default: pr_debug("%s: local_id %d, cm_id->state: %d\n", __func__, From 983653515849fb56b78ce55d349bb384d43030f6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 7 Apr 2020 12:37:14 +0300 Subject: [PATCH 03/11] RDMA/cm: Fix an error check in cm_alloc_id_priv() The xa_alloc_cyclic_irq() function returns either 0 or 1 on success and negatives on error. This code treats 1 as an error and returns ERR_PTR(1) which will cause an Oops in the caller. Fixes: ae78ff3a0f0c ("RDMA/cm: Convert local_id_table to XArray") Link: https://lore.kernel.org/r/20200407093714.GA80285@mwanda Signed-off-by: Dan Carpenter Reviewed-by: Matthew Wilcox (Oracle) Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 5d729bd9ad90..17f14e0eafe4 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -862,7 +862,7 @@ static struct cm_id_private *cm_alloc_id_priv(struct ib_device *device, ret = xa_alloc_cyclic_irq(&cm.local_id_table, &id, NULL, xa_limit_32b, &cm.local_id_next, GFP_KERNEL); - if (ret) + if (ret < 0) goto error; cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand; From c08cfb2d8d78bfe81b37cc6ba84f0875bddd0d5c Mon Sep 17 00:00:00 2001 From: Alaa Hleihel Date: Mon, 13 Apr 2020 16:22:35 +0300 Subject: [PATCH 04/11] RDMA/mlx4: Initialize ib_spec on the stack Initialize ib_spec on the stack before using it, otherwise we will have garbage values that will break creating default rules with invalid parsing error. Fixes: a37a1a428431 ("IB/mlx4: Add mechanism to support flow steering over IB links") Link: https://lore.kernel.org/r/20200413132235.930642-1-leon@kernel.org Signed-off-by: Alaa Hleihel Reviewed-by: Maor Gottlieb Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe --- drivers/infiniband/hw/mlx4/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index a66518a5c938..275722cec8c6 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -1499,8 +1499,9 @@ static int __mlx4_ib_create_default_rules( int i; for (i = 0; i < ARRAY_SIZE(pdefault_rules->rules_create_list); i++) { + union ib_flow_spec ib_spec = {}; int ret; - union ib_flow_spec ib_spec; + switch (pdefault_rules->rules_create_list[i]) { case 0: /* no rule */ From 6e051971b0e2eeb0ce7ec65d3cc8180450512d36 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Wed, 15 Apr 2020 11:09:22 -0300 Subject: [PATCH 05/11] RDMA/siw: Fix potential siw_mem refcnt leak in siw_fastreg_mr() siw_fastreg_mr() invokes siw_mem_id2obj(), which returns a local reference of the siw_mem object to "mem" with increased refcnt. When siw_fastreg_mr() returns, "mem" becomes invalid, so the refcount should be decreased to keep refcount balanced. The issue happens in one error path of siw_fastreg_mr(). When "base_mr" equals to NULL but "mem" is not NULL, the function forgets to decrease the refcnt increased by siw_mem_id2obj() and causes a refcnt leak. Reorganize the flow so that the goto unwind can be used as expected. Fixes: b9be6f18cf9e ("rdma/siw: transmit path") Link: https://lore.kernel.org/r/1586939949-69856-1-git-send-email-xiyuyang19@fudan.edu.cn Reported-by: Xiyu Yang Signed-off-by: Jason Gunthorpe --- drivers/infiniband/sw/siw/siw_qp_tx.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/sw/siw/siw_qp_tx.c b/drivers/infiniband/sw/siw/siw_qp_tx.c index ae92c8080967..9f53aa4feb87 100644 --- a/drivers/infiniband/sw/siw/siw_qp_tx.c +++ b/drivers/infiniband/sw/siw/siw_qp_tx.c @@ -920,20 +920,27 @@ static int siw_fastreg_mr(struct ib_pd *pd, struct siw_sqe *sqe) { struct ib_mr *base_mr = (struct ib_mr *)(uintptr_t)sqe->base_mr; struct siw_device *sdev = to_siw_dev(pd->device); - struct siw_mem *mem = siw_mem_id2obj(sdev, sqe->rkey >> 8); + struct siw_mem *mem; int rv = 0; siw_dbg_pd(pd, "STag 0x%08x\n", sqe->rkey); - if (unlikely(!mem || !base_mr)) { + if (unlikely(!base_mr)) { pr_warn("siw: fastreg: STag 0x%08x unknown\n", sqe->rkey); return -EINVAL; } + if (unlikely(base_mr->rkey >> 8 != sqe->rkey >> 8)) { pr_warn("siw: fastreg: STag 0x%08x: bad MR\n", sqe->rkey); - rv = -EINVAL; - goto out; + return -EINVAL; } + + mem = siw_mem_id2obj(sdev, sqe->rkey >> 8); + if (unlikely(!mem)) { + pr_warn("siw: fastreg: STag 0x%08x unknown\n", sqe->rkey); + return -EINVAL; + } + if (unlikely(mem->pd != pd)) { pr_warn("siw: fastreg: PD mismatch\n"); rv = -EINVAL; From 2d7e3ff7b6f2c614eb21d0dc348957a47eaffb57 Mon Sep 17 00:00:00 2001 From: Aharon Landau Date: Mon, 13 Apr 2020 16:20:28 +0300 Subject: [PATCH 06/11] RDMA/mlx5: Set GRH fields in query QP on RoCE GRH fields such as sgid_index, hop limit, et. are set in the QP context when QP is created/modified. Currently, when query QP is performed, we fill the GRH fields only if the GRH bit is set in the QP context, but this bit is not set for RoCE. Adjust the check so we will set all relevant data for the RoCE too. Since this data is returned to userspace, the below is an ABI regression. Fixes: d8966fcd4c25 ("IB/core: Use rdma_ah_attr accessor functions") Link: https://lore.kernel.org/r/20200413132028.930109-1-leon@kernel.org Signed-off-by: Aharon Landau Reviewed-by: Maor Gottlieb Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe --- drivers/infiniband/hw/mlx5/qp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 1456db4b6295..2210759843ba 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -5558,7 +5558,9 @@ static void to_rdma_ah_attr(struct mlx5_ib_dev *ibdev, rdma_ah_set_path_bits(ah_attr, path->grh_mlid & 0x7f); rdma_ah_set_static_rate(ah_attr, path->static_rate ? path->static_rate - 5 : 0); - if (path->grh_mlid & (1 << 7)) { + + if (path->grh_mlid & (1 << 7) || + ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) { u32 tc_fl = be32_to_cpu(path->tclass_flowlabel); rdma_ah_set_grh(ah_attr, NULL, From 39c011a538272589b9eb02ff1228af528522a22c Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Mon, 13 Apr 2020 16:21:36 +0300 Subject: [PATCH 07/11] RDMA/uverbs: Fix a race with disassociate and exit_mmap() If uverbs_user_mmap_disassociate() is called while the mmap is concurrently doing exit_mmap then the ordering of the rdma_user_mmap_entry_put() is not reliable. The put must be done before uvers_user_mmap_disassociate() returns, otherwise there can be a use after free on the ucontext, and a left over entry in the xarray. If the put is not done here then it is done during rdma_umap_close() later. Add the missing put to the error exit path. WARNING: CPU: 7 PID: 7111 at drivers/infiniband/core/rdma_core.c:810 uverbs_destroy_ufile_hw+0x2a5/0x340 [ib_uverbs] Modules linked in: bonding ipip tunnel4 geneve ip6_udp_tunnel udp_tunnel ip6_gre ip6_tunnel tunnel6 ip_gre ip_tunnel gre mlx5_ib mlx5_core mlxfw pci_hyperv_intf act_ct nf_flow_table ptp pps_core rdma_ucm ib_uverbs ib_ipoib ib_umad 8021q garp mrp openvswitch nsh nf_conncount nfsv3 nfs_acl xt_MASQUERADE nf_conntrack_netlink nfnetlink iptable_nat xt_addrtype iptable_filter xt_conntrack br_netfilter bridge stp llc rpcsec_gss_krb5 auth_rpcgss nfsv4 dns_resolver nfs lockd grace fscache overlay rpcrdma ib_isert iscsi_target_mod ib_iser kvm_intel ib_srpt iTCO_wdt target_core_mod iTCO_vendor_support kvm ib_srp nf_nat irqbypass crc32_pclmul crc32c_intel nf_conntrack rfkill nf_defrag_ipv6 virtio_net nf_defrag_ipv4 pcspkr ghash_clmulni_intel i2c_i801 net_failover failover i2c_core lpc_ich mfd_core rdma_cm ib_cm iw_cm button ib_core sunrpc sch_fq_codel ip_tables serio_raw [last unloaded: tunnel4] CPU: 7 PID: 7111 Comm: python3 Tainted: G W 5.6.0-rc6-for-upstream-dbg-2020-03-21_06-41-26-18 #1 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 RIP: 0010:uverbs_destroy_ufile_hw+0x2a5/0x340 [ib_uverbs] Code: ff df 48 89 fa 48 c1 ea 03 80 3c 02 00 75 74 49 8b 84 24 08 01 00 00 48 85 c0 0f 84 13 ff ff ff 48 89 ef ff d0 e9 09 ff ff ff <0f> 0b e9 77 ff ff ff e8 0f d8 fa e0 e9 c5 fd ff ff e8 05 d8 fa e0 RSP: 0018:ffff88840e0779a0 EFLAGS: 00010286 RAX: dffffc0000000000 RBX: ffff8882a7721c00 RCX: 0000000000000000 RDX: 1ffff11054ee469f RSI: ffffffff8446d7e0 RDI: ffff8882a77234f8 RBP: ffff8882a7723400 R08: ffffed1085c0112c R09: 0000000000000001 R10: 0000000000000001 R11: ffffed1085c0112b R12: ffff888403c30000 R13: 0000000000000002 R14: ffff8882a7721cb0 R15: ffff8882a7721cd0 FS: 00007f2046089700(0000) GS:ffff88842de00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f7cfe9a6e20 CR3: 000000040b8ac006 CR4: 0000000000360ee0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: ib_uverbs_remove_one+0x273/0x480 [ib_uverbs] ? up_write+0x15c/0x4a0 remove_client_context+0xa6/0xf0 [ib_core] disable_device+0x12d/0x200 [ib_core] ? remove_client_context+0xf0/0xf0 [ib_core] ? mnt_get_count+0x1d0/0x1d0 __ib_unregister_device+0x79/0x150 [ib_core] ib_unregister_device+0x21/0x30 [ib_core] __mlx5_ib_remove+0x91/0x110 [mlx5_ib] ? __mlx5_ib_remove+0x110/0x110 [mlx5_ib] mlx5_remove_device+0x241/0x310 [mlx5_core] mlx5_unregister_device+0x4d/0x1e0 [mlx5_core] mlx5_unload_one+0xc0/0x260 [mlx5_core] remove_one+0x5c/0x160 [mlx5_core] pci_device_remove+0xef/0x2a0 ? pcibios_free_irq+0x10/0x10 device_release_driver_internal+0x1d8/0x470 unbind_store+0x152/0x200 ? sysfs_kf_write+0x3b/0x180 ? sysfs_file_ops+0x160/0x160 kernfs_fop_write+0x284/0x460 ? __sb_start_write+0x243/0x3a0 vfs_write+0x197/0x4a0 ksys_write+0x156/0x1e0 ? __x64_sys_read+0xb0/0xb0 ? do_syscall_64+0x73/0x1330 ? do_syscall_64+0x73/0x1330 do_syscall_64+0xe7/0x1330 ? down_write_nested+0x3e0/0x3e0 ? syscall_return_slowpath+0x970/0x970 ? entry_SYSCALL_64_after_hwframe+0x3e/0xbe ? lockdep_hardirqs_off+0x1de/0x2d0 ? trace_hardirqs_off_thunk+0x1a/0x1c entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x7f20a3ff0cdb Code: 53 48 89 d5 48 89 f3 48 83 ec 18 48 89 7c 24 08 e8 5a fd ff ff 48 89 ea 41 89 c0 48 89 de 48 8b 7c 24 08 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 31 44 89 c7 48 89 44 24 08 e8 90 fd ff ff 48 RSP: 002b:00007f2046087040 EFLAGS: 00000293 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 00007f2038016df0 RCX: 00007f20a3ff0cdb RDX: 000000000000000d RSI: 00007f2038016df0 RDI: 0000000000000018 RBP: 000000000000000d R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000100 R11: 0000000000000293 R12: 00007f2046e29630 R13: 00007f20280035a0 R14: 0000000000000018 R15: 00007f2038016df0 Fixes: c043ff2cfb7f ("RDMA: Connect between the mmap entry and the umap_priv structure") Link: https://lore.kernel.org/r/20200413132136.930388-1-leon@kernel.org Signed-off-by: Yishai Hadas Signed-off-by: Leon Romanovsky Reviewed-by: Jason Gunthorpe Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/uverbs_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 2d4083bf4a04..17fc25db0311 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -820,6 +820,10 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) ret = mmget_not_zero(mm); if (!ret) { list_del_init(&priv->list); + if (priv->entry) { + rdma_user_mmap_entry_put(priv->entry); + priv->entry = NULL; + } mm = NULL; continue; } From 0fb00941dc63990a10951146df216fc7b0e20bc2 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Tue, 21 Apr 2020 11:29:28 +0300 Subject: [PATCH 08/11] RDMA/core: Prevent mixed use of FDs between shared ufiles FDs can only be used on the ufile that created them, they cannot be mixed to other ufiles. We are lacking a check to prevent it. BUG: KASAN: null-ptr-deref in atomic64_sub_and_test include/asm-generic/atomic-instrumented.h:1547 [inline] BUG: KASAN: null-ptr-deref in atomic_long_sub_and_test include/asm-generic/atomic-long.h:460 [inline] BUG: KASAN: null-ptr-deref in fput_many+0x1a/0x140 fs/file_table.c:336 Write of size 8 at addr 0000000000000038 by task syz-executor179/284 CPU: 0 PID: 284 Comm: syz-executor179 Not tainted 5.5.0-rc5+ #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x94/0xce lib/dump_stack.c:118 __kasan_report+0x18f/0x1b7 mm/kasan/report.c:510 kasan_report+0xe/0x20 mm/kasan/common.c:639 check_memory_region_inline mm/kasan/generic.c:185 [inline] check_memory_region+0x15d/0x1b0 mm/kasan/generic.c:192 atomic64_sub_and_test include/asm-generic/atomic-instrumented.h:1547 [inline] atomic_long_sub_and_test include/asm-generic/atomic-long.h:460 [inline] fput_many+0x1a/0x140 fs/file_table.c:336 rdma_lookup_put_uobject+0x85/0x130 drivers/infiniband/core/rdma_core.c:692 uobj_put_read include/rdma/uverbs_std_types.h:96 [inline] _ib_uverbs_lookup_comp_file drivers/infiniband/core/uverbs_cmd.c:198 [inline] create_cq+0x375/0xba0 drivers/infiniband/core/uverbs_cmd.c:1006 ib_uverbs_create_cq+0x114/0x140 drivers/infiniband/core/uverbs_cmd.c:1089 ib_uverbs_write+0xaa5/0xdf0 drivers/infiniband/core/uverbs_main.c:769 __vfs_write+0x7c/0x100 fs/read_write.c:494 vfs_write+0x168/0x4a0 fs/read_write.c:558 ksys_write+0xc8/0x200 fs/read_write.c:611 do_syscall_64+0x9c/0x390 arch/x86/entry/common.c:294 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x44ef99 Code: 00 b8 00 01 00 00 eb e1 e8 74 1c 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c4 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffc0b74c028 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 00007ffc0b74c030 RCX: 000000000044ef99 RDX: 0000000000000040 RSI: 0000000020000040 RDI: 0000000000000005 RBP: 00007ffc0b74c038 R08: 0000000000401830 R09: 0000000000401830 R10: 00007ffc0b74c038 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000000 R14: 00000000006be018 R15: 0000000000000000 Fixes: cf8966b3477d ("IB/core: Add support for fd objects") Link: https://lore.kernel.org/r/20200421082929.311931-2-leon@kernel.org Suggested-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/rdma_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c index 5128cb16bb48..8f480de5596a 100644 --- a/drivers/infiniband/core/rdma_core.c +++ b/drivers/infiniband/core/rdma_core.c @@ -360,7 +360,7 @@ lookup_get_fd_uobject(const struct uverbs_api_object *obj, * uverbs_uobject_fd_release(), and the caller is expected to ensure * that release is never done while a call to lookup is possible. */ - if (f->f_op != fd_type->fops) { + if (f->f_op != fd_type->fops || uobject->ufile != ufile) { fput(f); return ERR_PTR(-EBADF); } From 83a2670212215a569ed133efc10c92055c96cc8c Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Tue, 21 Apr 2020 11:29:29 +0300 Subject: [PATCH 09/11] RDMA/core: Fix overwriting of uobj in case of error In case of failure to get file, the uobj is overwritten and causes to supply bad pointer as an input to uverbs_uobject_put(). BUG: KASAN: null-ptr-deref in atomic_fetch_sub include/asm-generic/atomic-instrumented.h:199 [inline] BUG: KASAN: null-ptr-deref in refcount_sub_and_test include/linux/refcount.h:253 [inline] BUG: KASAN: null-ptr-deref in refcount_dec_and_test include/linux/refcount.h:281 [inline] BUG: KASAN: null-ptr-deref in kref_put include/linux/kref.h:64 [inline] BUG: KASAN: null-ptr-deref in uverbs_uobject_put+0x22/0x90 drivers/infiniband/core/rdma_core.c:57 Write of size 4 at addr 0000000000000030 by task syz-executor.4/1691 CPU: 1 PID: 1691 Comm: syz-executor.4 Not tainted 5.6.0 #17 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x94/0xce lib/dump_stack.c:118 __kasan_report+0x10c/0x190 mm/kasan/report.c:515 kasan_report+0x32/0x50 mm/kasan/common.c:625 check_memory_region_inline mm/kasan/generic.c:187 [inline] check_memory_region+0x16d/0x1c0 mm/kasan/generic.c:193 atomic_fetch_sub include/asm-generic/atomic-instrumented.h:199 [inline] refcount_sub_and_test include/linux/refcount.h:253 [inline] refcount_dec_and_test include/linux/refcount.h:281 [inline] kref_put include/linux/kref.h:64 [inline] uverbs_uobject_put+0x22/0x90 drivers/infiniband/core/rdma_core.c:57 alloc_begin_fd_uobject+0x1d0/0x250 drivers/infiniband/core/rdma_core.c:486 rdma_alloc_begin_uobject+0xa8/0xf0 drivers/infiniband/core/rdma_core.c:509 __uobj_alloc include/rdma/uverbs_std_types.h:117 [inline] ib_uverbs_create_comp_channel+0x16d/0x230 drivers/infiniband/core/uverbs_cmd.c:982 ib_uverbs_write+0xaa5/0xdf0 drivers/infiniband/core/uverbs_main.c:665 __vfs_write+0x7c/0x100 fs/read_write.c:494 vfs_write+0x168/0x4a0 fs/read_write.c:558 ksys_write+0xc8/0x200 fs/read_write.c:611 do_syscall_64+0x9c/0x390 arch/x86/entry/common.c:295 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x466479 Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007efe9f6a7c48 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 000000000073bf00 RCX: 0000000000466479 RDX: 0000000000000018 RSI: 0000000020000040 RDI: 0000000000000003 RBP: 00007efe9f6a86bc R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000005 R13: 0000000000000bf2 R14: 00000000004cb80a R15: 00000000006fefc0 Fixes: 849e149063bd ("RDMA/core: Do not allow alloc_commit to fail") Link: https://lore.kernel.org/r/20200421082929.311931-3-leon@kernel.org Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/rdma_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c index 8f480de5596a..2947f4f83561 100644 --- a/drivers/infiniband/core/rdma_core.c +++ b/drivers/infiniband/core/rdma_core.c @@ -474,16 +474,15 @@ alloc_begin_fd_uobject(const struct uverbs_api_object *obj, filp = anon_inode_getfile(fd_type->name, fd_type->fops, NULL, fd_type->flags); if (IS_ERR(filp)) { + uverbs_uobject_put(uobj); uobj = ERR_CAST(filp); - goto err_uobj; + goto err_fd; } uobj->object = filp; uobj->id = new_fd; return uobj; -err_uobj: - uverbs_uobject_put(uobj); err_fd: put_unused_fd(new_fd); return uobj; From 47c370c1a5eea9b2f6f026d49e060c3748c89667 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 24 Apr 2020 18:31:46 +0100 Subject: [PATCH 10/11] IB/rdmavt: Always return ERR_PTR from rvt_create_mmap_info() The commit below modified rvt_create_mmap_info() to return ERR_PTR's but didn't update the callers to handle them. Modify rvt_create_mmap_info() to only return ERR_PTR and fix all error checking after rvt_create_mmap_info() was called. Fixes: ff23dfa13457 ("IB: Pass only ib_udata in function prototypes") Link: https://lore.kernel.org/r/20200424173146.10970-1-sudipm.mukherjee@gmail.com Cc: stable@vger.kernel.org [5.4+] Tested-by: Mike Marciniszyn Acked-by: Mike Marciniszyn Signed-off-by: Sudip Mukherjee Signed-off-by: Jason Gunthorpe --- drivers/infiniband/sw/rdmavt/cq.c | 4 ++-- drivers/infiniband/sw/rdmavt/mmap.c | 4 ++-- drivers/infiniband/sw/rdmavt/qp.c | 4 ++-- drivers/infiniband/sw/rdmavt/srq.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/sw/rdmavt/cq.c b/drivers/infiniband/sw/rdmavt/cq.c index 5724cbbe38b1..04d2e72017fe 100644 --- a/drivers/infiniband/sw/rdmavt/cq.c +++ b/drivers/infiniband/sw/rdmavt/cq.c @@ -248,8 +248,8 @@ int rvt_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, */ if (udata && udata->outlen >= sizeof(__u64)) { cq->ip = rvt_create_mmap_info(rdi, sz, udata, u_wc); - if (!cq->ip) { - err = -ENOMEM; + if (IS_ERR(cq->ip)) { + err = PTR_ERR(cq->ip); goto bail_wc; } diff --git a/drivers/infiniband/sw/rdmavt/mmap.c b/drivers/infiniband/sw/rdmavt/mmap.c index 652f4a7efc1b..37853aa3bcf7 100644 --- a/drivers/infiniband/sw/rdmavt/mmap.c +++ b/drivers/infiniband/sw/rdmavt/mmap.c @@ -154,7 +154,7 @@ done: * @udata: user data (must be valid!) * @obj: opaque pointer to a cq, wq etc * - * Return: rvt_mmap struct on success + * Return: rvt_mmap struct on success, ERR_PTR on failure */ struct rvt_mmap_info *rvt_create_mmap_info(struct rvt_dev_info *rdi, u32 size, struct ib_udata *udata, void *obj) @@ -166,7 +166,7 @@ struct rvt_mmap_info *rvt_create_mmap_info(struct rvt_dev_info *rdi, u32 size, ip = kmalloc_node(sizeof(*ip), GFP_KERNEL, rdi->dparms.node); if (!ip) - return ip; + return ERR_PTR(-ENOMEM); size = PAGE_ALIGN(size); diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 0e1b291d2cec..500a7ee04c44 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -1244,8 +1244,8 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, qp->ip = rvt_create_mmap_info(rdi, s, udata, qp->r_rq.wq); - if (!qp->ip) { - ret = ERR_PTR(-ENOMEM); + if (IS_ERR(qp->ip)) { + ret = ERR_CAST(qp->ip); goto bail_qpn; } diff --git a/drivers/infiniband/sw/rdmavt/srq.c b/drivers/infiniband/sw/rdmavt/srq.c index 24fef021d51d..f547c115af03 100644 --- a/drivers/infiniband/sw/rdmavt/srq.c +++ b/drivers/infiniband/sw/rdmavt/srq.c @@ -111,8 +111,8 @@ int rvt_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *srq_init_attr, u32 s = sizeof(struct rvt_rwq) + srq->rq.size * sz; srq->ip = rvt_create_mmap_info(dev, s, udata, srq->rq.wq); - if (!srq->ip) { - ret = -ENOMEM; + if (IS_ERR(srq->ip)) { + ret = PTR_ERR(srq->ip); goto bail_wq; } From f0abc761bbb9418876cc4d1ebc473e4ea6352e42 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Thu, 23 Apr 2020 09:01:22 +0300 Subject: [PATCH 11/11] RDMA/core: Fix race between destroy and release FD object The call to ->lookup_put() was too early and it caused an unlock of the read/write protection of the uobject after the FD was put. This allows a race: CPU1 CPU2 rdma_lookup_put_uobject() lookup_put_fd_uobject() fput() fput() uverbs_uobject_fd_release() WARN_ON(uverbs_try_lock_object(uobj, UVERBS_LOOKUP_WRITE)); atomic_dec(usecnt) Fix the code by changing the order, first unlock and call to ->lookup_put() after that. Fixes: 3832125624b7 ("IB/core: Add support for idr types") Link: https://lore.kernel.org/r/20200423060122.6182-1-leon@kernel.org Suggested-by: Jason Gunthorpe Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/rdma_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c index 2947f4f83561..177333d8bcda 100644 --- a/drivers/infiniband/core/rdma_core.c +++ b/drivers/infiniband/core/rdma_core.c @@ -678,7 +678,6 @@ void rdma_lookup_put_uobject(struct ib_uobject *uobj, enum rdma_lookup_mode mode) { assert_uverbs_usecnt(uobj, mode); - uobj->uapi_object->type_class->lookup_put(uobj, mode); /* * In order to unlock an object, either decrease its usecnt for * read access or zero it in case of exclusive access. See @@ -695,6 +694,7 @@ void rdma_lookup_put_uobject(struct ib_uobject *uobj, break; } + uobj->uapi_object->type_class->lookup_put(uobj, mode); /* Pairs with the kref obtained by type->lookup_get */ uverbs_uobject_put(uobj); }