Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp3875878pxb; Tue, 17 Nov 2020 06:00:59 -0800 (PST) X-Google-Smtp-Source: ABdhPJyamgv4a7dBe6zlYofCIMk2pf/EJVglDvMeyQNnsHyA0DMky9xl+Ua5d9uVz88LdLUUqm76 X-Received: by 2002:a17:906:5052:: with SMTP id e18mr18775627ejk.530.1605621659530; Tue, 17 Nov 2020 06:00:59 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605621659; cv=none; d=google.com; s=arc-20160816; b=OAZk9SotcjKuaBn9qMqShWy6v14WtYvmJk6jK3vZU4yBpJodyUNXK3NUqx6upcaRsK mO2GQrhxbEjIR4akyUAyg0KU3df7I9k4nl4ujO3Nnq6KWrVdK4TCulr6YDIYScpu+5gC Lk3caxaxR1T0offpM3G8sLj20KJj6JkGDjCpD9Jn1e67l+RJGAC6f1Gk8Gy4Pafg4ai7 TRTwC4p++ywV6jkfT33J3KmXCY/KbUOleZwVRPa9Y024lNDGv0Hd2EKK2mTZKNUEygLN gGIR5cZye/ccUi1YTZPgOZo5aTyO7Q3P/PBl+UkaP2VYP2Lvg0RLiGqeBEkSQwNDWNao 9nmA== 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=KFeNl3vU/B09KK/hOQeo/mgBgvBPdw11JgofeXEK6tU=; b=mNv35M3TC3Uo8gXiiPNu82rnUq19xJvg2MjrLXmUA5GbYjlavwuLC20QTvqYXCLoIX ElPiDDEbvvU68unnj2Rt7cMtj5KC2gv/HKWdLu7C/P74Rv78BD2/dhVJQGz3qvyfdIsA YADs1I6n3z8UErdh2H0SLca++HFYJWKk49gmua3WJPLnMpkPIX9qisWXBOSUmn2Jx74t RI/CzjUrP+uiVJrcq7LWfCRTJpMqYp79ulbTPpJoiJEE+R1ik4bfVFJbl3jjzGDfWEQY /DwSQZKPSMGoNcPJyNeKXQmU5EjlfqfZkiCW7iIxsRagaLaqsr1hoHOGJJ5iU/RE64LW hi7A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=Y24z+k9b; 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 h4si13605910ejj.390.2020.11.17.06.00.33; Tue, 17 Nov 2020 06:00:59 -0800 (PST) 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=Y24z+k9b; 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 S1732891AbgKQN6k (ORCPT + 99 others); Tue, 17 Nov 2020 08:58:40 -0500 Received: from mail.kernel.org ([198.145.29.99]:55630 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729836AbgKQNVt (ORCPT ); Tue, 17 Nov 2020 08:21:49 -0500 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 C8C3420781; Tue, 17 Nov 2020 13:21:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1605619307; bh=hJIYWwQwIAmMj0tJjiaAfEAul96OAerd2cv5TffONkQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Y24z+k9bRUQnw+Jq0ebYVCTzSgRN+geCyXShejrhj6IYFVy/+PS+Vd4chSJm3+QyN stQzblLHr2PVh3vuVN0BfTfgDVVIwdsZVyBa2LiPWSstvrER34dJzcbz+P0uZ7koZq Omehmq+zIfTjDlvzpyq6dj673JyRP+zir54QO33g= 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 , Sudip Mukherjee Subject: [PATCH 4.19 097/101] perf/core: Fix race in the perf_mmap_close() function Date: Tue, 17 Nov 2020 14:06:04 +0100 Message-Id: <20201117122117.860183645@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201117122113.128215851@linuxfoundation.org> References: <20201117122113.128215851@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 commit f91072ed1b7283b13ca57fcfbece5a3b92726143 upstream. 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 [sudip: used ring_buffer] Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- kernel/events/core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5475,11 +5475,11 @@ static void perf_pmu_output_stop(struct static void perf_mmap_close(struct vm_area_struct *vma) { struct perf_event *event = vma->vm_file->private_data; - struct ring_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); @@ -5510,7 +5510,8 @@ static void perf_mmap_close(struct vm_ar 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; @@ -5519,7 +5520,7 @@ static void perf_mmap_close(struct vm_ar 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; /*