Received: by 2002:a05:6a10:9e8c:0:0:0:0 with SMTP id y12csp512303pxx; Wed, 28 Oct 2020 10:01:13 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx0U+ARiJGuuaM6z7EAbuuU9hr6cx6mCiqLM92/Y/hHD0c0DdHDmfrQMjXRIO9qcQF+8rcM X-Received: by 2002:a2e:b888:: with SMTP id r8mr94254ljp.138.1603904472879; Wed, 28 Oct 2020 10:01:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603904472; cv=none; d=google.com; s=arc-20160816; b=r3ThqTFLsFD8Cr1l3PQ0KeQKO85DHehfyeNA6YcMVWf1WflzRcSKaegNI9Yw4NSO+Z 3w1qV4MvoVggL+OY7Pou3GdtxbIul0g9r0RBgXD8weNFwsD0E3GBh2t2oKqmZSL10Bbt 30U5wS0yKYOw/CAxfqqXUz8h74ifQXgdxDRZ9i7O+QExFV311Z76H8sPBO4LQsUTI91C d/7PndSd55l2p9ZNiio50mTmOIwsU1qrREmv2QdYlK+XiaRnPYSZ9o6nIOUXyycC0bx3 0PNzhiZmRSh553AE6XJIrbfVkb04nzfrq0gl0v9anMdC/+KUkiNv8XaLvJ4F2YvMShUu +lxQ== 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 :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=nu2SNwcpAy8B9VrWv5RD2HfiVAtl98DVMkSoEK1UJTo=; b=AE+aVOYx0Uj62Cpcp4e5wTI0pgjk84qNP+clC8Vder9KdrUjFhpMI1mrF8j9hfFUa5 Pq5ZcbNrz6RPJ+mvjB8l3RF+n8nm8hsyd6s13A0daOpg+w/sgQiWwtC5+2ExMl7YdTdl U4mfB3SxRGkoDRpkXqHwGlIAR5lF2gRlnxMg+UmnYSdz7yopX0dZp8dYseRglN8LqgU2 MuF68GtiGjMUEUfROT5qHOQ0LlxlDFeTnkizuDHYlK9A8IoVZU858UjDXO06YJ7RnI7F VjgM9LIv6Z5uH+Nml9S+Ep9WsmK6FDdrFwkm5oUUAPY3crX7b7ClQXJGrel5Z4VQKlVZ IQfw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=zAipfGNp; 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=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id g1si6073edt.484.2020.10.28.10.00.47; Wed, 28 Oct 2020 10:01:12 -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=zAipfGNp; 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=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1819250AbgJ0R2y (ORCPT + 99 others); Tue, 27 Oct 2020 13:28:54 -0400 Received: from mail.kernel.org ([198.145.29.99]:51446 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1775157AbgJ0OwL (ORCPT ); Tue, 27 Oct 2020 10:52:11 -0400 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id E14A921556; Tue, 27 Oct 2020 14:52:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1603810330; bh=JHnr9jiyznjEuOhqEiKotqufP++3GHGfoKT8jdmcEMA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=zAipfGNpnxnjUpxNS+ighBxH1GBvgfsO9+Qp3sZYX+WGGt0kWeQwk4025w2RO2v6y H9d/Zw6WfZegjPg5vFQ2l2JG06Vx0CjH9z1/UZse15BDaOAVvltO4oOpIYPTNLgs4R 82idoR3hBde0++J6qB8TNuVQawrFuErmbzSkEHT0= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Michael Petlan , Jiri Olsa , Ingo Molnar , Peter Zijlstra , Namhyung Kim , Wade Mealing , Sasha Levin Subject: [PATCH 5.8 101/633] perf/core: Fix race in the perf_mmap_close() function Date: Tue, 27 Oct 2020 14:47:24 +0100 Message-Id: <20201027135527.444713945@linuxfoundation.org> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027135522.655719020@linuxfoundation.org> References: <20201027135522.655719020@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jiri Olsa [ Upstream commit f91072ed1b7283b13ca57fcfbece5a3b92726143 ] There's a possible race in perf_mmap_close() when checking ring buffer's mmap_count refcount value. The problem is that the mmap_count check is not atomic because we call atomic_dec() and atomic_read() separately. perf_mmap_close: ... atomic_dec(&rb->mmap_count); ... if (atomic_read(&rb->mmap_count)) goto out_put; free_uid out_put: ring_buffer_put(rb); /* could be last */ The race can happen when we have two (or more) events sharing same ring buffer and they go through atomic_dec() and then they both see 0 as refcount value later in atomic_read(). Then both will go on and execute code which is meant to be run just once. The code that detaches ring buffer is probably fine to be executed more than once, but the problem is in calling free_uid(), which will later on demonstrate in related crashes and refcount warnings, like: refcount_t: addition on 0; use-after-free. ... RIP: 0010:refcount_warn_saturate+0x6d/0xf ... Call Trace: prepare_creds+0x190/0x1e0 copy_creds+0x35/0x172 copy_process+0x471/0x1a80 _do_fork+0x83/0x3a0 __do_sys_wait4+0x83/0x90 __do_sys_clone+0x85/0xa0 do_syscall_64+0x5b/0x1e0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Using atomic decrease and check instead of separated calls. Tested-by: Michael Petlan Signed-off-by: Jiri Olsa Signed-off-by: Ingo Molnar Acked-by: Peter Zijlstra Acked-by: Namhyung Kim Acked-by: Wade Mealing Fixes: 9bb5d40cd93c ("perf: Fix mmap() accounting hole"); Link: https://lore.kernel.org/r/20200916115311.GE2301783@krava Signed-off-by: Sasha Levin --- kernel/events/core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index fd8cd00099dae..38eeb297255e4 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5852,11 +5852,11 @@ static void perf_pmu_output_stop(struct perf_event *event); static void perf_mmap_close(struct vm_area_struct *vma) { struct perf_event *event = vma->vm_file->private_data; - struct perf_buffer *rb = ring_buffer_get(event); struct user_struct *mmap_user = rb->mmap_user; int mmap_locked = rb->mmap_locked; unsigned long size = perf_data_size(rb); + bool detach_rest = false; if (event->pmu->event_unmapped) event->pmu->event_unmapped(event, vma->vm_mm); @@ -5887,7 +5887,8 @@ static void perf_mmap_close(struct vm_area_struct *vma) mutex_unlock(&event->mmap_mutex); } - atomic_dec(&rb->mmap_count); + if (atomic_dec_and_test(&rb->mmap_count)) + detach_rest = true; if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) goto out_put; @@ -5896,7 +5897,7 @@ static void perf_mmap_close(struct vm_area_struct *vma) mutex_unlock(&event->mmap_mutex); /* If there's still other mmap()s of this buffer, we're done. */ - if (atomic_read(&rb->mmap_count)) + if (!detach_rest) goto out_put; /* -- 2.25.1