From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2F101A0A0E for ; Wed, 7 Apr 2021 16:49:35 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 20ED3140F67; Wed, 7 Apr 2021 16:49:35 +0200 (CEST) Received: from mail-qk1-f182.google.com (mail-qk1-f182.google.com [209.85.222.182]) by mails.dpdk.org (Postfix) with ESMTP id 13A184013F; Wed, 7 Apr 2021 16:49:33 +0200 (CEST) Received: by mail-qk1-f182.google.com with SMTP id c3so18950425qkc.5; Wed, 07 Apr 2021 07:49:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=g6cSOZ+zW04ZJUn3Pb7pg5Psf57bIkbn1yKx+8ERLyY=; b=IrScBmFrxy8+LLiZKngM+f9Z9achDG+e5c9dFn91jdQSBspi/unM69/brXpir8/Wkt Xka46i0g/cm6JAVK4Kx6psUhtZHpI0E3AsDPHnuo8dFhVWeC58okaGWgSM02SkkToJ3w S4RiuKTfncuEGetySJ/xJuyJF8htf2SuWm5JQ+1OMN3WoSYbl/FLmfQhzUMvrtcQzEdO 6pAm3p2KB3XyCGJyTHgh9eobmwDrHjURv5D+1SVsAlPkR5MQ1Un3cgy+DqGHlhJXE8Bc 1j0PWYNdZ5mGXI6aso7wOkASeiH0dqkI+KSCc1oIuyquzKG/h7IHX6UUf44yTSP0pYOg HR5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=g6cSOZ+zW04ZJUn3Pb7pg5Psf57bIkbn1yKx+8ERLyY=; b=acEuwl1s/yc7Ik7HxU1CUI1dpTxlGeMpESd0ukqxbG7Ug7RxnoDfa6VaY6Pu/jwsy8 yV/YkfXnhg84IK16sA6TjjpKb3Fl2CuYPLYNuwSlLCzrBYAGBcWuWeYuOuEgEz3hz8E3 v2l4s6JskdOegQX1NiUWZ0W60xStH2ozZ8Bm/3yAVSg2wBnhhc1Qhq1+tMeIyafqNDRQ 8NN8vvV6VzqtjFAKf+aNC9yvZ2ecRi7d9tOvk8AqrsDTijjcOeov//RaCybR9NnQH9VX ovv0t/rCDd0oSH4p8adYtyNPb1AKZMj3ELz2hlUuDB3u5ukykW4Itw6/kAynJKDwmjOd 6c+g== X-Gm-Message-State: AOAM530CbdNCUvwS+4gnKSweI7WqGABKnOmLIRHQV4duu8tmJsqEglGm CArEynLiV1/VFppDoMGZ3Ns= X-Google-Smtp-Source: ABdhPJxCcj1MZNidz9Y4TGk84TeOX7aHSrKQZVkMJLKEyvY4Rv7mcJPYyvozTHElxra8cp7LCT1Y2Q== X-Received: by 2002:a05:620a:53d:: with SMTP id h29mr3467532qkh.29.1617806972503; Wed, 07 Apr 2021 07:49:32 -0700 (PDT) Received: from localhost.localdomain (bras-base-hullpq2034w-grc-18-74-15-213-92.dsl.bell.ca. [74.15.213.92]) by smtp.gmail.com with ESMTPSA id t24sm16682335qto.23.2021.04.07.07.49.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Apr 2021 07:49:32 -0700 (PDT) From: Luc Pelletier To: olivier.matz@6wind.com, jianfeng.tan@intel.com, Honnappa.Nagarahalli@arm.com Cc: dev@dpdk.org, Luc Pelletier , stable@dpdk.org Date: Wed, 7 Apr 2021 10:42:37 -0400 Message-Id: <20210407144236.128365-1-lucp.at.work@gmail.com> In-Reply-To: <20210407133105.GL1650@platinum> References: <20210407133105.GL1650@platinum> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-stable] [PATCH v6] eal: fix race in ctrl thread creation X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: stable-bounces@dpdk.org Sender: "stable" The creation of control threads uses a pthread barrier for synchronization. This patch fixes a race condition where the pthread barrier could get destroyed while one of the threads has not yet returned from the pthread_barrier_wait function, which could result in undefined behaviour. Fixes: 3a0d465d4c53 ("eal: fix use-after-free on control thread creation") Cc: jianfeng.tan@intel.com Cc: stable@dpdk.org Signed-off-by: Luc Pelletier --- Hi Olivier, I've made the changes as you requested. However, I'm using the atomic built-ins for reading and writing start_routine; I think they're required to prevent any re-reordering. Please let me know what you think. lib/librte_eal/common/eal_common_thread.c | 63 +++++++++++++---------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/lib/librte_eal/common/eal_common_thread.c b/lib/librte_eal/common/eal_common_thread.c index 73a055902..fcb386f77 100644 --- a/lib/librte_eal/common/eal_common_thread.c +++ b/lib/librte_eal/common/eal_common_thread.c @@ -170,25 +170,34 @@ struct rte_thread_ctrl_params { void *(*start_routine)(void *); void *arg; pthread_barrier_t configured; + unsigned int refcnt; }; +static void ctrl_params_free(struct rte_thread_ctrl_params *params) +{ + if (__atomic_sub_fetch(¶ms->refcnt, 1, __ATOMIC_ACQ_REL) == 0) { + pthread_barrier_destroy(¶ms->configured); + free(params); + } +} + static void *ctrl_thread_init(void *arg) { - int ret; struct internal_config *internal_conf = eal_get_internal_configuration(); rte_cpuset_t *cpuset = &internal_conf->ctrl_cpuset; struct rte_thread_ctrl_params *params = arg; - void *(*start_routine)(void *) = params->start_routine; + void *(*start_routine)(void *); void *routine_arg = params->arg; __rte_thread_init(rte_lcore_id(), cpuset); - ret = pthread_barrier_wait(¶ms->configured); - if (ret == PTHREAD_BARRIER_SERIAL_THREAD) { - pthread_barrier_destroy(¶ms->configured); - free(params); - } + pthread_barrier_wait(¶ms->configured); + start_routine = __atomic_load_n(¶ms->start_routine, __ATOMIC_ACQUIRE); + ctrl_params_free(params); + + if (start_routine == NULL) + return NULL; return start_routine(routine_arg); } @@ -210,14 +219,15 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name, params->start_routine = start_routine; params->arg = arg; + params->refcnt = 2; - pthread_barrier_init(¶ms->configured, NULL, 2); + ret = pthread_barrier_init(¶ms->configured, NULL, 2); + if (ret != 0) + goto fail_no_barrier; ret = pthread_create(thread, attr, ctrl_thread_init, (void *)params); - if (ret != 0) { - free(params); - return -ret; - } + if (ret != 0) + goto fail_with_barrier; if (name != NULL) { ret = rte_thread_setname(*thread, name); @@ -227,25 +237,22 @@ rte_ctrl_thread_create(pthread_t *thread, const char *name, } ret = pthread_setaffinity_np(*thread, sizeof(*cpuset), cpuset); - if (ret) - goto fail; + if (ret != 0) + __atomic_store_n(¶ms->start_routine, NULL, __ATOMIC_RELEASE); + pthread_barrier_wait(¶ms->configured); + ctrl_params_free(params); - ret = pthread_barrier_wait(¶ms->configured); - if (ret == PTHREAD_BARRIER_SERIAL_THREAD) { - pthread_barrier_destroy(¶ms->configured); - free(params); - } + if (ret != 0) + pthread_join(*thread, NULL); - return 0; + return -ret; + +fail_with_barrier: + pthread_barrier_destroy(¶ms->configured); + +fail_no_barrier: + free(params); -fail: - if (PTHREAD_BARRIER_SERIAL_THREAD == - pthread_barrier_wait(¶ms->configured)) { - pthread_barrier_destroy(¶ms->configured); - free(params); - } - pthread_cancel(*thread); - pthread_join(*thread, NULL); return -ret; } -- 2.25.1