From patchwork Thu Sep 21 23:16:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 817229 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hMAUlLOU"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xyt6Z6gr0z9t3C for ; Fri, 22 Sep 2017 09:25:34 +1000 (AEST) Received: from localhost ([::1]:55892 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dvAqa-0003Di-97 for incoming@patchwork.ozlabs.org; Thu, 21 Sep 2017 19:25:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37184) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dvAiC-0004aI-M3 for qemu-devel@nongnu.org; Thu, 21 Sep 2017 19:16:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dvAiB-0003ws-Im for qemu-devel@nongnu.org; Thu, 21 Sep 2017 19:16:52 -0400 Received: from mail-wr0-x242.google.com ([2a00:1450:400c:c0c::242]:34893) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dvAiB-0003un-Bc for qemu-devel@nongnu.org; Thu, 21 Sep 2017 19:16:51 -0400 Received: by mail-wr0-x242.google.com with SMTP id n64so3848914wrb.2 for ; Thu, 21 Sep 2017 16:16:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:subject:date:message-id:in-reply-to:references; bh=I4un/RBv084vM0x2EbOSymlcxLRxjGOxSrI5Kh4hbXY=; b=hMAUlLOUpxSp2CQ840LOrl4iHitkNWSlYWEcbxO2B9k7kFTT+XKmT/TWNoMcp5kQli 7xNVhi3maPG7k1Zec6rOCjnOl0W+prHtab2Ti10cq6xxNmjRzecdoqhH3Qq/XAFGWeSZ uMSvWc7KhRCwg1FvJ249hlE+y3ggPR7gYvxCjITA3AuZDQAUN8Z5NDXnHAq0BjAVN2yd ugqTc7a7o7HR5XkLAV7qcuANJpN+oRUqBrnodVLU0p7abIH0I6ybzHUOC8JMfaq59/o6 G7gRlExTRCaHcm3eNYmZ9nvE1w6obJuPeO/6LTrVSqmsrGrFoEhMCXssVrZ9WD8TzwT5 i6mA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:subject:date:message-id :in-reply-to:references; bh=I4un/RBv084vM0x2EbOSymlcxLRxjGOxSrI5Kh4hbXY=; b=HH9MBty688EC+kLovdZ9KwgMdVWL+M7kMzxFlOqDcJ3E1ZajqSuv4farjLoYJX92Ul WXfuWS0SXZfHBsY/UKvMjJpoqh+wjKR4lIGWWzWCt6BAlxTUTcE1q6VnSPqSVBBKR0IB h/m7gKtTFo3s0P5A5Zi+Z1sxUblR3SJq8eUa78f9SWlEmd6yq6cow3uW15Ik0NHnwe6+ cqcxM7PAP9Q3PConfV34Zzo1zzqulEPhibmA9ZFRPIV/jnMPawAuDNqqcUdCirSxQqvY OGcIwsyUh/rZtzelJBrKQIWJxIkllCYVaaqhc3W3OWZM+7GyV8BzuA1+Hp+9Y8W44GRc zHfQ== X-Gm-Message-State: AHPjjUj0Psa5JMECVT9PwdKM8VY8jTNIGdlpTG/oRvEQo0kQKKR4Spp3 3xSES7b/ij5jJASVoVuDN6C5mkd/ X-Google-Smtp-Source: AOwi7QC9g8ftsMs3t8GhSBpXcHhyYFHCfEMic92APWWea7DlPdqBqdfd59lcB0YTM/G8he5F0yR+VQ== X-Received: by 10.223.138.235 with SMTP id z40mr3389206wrz.14.1506035809890; Thu, 21 Sep 2017 16:16:49 -0700 (PDT) Received: from 640k.lan (dynamic-adsl-78-12-246-117.clienti.tiscali.it. [78.12.246.117]) by smtp.gmail.com with ESMTPSA id u186sm2596278wmd.19.2017.09.21.16.16.48 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 21 Sep 2017 16:16:49 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Fri, 22 Sep 2017 01:16:13 +0200 Message-Id: <1506035800-30509-6-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1506035800-30509-1-git-send-email-pbonzini@redhat.com> References: <1506035800-30509-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c0c::242 Subject: [Qemu-devel] [PULL 05/32] memory: avoid "resurrection" of dead FlatViews X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" It's possible for address_space_get_flatview() as it currently stands to cause a use-after-free for the returned FlatView, if the reference count is incremented after the FlatView has been replaced by a writer: thread 1 thread 2 RCU thread ------------------------------------------------------------- rcu_read_lock read as->current_map set as->current_map flatview_unref '--> call_rcu flatview_ref [ref=1] rcu_read_unlock flatview_destroy Since FlatViews are not updated very often, we can just detect the situation using a new atomic op atomic_fetch_inc_nonzero, similar to Linux's atomic_inc_not_zero, which performs the refcount increment only if it hasn't already hit zero. This is similar to Linux commit de09a9771a53 ("CRED: Fix get_task_cred() and task_state() to not resurrect dead credentials", 2010-07-29). Signed-off-by: Paolo Bonzini --- docs/devel/atomics.txt | 1 + include/qemu/atomic.h | 8 ++++++++ memory.c | 12 ++++++++---- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/docs/devel/atomics.txt b/docs/devel/atomics.txt index 048e5f2..10c5fa3 100644 --- a/docs/devel/atomics.txt +++ b/docs/devel/atomics.txt @@ -64,6 +64,7 @@ operations: typeof(*ptr) atomic_fetch_and(ptr, val) typeof(*ptr) atomic_fetch_or(ptr, val) typeof(*ptr) atomic_fetch_xor(ptr, val) + typeof(*ptr) atomic_fetch_inc_nonzero(ptr) typeof(*ptr) atomic_xchg(ptr, val) typeof(*ptr) atomic_cmpxchg(ptr, old, new) diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index b6b62fb..d73c9e1 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -442,4 +442,12 @@ } while(0) #endif +#define atomic_fetch_inc_nonzero(ptr) ({ \ + typeof_strip_qual(*ptr) _oldn = atomic_read(ptr); \ + while (_oldn && atomic_cmpxchg(ptr, _oldn, _oldn + 1) != _oldn) { \ + _oldn = atomic_read(ptr); \ + } \ + _oldn; \ +}) + #endif /* QEMU_ATOMIC_H */ diff --git a/memory.c b/memory.c index 2b90117..51f54ab 100644 --- a/memory.c +++ b/memory.c @@ -294,9 +294,9 @@ static void flatview_destroy(FlatView *view) g_free(view); } -static void flatview_ref(FlatView *view) +static bool flatview_ref(FlatView *view) { - atomic_inc(&view->ref); + return atomic_fetch_inc_nonzero(&view->ref) > 0; } static void flatview_unref(FlatView *view) @@ -773,8 +773,12 @@ static FlatView *address_space_get_flatview(AddressSpace *as) FlatView *view; rcu_read_lock(); - view = atomic_rcu_read(&as->current_map); - flatview_ref(view); + do { + view = atomic_rcu_read(&as->current_map); + /* If somebody has replaced as->current_map concurrently, + * flatview_ref returns false. + */ + } while (!flatview_ref(view)); rcu_read_unlock(); return view; }