From patchwork Tue Nov 20 15:23:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anatoly Burakov X-Patchwork-Id: 48208 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id ACAB92B9E; Tue, 20 Nov 2018 16:23:25 +0100 (CET) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by dpdk.org (Postfix) with ESMTP id A35B22B94 for ; Tue, 20 Nov 2018 16:23:23 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Nov 2018 07:23:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,257,1539673200"; d="scan'208";a="90770146" Received: from irvmail001.ir.intel.com ([163.33.26.43]) by orsmga007.jf.intel.com with ESMTP; 20 Nov 2018 07:23:21 -0800 Received: from sivswdev01.ir.intel.com (sivswdev01.ir.intel.com [10.237.217.45]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id wAKFNLm2000555; Tue, 20 Nov 2018 15:23:21 GMT Received: from sivswdev01.ir.intel.com (localhost [127.0.0.1]) by sivswdev01.ir.intel.com with ESMTP id wAKFNK0K004468; Tue, 20 Nov 2018 15:23:20 GMT Received: (from aburakov@localhost) by sivswdev01.ir.intel.com with LOCAL id wAKFNK1D004457; Tue, 20 Nov 2018 15:23:20 GMT From: Anatoly Burakov To: dev@dpdk.org Cc: thomas@monjalon.net Date: Tue, 20 Nov 2018 15:23:20 +0000 Message-Id: <3ac0562bbdfbabbcb2bdf5fec9e0ffa777475e2b.1542727150.git.anatoly.burakov@intel.com> X-Mailer: git-send-email 1.7.0.7 Subject: [dpdk-dev] [PATCH] ipc: fix use-after-free on failed send X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Previous fix for rte_panic has moved setting of alarm before sending the message. This means that whether we send a message, the alarm would still trigger. The comment noted that cleanup would happen in the alarm handler, but that's not what actually happened - instead, in the event of failed send we freed the memory in-place, before putting the request on the queue. This works OK when the message is sent, but when sending the message fails, the alarm would still trigger with a pointer argument that points to non-existent memory, and cause memory corruption. There probably is a "proper" fix for this issue, with correct handling of sent vs. unsent requests, however it would be simpler just to sacrifice the sent request in the (extremely unlikely) event of alarm set failing. The other process would still send a response, but it will be ignored by the sender. Fixes: 45e5f49e87fb ("ipc: remove panic in async request") Signed-off-by: Anatoly Burakov --- lib/librte_eal/common/eal_common_proc.c | 36 ++++++++----------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c index f65ef56c0..375e98709 100644 --- a/lib/librte_eal/common/eal_common_proc.c +++ b/lib/librte_eal/common/eal_common_proc.c @@ -827,20 +827,17 @@ mp_request_async(const char *dst, struct rte_mp_msg *req, goto fail; } - /* - * set the alarm before sending message. there are two possible error - * scenarios to consider here: - * - * - if the alarm set fails, we free the memory right there - * - if the alarm set succeeds but sending message fails, then the alarm - * will trigger and clean up the memory - * - * Even if the alarm triggers too early (i.e. immediately), we're still - * holding the lock to pending requests queue, so the interrupt thread - * will just spin until we release the lock, and either release the - * memory, or doesn't find any pending requests in the queue because we - * never added any due to send message failure. - */ + ret = send_msg(dst, req, MP_REQ); + if (ret < 0) { + RTE_LOG(ERR, EAL, "Fail to send request %s:%s\n", + dst, req->name); + ret = -1; + goto fail; + } else if (ret == 0) { + ret = 0; + goto fail; + } + /* if alarm set fails, we simply ignore the reply */ if (rte_eal_alarm_set(ts->tv_sec * 1000000 + ts->tv_nsec / 1000, async_reply_handle, pending_req) < 0) { RTE_LOG(ERR, EAL, "Fail to set alarm for request %s:%s\n", @@ -848,17 +845,6 @@ mp_request_async(const char *dst, struct rte_mp_msg *req, ret = -1; goto fail; } - - ret = send_msg(dst, req, MP_REQ); - if (ret < 0) { - RTE_LOG(ERR, EAL, "Fail to send request %s:%s\n", - dst, req->name); - ret = -1; - goto fail; - } else if (ret == 0) { - ret = 0; - goto fail; - } TAILQ_INSERT_TAIL(&pending_requests.requests, pending_req, next); param->user_reply.nb_sent++;