Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp3109425pxb; Mon, 4 Apr 2022 08:02:20 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxDaClU77uxA5aw9WqYjuItFj/uBO5Frd5Tz3u9acrCzSQ+3IlEw/dywon13P5pb4JQwhuM X-Received: by 2002:a17:907:c0c:b0:6d1:8c46:6415 with SMTP id ga12-20020a1709070c0c00b006d18c466415mr531123ejc.326.1649084540469; Mon, 04 Apr 2022 08:02:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649084540; cv=none; d=google.com; s=arc-20160816; b=AxxUfKzss+i+WXrGnYEnIIn7E+yPVdpQ6mNz6aurjiB7/UHiZ2/fDp1j/ZocpHoqh+ kxE5MtKy6GLF5cm8xGeTrPRGaBUzhMhHsy/FHEZbf58bUF/MG8BauI/HdKS7kUFSQstr fvU3Bue4vp59n14mxqunI/I+AT6Ih2egLHbBuXaxI9VfF2UR6zLnRTXQcOdMZDfNMpzF ORvR/R8I0r/nDxE/X7vqlVc58I+bqKFYF0zdVI6Qgo2lL1kvlXiDM3V5bhHdpWs8h+zj pooTfPnpKdS22PqYftfSynakkhTZWiYuNQ9+khKAJin72d2gJHZic9tKf8MYab46EWUj zN+g== 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:dkim-filter; bh=Yas84WJ4NXuOO1nmdoxbY/IEroFAtoghAgKJn/H+CD0=; b=Pfotr6rzIZSc4Dn/AtqSmYjyl9YRnI8/d1AAQB2c4ss50OFXEUnDStRt7Cmh4GuNHd Gle7bFseWuiy4HWdUQPhyg5keIB8cIfBgsihMkf1juSvcZM11IRl8QsbXaD8dYvbXMou xtMa/VQkxdxHVsLJvMn8yvBbJdAQVMzUu0xb0vmhjrvwmrTqAK4rcloiEvsMXHe93Yi9 QVgBTPMdobACUlrsdaV63wi5ZPwthPxst4Z1pGYF+b/TfwZbghmC6TS8hI7TCvY1aQxG +RpkOvV7hfHtjcKAIdNv+1f8Yv4vQgDMjNmLULKOUeu+Y3QItXYoNmKc6YzCMWSx8F6p yGnw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linux.microsoft.com header.s=default header.b=dhUbokt6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.microsoft.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id x21-20020a1709064bd500b006e0da544495si6613302ejv.632.2022.04.04.08.01.52; Mon, 04 Apr 2022 08:02:20 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linux.microsoft.com header.s=default header.b=dhUbokt6; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.microsoft.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353565AbiDAXpw (ORCPT + 99 others); Fri, 1 Apr 2022 19:45:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56510 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353458AbiDAXpS (ORCPT ); Fri, 1 Apr 2022 19:45:18 -0400 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2A6EA38B4; Fri, 1 Apr 2022 16:43:27 -0700 (PDT) Received: from localhost.localdomain (c-73-140-2-214.hsd1.wa.comcast.net [73.140.2.214]) by linux.microsoft.com (Postfix) with ESMTPSA id 9979420DF56B; Fri, 1 Apr 2022 16:43:24 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 9979420DF56B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1648856604; bh=Yas84WJ4NXuOO1nmdoxbY/IEroFAtoghAgKJn/H+CD0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dhUbokt6fF7kUhY9WKZejckFnyXq56DxG2EH5WrzRIFSkLVvXphN7MMywu/xObLZM VeHaIL6aooc2sCuxNQyyRo4Khf/wzUAURYzJwHoYHInoT2DMt9B+BZy4nVQ2p4zPi5 7ZiAtRndev/D0kTenZkl9YpXR0z+JAMeD+/eJoZQ= From: Beau Belgrave To: rostedt@goodmis.org, mhiramat@kernel.org, mathieu.desnoyers@efficios.com Cc: linux-trace-devel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org, beaub@linux.microsoft.com Subject: [PATCH 5/7] tracing/user_events: Use refcount instead of atomic for ref tracking Date: Fri, 1 Apr 2022 16:43:07 -0700 Message-Id: <20220401234309.21252-6-beaub@linux.microsoft.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220401234309.21252-1-beaub@linux.microsoft.com> References: <20220401234309.21252-1-beaub@linux.microsoft.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-19.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,ENV_AND_HDR_SPF_MATCH,RCVD_IN_DNSWL_MED, SPF_HELO_PASS,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL, USER_IN_DEF_SPF_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org User processes could open up enough event references to cause rollovers. These could cause use after free scenarios, which we do not want. Switching to refcount APIs prevent this, but will leak memory once saturated. Once saturated, user processes can still use the events. This prevents a bad user process from stopping existing telemetry from being emitted. Link: https://lore.kernel.org/all/2059213643.196683.1648499088753.JavaMail.zimbra@efficios.com/ Reported-by: Mathieu Desnoyers Signed-off-by: Beau Belgrave --- kernel/trace/trace_events_user.c | 53 +++++++++++++++----------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c index f9bb7d37d76f..2bcae7abfa81 100644 --- a/kernel/trace/trace_events_user.c +++ b/kernel/trace/trace_events_user.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -57,7 +58,7 @@ static DECLARE_BITMAP(page_bitmap, MAX_EVENTS); * within a file a user_event might be created if it does not * already exist. These are globally used and their lifetime * is tied to the refcnt member. These cannot go away until the - * refcnt reaches zero. + * refcnt reaches one. */ struct user_event { struct tracepoint tracepoint; @@ -67,7 +68,7 @@ struct user_event { struct hlist_node node; struct list_head fields; struct list_head validators; - atomic_t refcnt; + refcount_t refcnt; int index; int flags; int min_size; @@ -105,6 +106,12 @@ static u32 user_event_key(char *name) return jhash(name, strlen(name), 0); } +static __always_inline __must_check +bool user_event_last_ref(struct user_event *user) +{ + return refcount_read(&user->refcnt) == 1; +} + static __always_inline __must_check size_t copy_nofault(void *addr, size_t bytes, struct iov_iter *i) { @@ -662,7 +669,7 @@ static struct user_event *find_user_event(char *name, u32 *outkey) hash_for_each_possible(register_table, user, node, key) if (!strcmp(EVENT_NAME(user), name)) { - atomic_inc(&user->refcnt); + refcount_inc(&user->refcnt); return user; } @@ -876,12 +883,12 @@ static int user_event_reg(struct trace_event_call *call, return ret; inc: - atomic_inc(&user->refcnt); + refcount_inc(&user->refcnt); update_reg_page_for(user); return 0; dec: update_reg_page_for(user); - atomic_dec(&user->refcnt); + refcount_dec(&user->refcnt); return 0; } @@ -907,7 +914,7 @@ static int user_event_create(const char *raw_command) ret = user_event_parse_cmd(name, &user); if (!ret) - atomic_dec(&user->refcnt); + refcount_dec(&user->refcnt); mutex_unlock(®_mutex); @@ -951,14 +958,14 @@ static bool user_event_is_busy(struct dyn_event *ev) { struct user_event *user = container_of(ev, struct user_event, devent); - return atomic_read(&user->refcnt) != 0; + return !user_event_last_ref(user); } static int user_event_free(struct dyn_event *ev) { struct user_event *user = container_of(ev, struct user_event, devent); - if (atomic_read(&user->refcnt) != 0) + if (!user_event_last_ref(user)) return -EBUSY; return destroy_user_event(user); @@ -1137,8 +1144,8 @@ static int user_event_parse(char *name, char *args, char *flags, user->index = index; - /* Ensure we track ref */ - atomic_inc(&user->refcnt); + /* Ensure we track self ref and caller ref (2) */ + refcount_set(&user->refcnt, 2); dyn_event_init(&user->devent, &user_event_dops); dyn_event_add(&user->devent, &user->call); @@ -1164,29 +1171,17 @@ static int user_event_parse(char *name, char *args, char *flags, static int delete_user_event(char *name) { u32 key; - int ret; struct user_event *user = find_user_event(name, &key); if (!user) return -ENOENT; - /* Ensure we are the last ref */ - if (atomic_read(&user->refcnt) != 1) { - ret = -EBUSY; - goto put_ref; - } - - ret = destroy_user_event(user); + refcount_dec(&user->refcnt); - if (ret) - goto put_ref; - - return ret; -put_ref: - /* No longer have this ref */ - atomic_dec(&user->refcnt); + if (!user_event_last_ref(user)) + return -EBUSY; - return ret; + return destroy_user_event(user); } /* @@ -1314,7 +1309,7 @@ static int user_events_ref_add(struct file *file, struct user_event *user) new_refs->events[i] = user; - atomic_inc(&user->refcnt); + refcount_inc(&user->refcnt); rcu_assign_pointer(file->private_data, new_refs); @@ -1374,7 +1369,7 @@ static long user_events_ioctl_reg(struct file *file, unsigned long uarg) ret = user_events_ref_add(file, user); /* No longer need parse ref, ref_add either worked or not */ - atomic_dec(&user->refcnt); + refcount_dec(&user->refcnt); /* Positive number is index and valid */ if (ret < 0) @@ -1464,7 +1459,7 @@ static int user_events_release(struct inode *node, struct file *file) user = refs->events[i]; if (user) - atomic_dec(&user->refcnt); + refcount_dec(&user->refcnt); } out: file->private_data = NULL; -- 2.25.1