Received: by 2002:a05:6a10:22f:0:0:0:0 with SMTP id 15csp877979pxk; Thu, 17 Sep 2020 20:06:23 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw8IiqqWsUwx/jTCVDVvLIiUlKPqoLka3mUdr5hn1GV3WoTcVSoCNBdIr3/vnKXeuMnYvOr X-Received: by 2002:a17:906:6a52:: with SMTP id n18mr33118023ejs.58.1600398383230; Thu, 17 Sep 2020 20:06:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1600398383; cv=none; d=google.com; s=arc-20160816; b=TTaQLj2sgEfWkXRB6RBP3I3FzNzOk0gLvhm15yUP6Bt0FHjLfTYX3ah9p0p2a1Zykq wspt0fnGHzFyW4lEwG2AaXwmFdfLMvWkcLzqwnLIqR4nZWLGMcOBjdU0uV95dJjJEr/c 4dIAvEv+eHxlbAvOUGXPFOY0+ZIHV7oAWLBHzsjv2klmvksQKWiJLLIys+0fTtlrBvZt FCuej1U2O3kmtSrbDUPreJIYgeWvk5qXM9zKAgs5VA7Vkuk4lEls8ah+wrIIvO6zHq7T nZcPbu6FRjGEiLaMYvRH0saJA3f9XlCryefEiG9JC5cN9nbqNugaI4vTMBkKKsZ3H6n6 FOsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ijMc+dcLthW6wYHYBNBitI/5nhOOmSpfErhnjznQ+Bk=; b=qtaZae0LH51sfVLbyLD7ZSLd00RvQ/y8q6UYYc4LQb0+QVt1e8FLA7n5cdyDreSOiN z1Q/Q6SkKVuI+Un2zYgoQU9SqWs67Bltviy8VwgHpQViSCyS8Gcfe8J+s42U+LTRECRl VK9g0hqkXFslabsljK4fmeB1m3wAJZX2Rk0lyULjEEB5MexHaLLWkR291zlGK9355iGZ SvTAXuJaA6LtCS0zUhfXe8/GPugY1jX7BRYDyF1EmtNyR0B9Mhdq2HFFLwkeHM5Ek8o/ 3b9Ar9JCOetO6qMt3EHeDS4NjtlAEDx9QzLap2ss3ebJSAuLhabV0sbhrLKmLicoTGpn Th1A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=h3k+MDF2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id r14si1110113edb.14.2020.09.17.20.06.00; Thu, 17 Sep 2020 20:06:23 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=h3k+MDF2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726871AbgIRCE7 (ORCPT + 99 others); Thu, 17 Sep 2020 22:04:59 -0400 Received: from mail.kernel.org ([198.145.29.99]:52518 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726564AbgIRCEu (ORCPT ); Thu, 17 Sep 2020 22:04:50 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id D031023718; Fri, 18 Sep 2020 02:04:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1600394689; bh=a8TAtyVBLWhSc13/EqI2FOiHMoVAkw2IHfHbUIO1nmo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=h3k+MDF29JQXsNUvGFaf1HtgZA21bsjYzNY9hmVk7bmMi00AypZ7NEOd6ddY86RM8 6SNR2M6G8tPSK/GNVhlT/mfmzDm4LqUg6EK6FQTuI2bQ+S/HOc+N4Zwa4WkG4LPCqH fMJHPta4i7RlBADAp0Vq2HUqKmDtE6XBE9EGp13Y= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Jason Gunthorpe , Leon Romanovsky , Sasha Levin , linux-rdma@vger.kernel.org Subject: [PATCH AUTOSEL 5.4 178/330] RDMA/cm: Remove a race freeing timewait_info Date: Thu, 17 Sep 2020 21:58:38 -0400 Message-Id: <20200918020110.2063155-178-sashal@kernel.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200918020110.2063155-1-sashal@kernel.org> References: <20200918020110.2063155-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jason Gunthorpe [ Upstream commit bede86a39d9dc3387ac00dcb8e1ac221676b2f25 ] When creating a cm_id during REQ the id immediately becomes visible to the other MAD handlers, and shortly after the state is moved to IB_CM_REQ_RCVD This allows cm_rej_handler() to run concurrently and free the work: CPU 0 CPU1 cm_req_handler() ib_create_cm_id() cm_match_req() id_priv->state = IB_CM_REQ_RCVD cm_rej_handler() cm_acquire_id() spin_lock(&id_priv->lock) switch (id_priv->state) case IB_CM_REQ_RCVD: cm_reset_to_idle() kfree(id_priv->timewait_info); goto destroy destroy: kfree(id_priv->timewait_info); id_priv->timewait_info = NULL Causing a double free or worse. Do not free the timewait_info without also holding the id_priv->lock. Simplify this entire flow by making the free unconditional during cm_destroy_id() and removing the confusing special case error unwind during creation of the timewait_info. This also fixes a leak of the timewait if cm_destroy_id() is called in IB_CM_ESTABLISHED with an XRC TGT QP. The state machine will be left in ESTABLISHED while it needed to transition through IB_CM_TIMEWAIT to release the timewait pointer. Also fix a leak of the timewait_info if the caller mis-uses the API and does ib_send_cm_reqs(). Fixes: a977049dacde ("[PATCH] IB: Add the kernel CM implementation") Link: https://lore.kernel.org/r/20200310092545.251365-4-leon@kernel.org Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe Signed-off-by: Sasha Levin --- drivers/infiniband/core/cm.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 09af96ec41dd6..c1d6a068f50fe 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -1092,14 +1092,22 @@ retest: break; } - spin_lock_irq(&cm.lock); + spin_lock_irq(&cm_id_priv->lock); + spin_lock(&cm.lock); + /* Required for cleanup paths related cm_req_handler() */ + if (cm_id_priv->timewait_info) { + cm_cleanup_timewait(cm_id_priv->timewait_info); + kfree(cm_id_priv->timewait_info); + cm_id_priv->timewait_info = NULL; + } if (!list_empty(&cm_id_priv->altr_list) && (!cm_id_priv->altr_send_port_not_ready)) list_del(&cm_id_priv->altr_list); if (!list_empty(&cm_id_priv->prim_list) && (!cm_id_priv->prim_send_port_not_ready)) list_del(&cm_id_priv->prim_list); - spin_unlock_irq(&cm.lock); + spin_unlock(&cm.lock); + spin_unlock_irq(&cm_id_priv->lock); cm_free_id(cm_id->local_id); cm_deref_id(cm_id_priv); @@ -1416,7 +1424,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, /* Verify that we're not in timewait. */ cm_id_priv = container_of(cm_id, struct cm_id_private, id); spin_lock_irqsave(&cm_id_priv->lock, flags); - if (cm_id->state != IB_CM_IDLE) { + if (cm_id->state != IB_CM_IDLE || WARN_ON(cm_id_priv->timewait_info)) { spin_unlock_irqrestore(&cm_id_priv->lock, flags); ret = -EINVAL; goto out; @@ -1434,12 +1442,12 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, param->ppath_sgid_attr, &cm_id_priv->av, cm_id_priv); if (ret) - goto error1; + goto out; if (param->alternate_path) { ret = cm_init_av_by_path(param->alternate_path, NULL, &cm_id_priv->alt_av, cm_id_priv); if (ret) - goto error1; + goto out; } cm_id->service_id = param->service_id; cm_id->service_mask = ~cpu_to_be64(0); @@ -1457,7 +1465,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg); if (ret) - goto error1; + goto out; req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad; cm_format_req(req_msg, cm_id_priv, param); @@ -1480,7 +1488,6 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, return 0; error2: cm_free_msg(cm_id_priv->msg); -error1: kfree(cm_id_priv->timewait_info); out: return ret; } EXPORT_SYMBOL(ib_send_cm_req); @@ -1965,7 +1972,7 @@ static int cm_req_handler(struct cm_work *work) pr_debug("%s: local_id %d, no listen_cm_id_priv\n", __func__, be32_to_cpu(cm_id->local_id)); ret = -EINVAL; - goto free_timeinfo; + goto destroy; } cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler; @@ -2050,8 +2057,6 @@ static int cm_req_handler(struct cm_work *work) rejected: atomic_dec(&cm_id_priv->refcount); cm_deref_id(listen_cm_id_priv); -free_timeinfo: - kfree(cm_id_priv->timewait_info); destroy: ib_destroy_cm_id(cm_id); return ret; -- 2.25.1