From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A933762B for ; Wed, 6 Sep 2023 00:45:04 +0000 (UTC) Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-68a628f923dso3562698b3a.2 for ; Tue, 05 Sep 2023 17:45:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1693961104; x=1694565904; darn=lists.linux.dev; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=HUA9usxNgwB6YytBqtV+1OLueYqIkCgXy7MnO3qXqNQ=; b=q7pGVSS+8Hm1Dz6deh5U7PY3vQDZ+oF/8ZCa8JA99595NOA3/ANXmdSMMNYk/HJ1U8 nQk5CvGnCWoTIcqzjM+Z/hDJxOQTNxvNlSsNOQeSGwW7bRJrk3DRpa3sjISO6yF+W55P PRcXLurdTSJIjWTGqKvueT3ykP+YAHIbZojSztUllDqHfI8MmTVyV1HU0MSNKeFYlCRW PnRasshf7PEzuBmm6JeKLGW0SVge24rbwD6Nq+xOFBXE9tBMSR0WnFpTCUPNJfcIw5GT /J+NmrMoXewI5QoGRwhHJmv6urXsC+QTMrikzLAjWc7uym43P3E9WqqNJjqDDzRO+zS/ 7FqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693961104; x=1694565904; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to; bh=HUA9usxNgwB6YytBqtV+1OLueYqIkCgXy7MnO3qXqNQ=; b=GxFchHR5ocJwyqMAZIvvHthdSetPNK1BqThJ+ldCZMbn/cNAT0VGTtXYltKFPpCM/R fvk4XwfoXHOAhLkzaGfzwxBp0yZGOmKxuIDZrWpHsVpgXqZGTPRSGlz7/0bWmF99p7BX bI0f8WgS8xukdvzxtkdUxGI8hCAUoVjuhTRE4VYwtLQih7+Tfccr8EKuiuKTFIAC/2n0 kBthjXrYCK+bDnfxtvfndT516dnsBfYBjODDzBNNCjYcYG+G7zVdFZLAkrjRVETPxoJK 71njdnFrIVUdZTaLfuTjVUyDwcT80sr+tK+Y4kiTh72ZelBzr7NxBktq0iE4EjlVhfL/ 5ZoQ== X-Gm-Message-State: AOJu0YwEnxHQzgZsKuPpXPBzAM/XtdE28VH53tn91aQcTD2Dx4tmXb0H o1ucIsulMsMCfkdbqwdRj/K6ZCvgtA4= X-Google-Smtp-Source: AGHT+IEjMoa55UXF5kyTyYfYfW3WHpsvfUj4SXpf2Xux5fwvpnUOg3He95RZW7oJ1ZZo3y681Y0APv8WxlY= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a05:6a00:3982:b0:68c:33a9:e564 with SMTP id fi2-20020a056a00398200b0068c33a9e564mr5874174pfb.5.1693961103860; Tue, 05 Sep 2023 17:45:03 -0700 (PDT) Date: Tue, 5 Sep 2023 17:45:02 -0700 In-Reply-To: Precedence: bulk X-Mailing-List: kvmarm@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20230704075054.3344915-1-stevensd@google.com> <20230704075054.3344915-4-stevensd@google.com> <20230705161914.00004070.zhi.wang.linux@gmail.com> <20230711203348.00000fb8.zhi.wang.linux@gmail.com> Message-ID: Subject: Re: [PATCH v7 3/8] KVM: Make __kvm_follow_pfn not imply FOLL_GET From: Sean Christopherson To: David Stevens Cc: Zhi Wang , Marc Zyngier , Michael Ellerman , Peter Xu , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, kvm@vger.kernel.org Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable On Tue, Sep 05, 2023, David Stevens wrote: > On Wed, Jul 12, 2023 at 7:00=E2=80=AFAM Sean Christopherson wrote: > > > > On Tue, Jul 11, 2023, Zhi Wang wrote: > > > On Thu, 6 Jul 2023 15:49:39 +0900 > > > David Stevens wrote: > > > > > > > On Wed, Jul 5, 2023 at 10:19___PM Zhi Wang wrote: > > > > > > > > > > On Tue, 4 Jul 2023 16:50:48 +0900 > > > > > David Stevens wrote: > > > > > If yes, do we have to use FOLL_GET to resolve GFN associated with= a tail page? > > > > > It seems gup can tolerate gup_flags without FOLL_GET, but it is m= ore like a > > > > > temporary solution. I don't think it is a good idea to play trick= s with > > > > > a temporary solution, more like we are abusing the toleration. > > > > > > > > I'm not sure I understand what you're getting at. This series never > > > > calls gup without FOLL_GET. > > > > > > > > This series aims to provide kvm_follow_pfn as a unified API on top = of > > > > gup+follow_pte. Since one of the major clients of this API uses an = mmu > > > > notifier, it makes sense to support returning a pfn without taking = a > > > > reference. And we indeed need to do that for certain types of memor= y. > > > > > > > > > > I am not having prob with taking a pfn without taking a ref. I am > > > questioning if using !FOLL_GET in struct kvm_follow_pfn to indicate t= aking > > > a pfn without a ref is a good idea or not, while there is another fla= g > > > actually showing it. > > > > > > I can understand that using FOLL_XXX in kvm_follow_pfn saves some > > > translation between struct kvm_follow_pfn.{write, async, xxxx} and GU= P > > > flags. However FOLL_XXX is for GUP. Using FOLL_XXX for reflecting the > > > requirements of GUP in the code path that going to call GUP is reason= able. > > > > > > But using FOLL_XXX with purposes that are not related to GUP call rea= lly > > > feels off. > > > > I agree, assuming you're talking specifically about the logic in hva_to= _pfn_remapped() > > that handles non-refcounted pages, i.e. this > > > > if (get_page_unless_zero(page)) { > > foll->is_refcounted_page =3D true; > > if (!(foll->flags & FOLL_GET)) > > put_page(page); > > } else if (foll->flags & FOLL_GET) { > > r =3D -EFAULT; > > } > > > > should be > > > > if (get_page_unless_zero(page)) { > > foll->is_refcounted_page =3D true; > > if (!(foll->flags & FOLL_GET)) > > put_page(page); > > else if (!foll->guarded_by_mmu_notifier) > > r =3D -EFAULT; > > > > because it's not the desire to grab a reference that makes getting non-= refcounted > > pfns "safe", it's whether or not the caller is plugged into the MMU not= ifiers. > > > > Though that highlights that checking guarded_by_mmu_notifier should be = done for > > *all* non-refcounted pfns, not just non-refcounted struct page memory. >=20 > I think things are getting confused here because there are multiple > things which "safe" refers to. There are three different definitions > that I think are relevant here: >=20 > 1) "safe" in the sense that KVM doesn't corrupt page reference counts > 2) "safe" in the sense that KVM doesn't access pfns after they have been = freed > 3) "safe" in the sense that KVM doesn't use stale hva -> pfn translations > > For property 1, FOLL_GET is important. If the caller passes FOLL_GET, > then they expect to be able to pass the returned pfn to > kvm_release_pfn. This means that when FOLL_GET is set, if > kvm_pfn_to_refcounted_page returns a page, then hva_to_pfn_remapped > must take a reference count to avoid eventually corrupting the page > ref count. I guess replacing the FOLL_GET check with > !guarded_by_mmu_notifier is logically equivalent because > __kvm_follow_pfn requires that at least one of guarded_by_mmu_notifier > and FOLL_GET is set. But since we're concerned about a property of the > refcount, I think that checking FOLL_GET is clearer. >=20 > For property 2, FOLL_GET is also important. If guarded_by_mmu_notifier > is set, then we're all good here. If guarded_by_mmu_notifier is not > set, then the check in __kvm_follow_pfn guarantees that FOLL_GET is > set. For struct page memory, we're safe because KVM will hold a > reference as long as it's still using the page. For non struct page > memory, we're not safe - this is where the breaking change of > allow_unsafe_mappings would go. Note that for non-refcounted struct > page, we can't use the allow_unsafe_mappings escape hatch. Since > FOLL_GET was requested, if we returned such a page, then the caller > would eventually corrupt the page refcount via kvm_release_pfn. Yes we can. The caller simply needs to be made aware of is_refcounted_page= . I didn't include that in the snippet below because I didn't want to write the= entire patch. The whole point of adding is_refcounted_page is so that callers can identify exactly what type of page was at the end of the trail that was fol= lowed. > Property 3 would be nice, but we've already concluded that guarding > all translations with mmu notifiers is infeasible. So maintaining > property 2 is the best we can hope for. No, #3 is just a variant of #2. Unless you're talking about not making gua= rantees about guest accesses being ordered with respect to VMA/memslot updates, but= I don't think that's the case. > > As for the other usage of FOLL_GET in this series (using it to conditio= nally do > > put_page()), IMO that's very much related to the GUP call. Invoking pu= t_page() > > is a hack to workaround the fact that GUP doesn't provide a way to get = the pfn > > without grabbing a reference to the page. In an ideal world, KVM would= NOT pass > > FOLL_GET to the various GUP helpers, i.e. FOLL_GET would be passed as-i= s and KVM > > wouldn't "need" to kinda sorta overload FOLL_GET to manually drop the r= eference. > > > > I do think it's worth providing a helper to consolidate and document th= at hacky > > code, e.g. add a kvm_follow_refcounted_pfn() helper. > > > > All in all, I think the below (completely untested) is what we want? > > > > David (and others), I am planning on doing a full review of this series= "soon", > > but it will likely be a few weeks until that happens. I jumped in on t= his > > specific thread because this caught my eye and I really don't want to t= hrow out > > *all* of the FOLL_GET usage. > > > > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > > index 5b5afd70f239..90d424990e0a 100644 > > --- a/virt/kvm/kvm_main.c > > +++ b/virt/kvm/kvm_main.c > > @@ -2481,6 +2481,25 @@ static inline int check_user_page_hwpoison(unsig= ned long addr) > > return rc =3D=3D -EHWPOISON; > > } > > > > +static kvm_pfn_t kvm_follow_refcounted_pfn(struct kvm_follow_pfn *foll= , > > + struct page *page) > > +{ > > + kvm_pfn_t pfn =3D page_to_pfn(page); > > + > > + foll->is_refcounted_page =3D true; > > + > > + /* > > + * FIXME: Ideally, KVM wouldn't pass FOLL_GET to gup() when the= caller > > + * doesn't want to grab a reference, but gup() doesn't support = getting > > + * just the pfn, i.e. FOLL_GET is effectively mandatory. If th= at ever > > + * changes, drop this and simply don't pass FOLL_GET to gup(). > > + */ > > + if (!(foll->flags & FOLL_GET)) > > + put_page(page); > > + > > + return pfn; > > +} > > + > > /* > > * The fast path to get the writable pfn which will be stored in @pfn, > > * true indicates success, otherwise false is returned. It's also the > > @@ -2500,11 +2519,9 @@ static bool hva_to_pfn_fast(struct kvm_follow_pf= n *foll, kvm_pfn_t *pfn) > > return false; > > > > if (get_user_page_fast_only(foll->hva, FOLL_WRITE, page)) { > > - *pfn =3D page_to_pfn(page[0]); > > foll->writable =3D foll->allow_write_mapping; > > - foll->is_refcounted_page =3D true; > > - if (!(foll->flags & FOLL_GET)) > > - put_page(page[0]); > > + > > + *pfn =3D kvm_follow_refcounted_pfn(foll, page[0]); > > return true; > > } > > > > @@ -2528,7 +2545,6 @@ static int hva_to_pfn_slow(struct kvm_follow_pfn = *foll, kvm_pfn_t *pfn) > > return npages; > > > > foll->writable =3D (foll->flags & FOLL_WRITE) && foll->allow_wr= ite_mapping; > > - foll->is_refcounted_page =3D true; > > > > /* map read fault as writable if possible */ > > if (unlikely(!foll->writable) && foll->allow_write_mapping) { > > @@ -2540,9 +2556,8 @@ static int hva_to_pfn_slow(struct kvm_follow_pfn = *foll, kvm_pfn_t *pfn) > > page =3D wpage; > > } > > } > > - *pfn =3D page_to_pfn(page); > > - if (!(foll->flags & FOLL_GET)) > > - put_page(page); > > + > > + *pfn =3D kvm_follow_refcounted_pfn(foll, page); > > return npages; > > } > > > > @@ -2610,17 +2625,16 @@ static int hva_to_pfn_remapped(struct vm_area_s= truct *vma, struct kvm_follow_pfn > > if (!page) > > goto out; > > > > - if (get_page_unless_zero(page)) { > > - foll->is_refcounted_page =3D true; > > - if (!(foll->flags & FOLL_GET)) > > - put_page(page); > > - } else if (foll->flags & FOLL_GET) { > > - r =3D -EFAULT; > > - } > > - > > + if (get_page_unless_zero(page)) > > + WARN_ON_ONCE(kvm_follow_refcounted_pfn(foll, page) !=3D= pfn); > > out: > > pte_unmap_unlock(ptep, ptl); > > - *p_pfn =3D pfn; > > + > > + if (!foll->is_refcounted_page && !foll->guarded_by_mmu_notifier= && > > + !allow_unsafe_mappings) > > + r =3D -EFAULT; > > + else > > + *p_pfn =3D pfn; > > > > return r; > > } > > >=20 > As I pointed out above, this suggestion is broken because a FOLL_GET > && !guarded_by_mmu_notifier request (e.g. kvm_vcpu_map) for a > non-refcounted page will result in the refcount eventually being > corrupted. I don't think so, unless I'm misunderstanding the concern. It just wasn't = a complete patch, and wasn't intended to be. > What do you think of this implementation? If it makes sense, I can > send out an updated patch series. > > /* > * If FOLL_GET is set, then the caller wants us to take a reference to > * keep the pfn alive. If FOLL_GET isn't set, then __kvm_follow_pfn > * guarantees that guarded_by_mmu_notifier is set, so there aren't any > * use-after-free concerns. > */ > page =3D kvm_pfn_to_refcounted_page(pfn); > if (page) { > if (get_page_unless_zero(page)) { > WARN_ON_ONCE(kvm_follow_refcounted_pfn(foll, page) !=3D p= fn); > } else if (foll->flags & FOLL_GET) { > /* > * Certain IO or PFNMAP mappings can be backed with > * valid struct pages but be allocated without > * refcounting e.g., tail pages of non-compound higher > * order allocations. The caller asked for a ref, but > * we can't take one, since releasing such a ref would > * free the page. > */ > r =3D -EFAULT; > } > } else if (foll->flags & FOLL_GET) { > /* > * When there's no struct page to refcount and no MMU notifier, > * then KVM can't be guarantee to avoid use-after-free. However, > * there are valid reasons to set up such mappings. If userspace > * is trusted and willing to forego kernel safety guarantees, > * allow this check to be bypassed. > */ > if (foll->guarded_by_mmu_notifier && !allow_unsafe_mappings) I assume you mean: if (!foll->guarded_by_mmu_notifier && !allow_unsafe_mappings) > r =3D -EFAULT; > } Please no. I don't want to overload FOLL_GET or have dependencies between FOLL_GET and guarded_by_mmu_notifier. The guest page fault path should be = able to omit FOLL_GET, and it obviously should set guarded_by_mmu_notifier. And kvm_vcpu_map() should be able to set FOLL_GET, omit guarded_by_mmu_notifier= , _and_ play nice with "unsafe", non-refcounted memory when allow_unsafe_mappings i= s true. The above fits your use case because nothing in KVM needs to do kvm_vcpu_ma= p() on the GPU's buffer, but as a general solution the semantics are very odd. = E.g. in long form, they are: Get get a reference if a there's a refcounted page, fail with -EFAULT if = there's a struct page but it's not refcounted, and fail with -EFAULT if there's n= ot struct page unless the caller is protected by mmu_notifiers or unsafe mappings a= re allowed. That's rather bonkers. What I instead want is FOLL_GET to be: Get a reference if there's a refcounted page. And then allow_unsafe_mappings is simply: Allow mapping non-refcounted memory into the guest even if the mapping is= n't guarded by mmu_notifier events. From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DAFB2CCF9ED for ; Wed, 6 Sep 2023 00:45:59 +0000 (UTC) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20221208 header.b=F3UquzpO; dkim-atps=neutral Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4RgNw61Bfkz3c7s for ; Wed, 6 Sep 2023 10:45:58 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20221208 header.b=F3UquzpO; dkim-atps=neutral Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=flex--seanjc.bounces.google.com (client-ip=2607:f8b0:4864:20::44a; helo=mail-pf1-x44a.google.com; envelope-from=3j8v3zaykddqiuqdzsweewbu.secbydknffs-tulbyiji.epbqri.ehw@flex--seanjc.bounces.google.com; receiver=lists.ozlabs.org) Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4RgNv74VWyz2xm3 for ; Wed, 6 Sep 2023 10:45:06 +1000 (AEST) Received: by mail-pf1-x44a.google.com with SMTP id d2e1a72fcca58-68c3b9f8312so3571016b3a.1 for ; Tue, 05 Sep 2023 17:45:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1693961104; x=1694565904; darn=lists.ozlabs.org; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=HUA9usxNgwB6YytBqtV+1OLueYqIkCgXy7MnO3qXqNQ=; b=F3UquzpOm2C75JJsWBls2g3c5FSzfyecattpYZFgRIq3vr99vOLyJjhefZsO7FxwTf Emj5r5amnIrPqyLCeK92vXW2UWTAaXvcO7GR2QwHJe3LLhtyxH8/C7zW/CwVgZVSYnK1 /2kMH1SUFoP4NphKLShNgrNkQqWoyv3ur8XhdVGhOhissdoCElGePQesqMYa6vRDuTGB jF5mQxg6QgDS5Kf2BZf0k0LcltqLX+NkO2b7Yuk7GfuiWiSthKRar/81pevUZ54o8qLa dz1yS/i3gEX6tt0rh3fbR/Msmudh+ybgTOetaBrolbm57UMxKqKvhH9qlwfNH4ZEdXSg E6TQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693961104; x=1694565904; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to; bh=HUA9usxNgwB6YytBqtV+1OLueYqIkCgXy7MnO3qXqNQ=; b=Qud1yiI0e1HvbP7WQJROpN6znKFiitBbf0zMiYvmw/zWMOqx4N6iC/Ob2oN26anLBH dJhKvoiY2Puw966ohz5ZrjXAbSXD0i0gQ8IIQ6zBFnI/giOnKbkMh8QFUZ/r54QYGL2+ TbD+OZC97W/h8AMxWFkqwsLA1ie9AZnMA8BIZf8C+8h3fXcUZe0hk9NVn5HeAXsYaEMT 129lDTHSnL8OWgde1VPdiSayH5ZykSwD2jc1HLSbrblPtPXSTvyE575oWNUppFOzPYaQ nrBmKtq+k0vDbAgk9Y4q1NgQvL/v0kfpDf20/Pf0wSnPYiArVkcre2EF/X0Xv7eqV7/g og5A== X-Gm-Message-State: AOJu0YzZMX2f9e/6VCZFHjU8NuS/ZzO9GpR6HrAPHkeqysb/+ee1w1H2 P2fBiXXNfcJt0d5+ktGSWI+nCc5ZPkQ= X-Google-Smtp-Source: AGHT+IEjMoa55UXF5kyTyYfYfW3WHpsvfUj4SXpf2Xux5fwvpnUOg3He95RZW7oJ1ZZo3y681Y0APv8WxlY= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a05:6a00:3982:b0:68c:33a9:e564 with SMTP id fi2-20020a056a00398200b0068c33a9e564mr5874174pfb.5.1693961103860; Tue, 05 Sep 2023 17:45:03 -0700 (PDT) Date: Tue, 5 Sep 2023 17:45:02 -0700 In-Reply-To: Mime-Version: 1.0 References: <20230704075054.3344915-1-stevensd@google.com> <20230704075054.3344915-4-stevensd@google.com> <20230705161914.00004070.zhi.wang.linux@gmail.com> <20230711203348.00000fb8.zhi.wang.linux@gmail.com> Message-ID: Subject: Re: [PATCH v7 3/8] KVM: Make __kvm_follow_pfn not imply FOLL_GET From: Sean Christopherson To: David Stevens Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Zhi Wang , kvm@vger.kernel.org, Marc Zyngier , linux-kernel@vger.kernel.org, Peter Xu , kvmarm@lists.linux.dev, linuxppc-dev@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org Errors-To: linuxppc-dev-bounces+linuxppc-dev=archiver.kernel.org@lists.ozlabs.org Sender: "Linuxppc-dev" On Tue, Sep 05, 2023, David Stevens wrote: > On Wed, Jul 12, 2023 at 7:00=E2=80=AFAM Sean Christopherson wrote: > > > > On Tue, Jul 11, 2023, Zhi Wang wrote: > > > On Thu, 6 Jul 2023 15:49:39 +0900 > > > David Stevens wrote: > > > > > > > On Wed, Jul 5, 2023 at 10:19___PM Zhi Wang wrote: > > > > > > > > > > On Tue, 4 Jul 2023 16:50:48 +0900 > > > > > David Stevens wrote: > > > > > If yes, do we have to use FOLL_GET to resolve GFN associated with= a tail page? > > > > > It seems gup can tolerate gup_flags without FOLL_GET, but it is m= ore like a > > > > > temporary solution. I don't think it is a good idea to play trick= s with > > > > > a temporary solution, more like we are abusing the toleration. > > > > > > > > I'm not sure I understand what you're getting at. This series never > > > > calls gup without FOLL_GET. > > > > > > > > This series aims to provide kvm_follow_pfn as a unified API on top = of > > > > gup+follow_pte. Since one of the major clients of this API uses an = mmu > > > > notifier, it makes sense to support returning a pfn without taking = a > > > > reference. And we indeed need to do that for certain types of memor= y. > > > > > > > > > > I am not having prob with taking a pfn without taking a ref. I am > > > questioning if using !FOLL_GET in struct kvm_follow_pfn to indicate t= aking > > > a pfn without a ref is a good idea or not, while there is another fla= g > > > actually showing it. > > > > > > I can understand that using FOLL_XXX in kvm_follow_pfn saves some > > > translation between struct kvm_follow_pfn.{write, async, xxxx} and GU= P > > > flags. However FOLL_XXX is for GUP. Using FOLL_XXX for reflecting the > > > requirements of GUP in the code path that going to call GUP is reason= able. > > > > > > But using FOLL_XXX with purposes that are not related to GUP call rea= lly > > > feels off. > > > > I agree, assuming you're talking specifically about the logic in hva_to= _pfn_remapped() > > that handles non-refcounted pages, i.e. this > > > > if (get_page_unless_zero(page)) { > > foll->is_refcounted_page =3D true; > > if (!(foll->flags & FOLL_GET)) > > put_page(page); > > } else if (foll->flags & FOLL_GET) { > > r =3D -EFAULT; > > } > > > > should be > > > > if (get_page_unless_zero(page)) { > > foll->is_refcounted_page =3D true; > > if (!(foll->flags & FOLL_GET)) > > put_page(page); > > else if (!foll->guarded_by_mmu_notifier) > > r =3D -EFAULT; > > > > because it's not the desire to grab a reference that makes getting non-= refcounted > > pfns "safe", it's whether or not the caller is plugged into the MMU not= ifiers. > > > > Though that highlights that checking guarded_by_mmu_notifier should be = done for > > *all* non-refcounted pfns, not just non-refcounted struct page memory. >=20 > I think things are getting confused here because there are multiple > things which "safe" refers to. There are three different definitions > that I think are relevant here: >=20 > 1) "safe" in the sense that KVM doesn't corrupt page reference counts > 2) "safe" in the sense that KVM doesn't access pfns after they have been = freed > 3) "safe" in the sense that KVM doesn't use stale hva -> pfn translations > > For property 1, FOLL_GET is important. If the caller passes FOLL_GET, > then they expect to be able to pass the returned pfn to > kvm_release_pfn. This means that when FOLL_GET is set, if > kvm_pfn_to_refcounted_page returns a page, then hva_to_pfn_remapped > must take a reference count to avoid eventually corrupting the page > ref count. I guess replacing the FOLL_GET check with > !guarded_by_mmu_notifier is logically equivalent because > __kvm_follow_pfn requires that at least one of guarded_by_mmu_notifier > and FOLL_GET is set. But since we're concerned about a property of the > refcount, I think that checking FOLL_GET is clearer. >=20 > For property 2, FOLL_GET is also important. If guarded_by_mmu_notifier > is set, then we're all good here. If guarded_by_mmu_notifier is not > set, then the check in __kvm_follow_pfn guarantees that FOLL_GET is > set. For struct page memory, we're safe because KVM will hold a > reference as long as it's still using the page. For non struct page > memory, we're not safe - this is where the breaking change of > allow_unsafe_mappings would go. Note that for non-refcounted struct > page, we can't use the allow_unsafe_mappings escape hatch. Since > FOLL_GET was requested, if we returned such a page, then the caller > would eventually corrupt the page refcount via kvm_release_pfn. Yes we can. The caller simply needs to be made aware of is_refcounted_page= . I didn't include that in the snippet below because I didn't want to write the= entire patch. The whole point of adding is_refcounted_page is so that callers can identify exactly what type of page was at the end of the trail that was fol= lowed. > Property 3 would be nice, but we've already concluded that guarding > all translations with mmu notifiers is infeasible. So maintaining > property 2 is the best we can hope for. No, #3 is just a variant of #2. Unless you're talking about not making gua= rantees about guest accesses being ordered with respect to VMA/memslot updates, but= I don't think that's the case. > > As for the other usage of FOLL_GET in this series (using it to conditio= nally do > > put_page()), IMO that's very much related to the GUP call. Invoking pu= t_page() > > is a hack to workaround the fact that GUP doesn't provide a way to get = the pfn > > without grabbing a reference to the page. In an ideal world, KVM would= NOT pass > > FOLL_GET to the various GUP helpers, i.e. FOLL_GET would be passed as-i= s and KVM > > wouldn't "need" to kinda sorta overload FOLL_GET to manually drop the r= eference. > > > > I do think it's worth providing a helper to consolidate and document th= at hacky > > code, e.g. add a kvm_follow_refcounted_pfn() helper. > > > > All in all, I think the below (completely untested) is what we want? > > > > David (and others), I am planning on doing a full review of this series= "soon", > > but it will likely be a few weeks until that happens. I jumped in on t= his > > specific thread because this caught my eye and I really don't want to t= hrow out > > *all* of the FOLL_GET usage. > > > > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > > index 5b5afd70f239..90d424990e0a 100644 > > --- a/virt/kvm/kvm_main.c > > +++ b/virt/kvm/kvm_main.c > > @@ -2481,6 +2481,25 @@ static inline int check_user_page_hwpoison(unsig= ned long addr) > > return rc =3D=3D -EHWPOISON; > > } > > > > +static kvm_pfn_t kvm_follow_refcounted_pfn(struct kvm_follow_pfn *foll= , > > + struct page *page) > > +{ > > + kvm_pfn_t pfn =3D page_to_pfn(page); > > + > > + foll->is_refcounted_page =3D true; > > + > > + /* > > + * FIXME: Ideally, KVM wouldn't pass FOLL_GET to gup() when the= caller > > + * doesn't want to grab a reference, but gup() doesn't support = getting > > + * just the pfn, i.e. FOLL_GET is effectively mandatory. If th= at ever > > + * changes, drop this and simply don't pass FOLL_GET to gup(). > > + */ > > + if (!(foll->flags & FOLL_GET)) > > + put_page(page); > > + > > + return pfn; > > +} > > + > > /* > > * The fast path to get the writable pfn which will be stored in @pfn, > > * true indicates success, otherwise false is returned. It's also the > > @@ -2500,11 +2519,9 @@ static bool hva_to_pfn_fast(struct kvm_follow_pf= n *foll, kvm_pfn_t *pfn) > > return false; > > > > if (get_user_page_fast_only(foll->hva, FOLL_WRITE, page)) { > > - *pfn =3D page_to_pfn(page[0]); > > foll->writable =3D foll->allow_write_mapping; > > - foll->is_refcounted_page =3D true; > > - if (!(foll->flags & FOLL_GET)) > > - put_page(page[0]); > > + > > + *pfn =3D kvm_follow_refcounted_pfn(foll, page[0]); > > return true; > > } > > > > @@ -2528,7 +2545,6 @@ static int hva_to_pfn_slow(struct kvm_follow_pfn = *foll, kvm_pfn_t *pfn) > > return npages; > > > > foll->writable =3D (foll->flags & FOLL_WRITE) && foll->allow_wr= ite_mapping; > > - foll->is_refcounted_page =3D true; > > > > /* map read fault as writable if possible */ > > if (unlikely(!foll->writable) && foll->allow_write_mapping) { > > @@ -2540,9 +2556,8 @@ static int hva_to_pfn_slow(struct kvm_follow_pfn = *foll, kvm_pfn_t *pfn) > > page =3D wpage; > > } > > } > > - *pfn =3D page_to_pfn(page); > > - if (!(foll->flags & FOLL_GET)) > > - put_page(page); > > + > > + *pfn =3D kvm_follow_refcounted_pfn(foll, page); > > return npages; > > } > > > > @@ -2610,17 +2625,16 @@ static int hva_to_pfn_remapped(struct vm_area_s= truct *vma, struct kvm_follow_pfn > > if (!page) > > goto out; > > > > - if (get_page_unless_zero(page)) { > > - foll->is_refcounted_page =3D true; > > - if (!(foll->flags & FOLL_GET)) > > - put_page(page); > > - } else if (foll->flags & FOLL_GET) { > > - r =3D -EFAULT; > > - } > > - > > + if (get_page_unless_zero(page)) > > + WARN_ON_ONCE(kvm_follow_refcounted_pfn(foll, page) !=3D= pfn); > > out: > > pte_unmap_unlock(ptep, ptl); > > - *p_pfn =3D pfn; > > + > > + if (!foll->is_refcounted_page && !foll->guarded_by_mmu_notifier= && > > + !allow_unsafe_mappings) > > + r =3D -EFAULT; > > + else > > + *p_pfn =3D pfn; > > > > return r; > > } > > >=20 > As I pointed out above, this suggestion is broken because a FOLL_GET > && !guarded_by_mmu_notifier request (e.g. kvm_vcpu_map) for a > non-refcounted page will result in the refcount eventually being > corrupted. I don't think so, unless I'm misunderstanding the concern. It just wasn't = a complete patch, and wasn't intended to be. > What do you think of this implementation? If it makes sense, I can > send out an updated patch series. > > /* > * If FOLL_GET is set, then the caller wants us to take a reference to > * keep the pfn alive. If FOLL_GET isn't set, then __kvm_follow_pfn > * guarantees that guarded_by_mmu_notifier is set, so there aren't any > * use-after-free concerns. > */ > page =3D kvm_pfn_to_refcounted_page(pfn); > if (page) { > if (get_page_unless_zero(page)) { > WARN_ON_ONCE(kvm_follow_refcounted_pfn(foll, page) !=3D p= fn); > } else if (foll->flags & FOLL_GET) { > /* > * Certain IO or PFNMAP mappings can be backed with > * valid struct pages but be allocated without > * refcounting e.g., tail pages of non-compound higher > * order allocations. The caller asked for a ref, but > * we can't take one, since releasing such a ref would > * free the page. > */ > r =3D -EFAULT; > } > } else if (foll->flags & FOLL_GET) { > /* > * When there's no struct page to refcount and no MMU notifier, > * then KVM can't be guarantee to avoid use-after-free. However, > * there are valid reasons to set up such mappings. If userspace > * is trusted and willing to forego kernel safety guarantees, > * allow this check to be bypassed. > */ > if (foll->guarded_by_mmu_notifier && !allow_unsafe_mappings) I assume you mean: if (!foll->guarded_by_mmu_notifier && !allow_unsafe_mappings) > r =3D -EFAULT; > } Please no. I don't want to overload FOLL_GET or have dependencies between FOLL_GET and guarded_by_mmu_notifier. The guest page fault path should be = able to omit FOLL_GET, and it obviously should set guarded_by_mmu_notifier. And kvm_vcpu_map() should be able to set FOLL_GET, omit guarded_by_mmu_notifier= , _and_ play nice with "unsafe", non-refcounted memory when allow_unsafe_mappings i= s true. The above fits your use case because nothing in KVM needs to do kvm_vcpu_ma= p() on the GPU's buffer, but as a general solution the semantics are very odd. = E.g. in long form, they are: Get get a reference if a there's a refcounted page, fail with -EFAULT if = there's a struct page but it's not refcounted, and fail with -EFAULT if there's n= ot struct page unless the caller is protected by mmu_notifiers or unsafe mappings a= re allowed. That's rather bonkers. What I instead want is FOLL_GET to be: Get a reference if there's a refcounted page. And then allow_unsafe_mappings is simply: Allow mapping non-refcounted memory into the guest even if the mapping is= n't guarded by mmu_notifier events. From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 839E8CCF9E9 for ; Wed, 6 Sep 2023 00:45:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:Message-ID: References:Mime-Version:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=wplkSDY9cm6RCv1pUQhWQmG87WPLuNDiTuwRTL3NV5g=; b=UrbLuMzeJpFdbMiBFVK2iKQ7wj bLnjGyZnMobAq5Nc3dhu1BD4UIt+yZkuvd+uw32gZ9avOgekv0wF6BPdOYFtevHhYPA3EVqGlv9AH Idqvz0KHecZN5216xF/2euil79pFwv/yCVIyQnZ3qrB6b1ptaVnX+/stZ9OVsATg89sAmRtHNzjrr DpFa6eIWmS2QbbLYVgXX72W1V7jgc/t1YrfrfLBGPYOPP9gJdTE7U9AJcJ4HDt8PJtkCiwxhS3eo0 w5T2S2BtTcgGw9zC53Bkrrwc2Xb2vvp9rPB/v2nBVdppl2B6NAw35Hfb7B+ySjRtqmWipTifWRNwy V0OZFWwQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qdgfQ-006yBU-12; Wed, 06 Sep 2023 00:45:12 +0000 Received: from mail-pf1-x44a.google.com ([2607:f8b0:4864:20::44a]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qdgfM-006yAY-0j for linux-arm-kernel@lists.infradead.org; Wed, 06 Sep 2023 00:45:10 +0000 Received: by mail-pf1-x44a.google.com with SMTP id d2e1a72fcca58-68a4075f42fso3569613b3a.3 for ; Tue, 05 Sep 2023 17:45:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1693961104; x=1694565904; darn=lists.infradead.org; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:from:to:cc:subject:date:message-id :reply-to; bh=HUA9usxNgwB6YytBqtV+1OLueYqIkCgXy7MnO3qXqNQ=; b=0IaYwgi8fikmVJe+CRwn6p8seyiZxV0bTG8u3UEeccHKIhqD/WZAkUFB2UTRmLjrkS /0tSW+aVY78yGUyOp7HToKNeBDH9gD9hhWQ/pgqgUWKlgE7luWA/tZMHP/gEFIjJtGto j9XsS5ukngYTH5clud6QJxOEtgDTI+c47hmdrbiVSvyf6quvZIPf/pTnpYIafOihlYiU OrE8D5hGwIm3PwaSBJVCakW+Czb0lrA5LhIANz0v7GLjdlWQZL/q83Ed7PXF6ZuouAVE kv+9VUT9Gs7lKUxqCIxN5tu3Hu4yxxRlmq5cserDtmqAXEnlANsBoyosE6lUuwlXkMj6 4ALg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693961104; x=1694565904; h=content-transfer-encoding:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to; bh=HUA9usxNgwB6YytBqtV+1OLueYqIkCgXy7MnO3qXqNQ=; b=WZv9Nvk8BjC625bV0o7cKqRAER4hTosWBvn9VmC8qDGWgQIQQisxpD7aq21/MSdOXs vtIiJyQyHOrhCyFkpud5fwSyohPR8qwoBTvBcaRmhMk+063uLeQ3KzHBn/5u5IE9xnuf IJjoGUMryKMQfb5Tm6ybLOS7XGlz0iB7BuG6KAHtzi0DUqffntbC/FSPWsGN6rGJL9SF W1iCg5IXKEmf9QtdFpf2ni/5Gdx5ifapoOP6vklQxPF+bvMCeeETpOiHlSA9olx9clmq Q1eozHDkypKTNor2ClsGq8yrGX2+nYY1l5QyX88Kx5HdfbWmKgY8R2K8F6ABWxal7q/7 VyUA== X-Gm-Message-State: AOJu0YzBX7LfyxuCl73dChFuJfiV1BA3lUcdAEuo9xFtRc/A06cs0DN9 sevFINus23MUnhwc9/EJxT4L9YMQr4A= X-Google-Smtp-Source: AGHT+IEjMoa55UXF5kyTyYfYfW3WHpsvfUj4SXpf2Xux5fwvpnUOg3He95RZW7oJ1ZZo3y681Y0APv8WxlY= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a05:6a00:3982:b0:68c:33a9:e564 with SMTP id fi2-20020a056a00398200b0068c33a9e564mr5874174pfb.5.1693961103860; Tue, 05 Sep 2023 17:45:03 -0700 (PDT) Date: Tue, 5 Sep 2023 17:45:02 -0700 In-Reply-To: Mime-Version: 1.0 References: <20230704075054.3344915-1-stevensd@google.com> <20230704075054.3344915-4-stevensd@google.com> <20230705161914.00004070.zhi.wang.linux@gmail.com> <20230711203348.00000fb8.zhi.wang.linux@gmail.com> Message-ID: Subject: Re: [PATCH v7 3/8] KVM: Make __kvm_follow_pfn not imply FOLL_GET From: Sean Christopherson To: David Stevens Cc: Zhi Wang , Marc Zyngier , Michael Ellerman , Peter Xu , linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, kvm@vger.kernel.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230905_174508_270116_D5969708 X-CRM114-Status: GOOD ( 69.54 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org T24gVHVlLCBTZXAgMDUsIDIwMjMsIERhdmlkIFN0ZXZlbnMgd3JvdGU6Cj4gT24gV2VkLCBKdWwg MTIsIDIwMjMgYXQgNzowMOKAr0FNIFNlYW4gQ2hyaXN0b3BoZXJzb24gPHNlYW5qY0Bnb29nbGUu Y29tPiB3cm90ZToKPiA+Cj4gPiBPbiBUdWUsIEp1bCAxMSwgMjAyMywgWmhpIFdhbmcgd3JvdGU6 Cj4gPiA+IE9uIFRodSwgNiBKdWwgMjAyMyAxNTo0OTozOSArMDkwMAo+ID4gPiBEYXZpZCBTdGV2 ZW5zIDxzdGV2ZW5zZEBjaHJvbWl1bS5vcmc+IHdyb3RlOgo+ID4gPgo+ID4gPiA+IE9uIFdlZCwg SnVsIDUsIDIwMjMgYXQgMTA6MTlfX19QTSBaaGkgV2FuZyA8emhpLndhbmcubGludXhAZ21haWwu Y29tPiB3cm90ZToKPiA+ID4gPiA+Cj4gPiA+ID4gPiBPbiBUdWUsICA0IEp1bCAyMDIzIDE2OjUw OjQ4ICswOTAwCj4gPiA+ID4gPiBEYXZpZCBTdGV2ZW5zIDxzdGV2ZW5zZEBjaHJvbWl1bS5vcmc+ IHdyb3RlOgo+ID4gPiA+ID4gSWYgeWVzLCBkbyB3ZSBoYXZlIHRvIHVzZSBGT0xMX0dFVCB0byBy ZXNvbHZlIEdGTiBhc3NvY2lhdGVkIHdpdGggYSB0YWlsIHBhZ2U/Cj4gPiA+ID4gPiBJdCBzZWVt cyBndXAgY2FuIHRvbGVyYXRlIGd1cF9mbGFncyB3aXRob3V0IEZPTExfR0VULCBidXQgaXQgaXMg bW9yZSBsaWtlIGEKPiA+ID4gPiA+IHRlbXBvcmFyeSBzb2x1dGlvbi4gSSBkb24ndCB0aGluayBp dCBpcyBhIGdvb2QgaWRlYSB0byBwbGF5IHRyaWNrcyB3aXRoCj4gPiA+ID4gPiBhIHRlbXBvcmFy eSBzb2x1dGlvbiwgbW9yZSBsaWtlIHdlIGFyZSBhYnVzaW5nIHRoZSB0b2xlcmF0aW9uLgo+ID4g PiA+Cj4gPiA+ID4gSSdtIG5vdCBzdXJlIEkgdW5kZXJzdGFuZCB3aGF0IHlvdSdyZSBnZXR0aW5n IGF0LiBUaGlzIHNlcmllcyBuZXZlcgo+ID4gPiA+IGNhbGxzIGd1cCB3aXRob3V0IEZPTExfR0VU Lgo+ID4gPiA+Cj4gPiA+ID4gVGhpcyBzZXJpZXMgYWltcyB0byBwcm92aWRlIGt2bV9mb2xsb3df cGZuIGFzIGEgdW5pZmllZCBBUEkgb24gdG9wIG9mCj4gPiA+ID4gZ3VwK2ZvbGxvd19wdGUuIFNp bmNlIG9uZSBvZiB0aGUgbWFqb3IgY2xpZW50cyBvZiB0aGlzIEFQSSB1c2VzIGFuIG1tdQo+ID4g PiA+IG5vdGlmaWVyLCBpdCBtYWtlcyBzZW5zZSB0byBzdXBwb3J0IHJldHVybmluZyBhIHBmbiB3 aXRob3V0IHRha2luZyBhCj4gPiA+ID4gcmVmZXJlbmNlLiBBbmQgd2UgaW5kZWVkIG5lZWQgdG8g ZG8gdGhhdCBmb3IgY2VydGFpbiB0eXBlcyBvZiBtZW1vcnkuCj4gPiA+ID4KPiA+ID4KPiA+ID4g SSBhbSBub3QgaGF2aW5nIHByb2Igd2l0aCB0YWtpbmcgYSBwZm4gd2l0aG91dCB0YWtpbmcgYSBy ZWYuIEkgYW0KPiA+ID4gcXVlc3Rpb25pbmcgaWYgdXNpbmcgIUZPTExfR0VUIGluIHN0cnVjdCBr dm1fZm9sbG93X3BmbiB0byBpbmRpY2F0ZSB0YWtpbmcKPiA+ID4gYSBwZm4gd2l0aG91dCBhIHJl ZiBpcyBhIGdvb2QgaWRlYSBvciBub3QsIHdoaWxlIHRoZXJlIGlzIGFub3RoZXIgZmxhZwo+ID4g PiBhY3R1YWxseSBzaG93aW5nIGl0Lgo+ID4gPgo+ID4gPiBJIGNhbiB1bmRlcnN0YW5kIHRoYXQg dXNpbmcgRk9MTF9YWFggaW4ga3ZtX2ZvbGxvd19wZm4gc2F2ZXMgc29tZQo+ID4gPiB0cmFuc2xh dGlvbiBiZXR3ZWVuIHN0cnVjdCBrdm1fZm9sbG93X3Bmbi57d3JpdGUsIGFzeW5jLCB4eHh4fSBh bmQgR1VQCj4gPiA+IGZsYWdzLiBIb3dldmVyIEZPTExfWFhYIGlzIGZvciBHVVAuIFVzaW5nIEZP TExfWFhYIGZvciByZWZsZWN0aW5nIHRoZQo+ID4gPiByZXF1aXJlbWVudHMgb2YgR1VQIGluIHRo ZSBjb2RlIHBhdGggdGhhdCBnb2luZyB0byBjYWxsIEdVUCBpcyByZWFzb25hYmxlLgo+ID4gPgo+ ID4gPiBCdXQgdXNpbmcgRk9MTF9YWFggd2l0aCBwdXJwb3NlcyB0aGF0IGFyZSBub3QgcmVsYXRl ZCB0byBHVVAgY2FsbCByZWFsbHkKPiA+ID4gZmVlbHMgb2ZmLgo+ID4KPiA+IEkgYWdyZWUsIGFz c3VtaW5nIHlvdSdyZSB0YWxraW5nIHNwZWNpZmljYWxseSBhYm91dCB0aGUgbG9naWMgaW4gaHZh X3RvX3Bmbl9yZW1hcHBlZCgpCj4gPiB0aGF0IGhhbmRsZXMgbm9uLXJlZmNvdW50ZWQgcGFnZXMs IGkuZS4gdGhpcwo+ID4KPiA+ICAgICAgICAgaWYgKGdldF9wYWdlX3VubGVzc196ZXJvKHBhZ2Up KSB7Cj4gPiAgICAgICAgICAgICAgICAgZm9sbC0+aXNfcmVmY291bnRlZF9wYWdlID0gdHJ1ZTsK PiA+ICAgICAgICAgICAgICAgICBpZiAoIShmb2xsLT5mbGFncyAmIEZPTExfR0VUKSkKPiA+ICAg ICAgICAgICAgICAgICAgICAgICAgIHB1dF9wYWdlKHBhZ2UpOwo+ID4gICAgICAgICB9IGVsc2Ug aWYgKGZvbGwtPmZsYWdzICYgRk9MTF9HRVQpIHsKPiA+ICAgICAgICAgICAgICAgICByID0gLUVG QVVMVDsKPiA+ICAgICAgICAgfQo+ID4KPiA+IHNob3VsZCBiZQo+ID4KPiA+ICAgICAgICAgaWYg KGdldF9wYWdlX3VubGVzc196ZXJvKHBhZ2UpKSB7Cj4gPiAgICAgICAgICAgICAgICAgZm9sbC0+ aXNfcmVmY291bnRlZF9wYWdlID0gdHJ1ZTsKPiA+ICAgICAgICAgICAgICAgICBpZiAoIShmb2xs LT5mbGFncyAmIEZPTExfR0VUKSkKPiA+ICAgICAgICAgICAgICAgICAgICAgICAgIHB1dF9wYWdl KHBhZ2UpOwo+ID4gICAgICAgICBlbHNlIGlmICghZm9sbC0+Z3VhcmRlZF9ieV9tbXVfbm90aWZp ZXIpCj4gPiAgICAgICAgICAgICAgICAgciA9IC1FRkFVTFQ7Cj4gPgo+ID4gYmVjYXVzZSBpdCdz IG5vdCB0aGUgZGVzaXJlIHRvIGdyYWIgYSByZWZlcmVuY2UgdGhhdCBtYWtlcyBnZXR0aW5nIG5v bi1yZWZjb3VudGVkCj4gPiBwZm5zICJzYWZlIiwgaXQncyB3aGV0aGVyIG9yIG5vdCB0aGUgY2Fs bGVyIGlzIHBsdWdnZWQgaW50byB0aGUgTU1VIG5vdGlmaWVycy4KPiA+Cj4gPiBUaG91Z2ggdGhh dCBoaWdobGlnaHRzIHRoYXQgY2hlY2tpbmcgZ3VhcmRlZF9ieV9tbXVfbm90aWZpZXIgc2hvdWxk IGJlIGRvbmUgZm9yCj4gPiAqYWxsKiBub24tcmVmY291bnRlZCBwZm5zLCBub3QganVzdCBub24t cmVmY291bnRlZCBzdHJ1Y3QgcGFnZSBtZW1vcnkuCj4gCj4gSSB0aGluayB0aGluZ3MgYXJlIGdl dHRpbmcgY29uZnVzZWQgaGVyZSBiZWNhdXNlIHRoZXJlIGFyZSBtdWx0aXBsZQo+IHRoaW5ncyB3 aGljaCAic2FmZSIgcmVmZXJzIHRvLiBUaGVyZSBhcmUgdGhyZWUgZGlmZmVyZW50IGRlZmluaXRp b25zCj4gdGhhdCBJIHRoaW5rIGFyZSByZWxldmFudCBoZXJlOgo+IAo+IDEpICJzYWZlIiBpbiB0 aGUgc2Vuc2UgdGhhdCBLVk0gZG9lc24ndCBjb3JydXB0IHBhZ2UgcmVmZXJlbmNlIGNvdW50cwo+ IDIpICJzYWZlIiBpbiB0aGUgc2Vuc2UgdGhhdCBLVk0gZG9lc24ndCBhY2Nlc3MgcGZucyBhZnRl ciB0aGV5IGhhdmUgYmVlbiBmcmVlZAo+IDMpICJzYWZlIiBpbiB0aGUgc2Vuc2UgdGhhdCBLVk0g ZG9lc24ndCB1c2Ugc3RhbGUgaHZhIC0+IHBmbiB0cmFuc2xhdGlvbnMKPgo+IEZvciBwcm9wZXJ0 eSAxLCBGT0xMX0dFVCBpcyBpbXBvcnRhbnQuIElmIHRoZSBjYWxsZXIgcGFzc2VzIEZPTExfR0VU LAo+IHRoZW4gdGhleSBleHBlY3QgdG8gYmUgYWJsZSB0byBwYXNzIHRoZSByZXR1cm5lZCBwZm4g dG8KPiBrdm1fcmVsZWFzZV9wZm4uIFRoaXMgbWVhbnMgdGhhdCB3aGVuIEZPTExfR0VUIGlzIHNl dCwgaWYKPiBrdm1fcGZuX3RvX3JlZmNvdW50ZWRfcGFnZSByZXR1cm5zIGEgcGFnZSwgdGhlbiBo dmFfdG9fcGZuX3JlbWFwcGVkCj4gbXVzdCB0YWtlIGEgcmVmZXJlbmNlIGNvdW50IHRvIGF2b2lk IGV2ZW50dWFsbHkgY29ycnVwdGluZyB0aGUgcGFnZQo+IHJlZiBjb3VudC4gSSBndWVzcyByZXBs YWNpbmcgdGhlIEZPTExfR0VUIGNoZWNrIHdpdGgKPiAhZ3VhcmRlZF9ieV9tbXVfbm90aWZpZXIg aXMgbG9naWNhbGx5IGVxdWl2YWxlbnQgYmVjYXVzZQo+IF9fa3ZtX2ZvbGxvd19wZm4gcmVxdWly ZXMgdGhhdCBhdCBsZWFzdCBvbmUgb2YgZ3VhcmRlZF9ieV9tbXVfbm90aWZpZXIKPiBhbmQgRk9M TF9HRVQgaXMgc2V0LiBCdXQgc2luY2Ugd2UncmUgY29uY2VybmVkIGFib3V0IGEgcHJvcGVydHkg b2YgdGhlCj4gcmVmY291bnQsIEkgdGhpbmsgdGhhdCBjaGVja2luZyBGT0xMX0dFVCBpcyBjbGVh cmVyLgo+IAo+IEZvciBwcm9wZXJ0eSAyLCBGT0xMX0dFVCBpcyBhbHNvIGltcG9ydGFudC4gSWYg Z3VhcmRlZF9ieV9tbXVfbm90aWZpZXIKPiBpcyBzZXQsIHRoZW4gd2UncmUgYWxsIGdvb2QgaGVy ZS4gSWYgZ3VhcmRlZF9ieV9tbXVfbm90aWZpZXIgaXMgbm90Cj4gc2V0LCB0aGVuIHRoZSBjaGVj ayBpbiBfX2t2bV9mb2xsb3dfcGZuIGd1YXJhbnRlZXMgdGhhdCBGT0xMX0dFVCBpcwo+IHNldC4g Rm9yIHN0cnVjdCBwYWdlIG1lbW9yeSwgd2UncmUgc2FmZSBiZWNhdXNlIEtWTSB3aWxsIGhvbGQg YQo+IHJlZmVyZW5jZSBhcyBsb25nIGFzIGl0J3Mgc3RpbGwgdXNpbmcgdGhlIHBhZ2UuIEZvciBu b24gc3RydWN0IHBhZ2UKPiBtZW1vcnksIHdlJ3JlIG5vdCBzYWZlIC0gdGhpcyBpcyB3aGVyZSB0 aGUgYnJlYWtpbmcgY2hhbmdlIG9mCj4gYWxsb3dfdW5zYWZlX21hcHBpbmdzIHdvdWxkIGdvLiBO b3RlIHRoYXQgZm9yIG5vbi1yZWZjb3VudGVkIHN0cnVjdAo+IHBhZ2UsIHdlIGNhbid0IHVzZSB0 aGUgYWxsb3dfdW5zYWZlX21hcHBpbmdzIGVzY2FwZSBoYXRjaC4gU2luY2UKPiBGT0xMX0dFVCB3 YXMgcmVxdWVzdGVkLCBpZiB3ZSByZXR1cm5lZCBzdWNoIGEgcGFnZSwgdGhlbiB0aGUgY2FsbGVy Cj4gd291bGQgZXZlbnR1YWxseSBjb3JydXB0IHRoZSBwYWdlIHJlZmNvdW50IHZpYSBrdm1fcmVs ZWFzZV9wZm4uCgpZZXMgd2UgY2FuLiAgVGhlIGNhbGxlciBzaW1wbHkgbmVlZHMgdG8gYmUgbWFk ZSBhd2FyZSBvZiBpc19yZWZjb3VudGVkX3BhZ2UuICAgSQpkaWRuJ3QgaW5jbHVkZSB0aGF0IGlu IHRoZSBzbmlwcGV0IGJlbG93IGJlY2F1c2UgSSBkaWRuJ3Qgd2FudCB0byB3cml0ZSB0aGUgZW50 aXJlCnBhdGNoLiAgVGhlIHdob2xlIHBvaW50IG9mIGFkZGluZyBpc19yZWZjb3VudGVkX3BhZ2Ug aXMgc28gdGhhdCBjYWxsZXJzIGNhbgppZGVudGlmeSBleGFjdGx5IHdoYXQgdHlwZSBvZiBwYWdl IHdhcyBhdCB0aGUgZW5kIG9mIHRoZSB0cmFpbCB0aGF0IHdhcyBmb2xsb3dlZC4KCj4gUHJvcGVy dHkgMyB3b3VsZCBiZSBuaWNlLCBidXQgd2UndmUgYWxyZWFkeSBjb25jbHVkZWQgdGhhdCBndWFy ZGluZwo+IGFsbCB0cmFuc2xhdGlvbnMgd2l0aCBtbXUgbm90aWZpZXJzIGlzIGluZmVhc2libGUu IFNvIG1haW50YWluaW5nCj4gcHJvcGVydHkgMiBpcyB0aGUgYmVzdCB3ZSBjYW4gaG9wZSBmb3Iu CgpObywgIzMgaXMganVzdCBhIHZhcmlhbnQgb2YgIzIuICBVbmxlc3MgeW91J3JlIHRhbGtpbmcg YWJvdXQgbm90IG1ha2luZyBndWFyYW50ZWVzCmFib3V0IGd1ZXN0IGFjY2Vzc2VzIGJlaW5nIG9y ZGVyZWQgd2l0aCByZXNwZWN0IHRvIFZNQS9tZW1zbG90IHVwZGF0ZXMsIGJ1dCBJCmRvbid0IHRo aW5rIHRoYXQncyB0aGUgY2FzZS4KCj4gPiBBcyBmb3IgdGhlIG90aGVyIHVzYWdlIG9mIEZPTExf R0VUIGluIHRoaXMgc2VyaWVzICh1c2luZyBpdCB0byBjb25kaXRpb25hbGx5IGRvCj4gPiBwdXRf cGFnZSgpKSwgSU1PIHRoYXQncyB2ZXJ5IG11Y2ggcmVsYXRlZCB0byB0aGUgR1VQIGNhbGwuICBJ bnZva2luZyBwdXRfcGFnZSgpCj4gPiBpcyBhIGhhY2sgdG8gd29ya2Fyb3VuZCB0aGUgZmFjdCB0 aGF0IEdVUCBkb2Vzbid0IHByb3ZpZGUgYSB3YXkgdG8gZ2V0IHRoZSBwZm4KPiA+IHdpdGhvdXQg Z3JhYmJpbmcgYSByZWZlcmVuY2UgdG8gdGhlIHBhZ2UuICBJbiBhbiBpZGVhbCB3b3JsZCwgS1ZN IHdvdWxkIE5PVCBwYXNzCj4gPiBGT0xMX0dFVCB0byB0aGUgdmFyaW91cyBHVVAgaGVscGVycywg aS5lLiBGT0xMX0dFVCB3b3VsZCBiZSBwYXNzZWQgYXMtaXMgYW5kIEtWTQo+ID4gd291bGRuJ3Qg Im5lZWQiIHRvIGtpbmRhIHNvcnRhIG92ZXJsb2FkIEZPTExfR0VUIHRvIG1hbnVhbGx5IGRyb3Ag dGhlIHJlZmVyZW5jZS4KPiA+Cj4gPiBJIGRvIHRoaW5rIGl0J3Mgd29ydGggcHJvdmlkaW5nIGEg aGVscGVyIHRvIGNvbnNvbGlkYXRlIGFuZCBkb2N1bWVudCB0aGF0IGhhY2t5Cj4gPiBjb2RlLCBl LmcuIGFkZCBhIGt2bV9mb2xsb3dfcmVmY291bnRlZF9wZm4oKSBoZWxwZXIuCj4gPgo+ID4gQWxs IGluIGFsbCwgSSB0aGluayB0aGUgYmVsb3cgKGNvbXBsZXRlbHkgdW50ZXN0ZWQpIGlzIHdoYXQg d2Ugd2FudD8KPiA+Cj4gPiBEYXZpZCAoYW5kIG90aGVycyksIEkgYW0gcGxhbm5pbmcgb24gZG9p bmcgYSBmdWxsIHJldmlldyBvZiB0aGlzIHNlcmllcyAic29vbiIsCj4gPiBidXQgaXQgd2lsbCBs aWtlbHkgYmUgYSBmZXcgd2Vla3MgdW50aWwgdGhhdCBoYXBwZW5zLiAgSSBqdW1wZWQgaW4gb24g dGhpcwo+ID4gc3BlY2lmaWMgdGhyZWFkIGJlY2F1c2UgdGhpcyBjYXVnaHQgbXkgZXllIGFuZCBJ IHJlYWxseSBkb24ndCB3YW50IHRvIHRocm93IG91dAo+ID4gKmFsbCogb2YgdGhlIEZPTExfR0VU IHVzYWdlLgo+ID4KPiA+IGRpZmYgLS1naXQgYS92aXJ0L2t2bS9rdm1fbWFpbi5jIGIvdmlydC9r dm0va3ZtX21haW4uYwo+ID4gaW5kZXggNWI1YWZkNzBmMjM5Li45MGQ0MjQ5OTBlMGEgMTAwNjQ0 Cj4gPiAtLS0gYS92aXJ0L2t2bS9rdm1fbWFpbi5jCj4gPiArKysgYi92aXJ0L2t2bS9rdm1fbWFp bi5jCj4gPiBAQCAtMjQ4MSw2ICsyNDgxLDI1IEBAIHN0YXRpYyBpbmxpbmUgaW50IGNoZWNrX3Vz ZXJfcGFnZV9od3BvaXNvbih1bnNpZ25lZCBsb25nIGFkZHIpCj4gPiAgICAgICAgIHJldHVybiBy YyA9PSAtRUhXUE9JU09OOwo+ID4gIH0KPiA+Cj4gPiArc3RhdGljIGt2bV9wZm5fdCBrdm1fZm9s bG93X3JlZmNvdW50ZWRfcGZuKHN0cnVjdCBrdm1fZm9sbG93X3BmbiAqZm9sbCwKPiA+ICsgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgcGFnZSAqcGFnZSkK PiA+ICt7Cj4gPiArICAgICAgIGt2bV9wZm5fdCBwZm4gPSBwYWdlX3RvX3BmbihwYWdlKTsKPiA+ ICsKPiA+ICsgICAgICAgZm9sbC0+aXNfcmVmY291bnRlZF9wYWdlID0gdHJ1ZTsKPiA+ICsKPiA+ ICsgICAgICAgLyoKPiA+ICsgICAgICAgICogRklYTUU6IElkZWFsbHksIEtWTSB3b3VsZG4ndCBw YXNzIEZPTExfR0VUIHRvIGd1cCgpIHdoZW4gdGhlIGNhbGxlcgo+ID4gKyAgICAgICAgKiBkb2Vz bid0IHdhbnQgdG8gZ3JhYiBhIHJlZmVyZW5jZSwgYnV0IGd1cCgpIGRvZXNuJ3Qgc3VwcG9ydCBn ZXR0aW5nCj4gPiArICAgICAgICAqIGp1c3QgdGhlIHBmbiwgaS5lLiBGT0xMX0dFVCBpcyBlZmZl Y3RpdmVseSBtYW5kYXRvcnkuICBJZiB0aGF0IGV2ZXIKPiA+ICsgICAgICAgICogY2hhbmdlcywg ZHJvcCB0aGlzIGFuZCBzaW1wbHkgZG9uJ3QgcGFzcyBGT0xMX0dFVCB0byBndXAoKS4KPiA+ICsg ICAgICAgICovCj4gPiArICAgICAgIGlmICghKGZvbGwtPmZsYWdzICYgRk9MTF9HRVQpKQo+ID4g KyAgICAgICAgICAgICAgIHB1dF9wYWdlKHBhZ2UpOwo+ID4gKwo+ID4gKyAgICAgICByZXR1cm4g cGZuOwo+ID4gK30KPiA+ICsKPiA+ICAvKgo+ID4gICAqIFRoZSBmYXN0IHBhdGggdG8gZ2V0IHRo ZSB3cml0YWJsZSBwZm4gd2hpY2ggd2lsbCBiZSBzdG9yZWQgaW4gQHBmbiwKPiA+ICAgKiB0cnVl IGluZGljYXRlcyBzdWNjZXNzLCBvdGhlcndpc2UgZmFsc2UgaXMgcmV0dXJuZWQuICBJdCdzIGFs c28gdGhlCj4gPiBAQCAtMjUwMCwxMSArMjUxOSw5IEBAIHN0YXRpYyBib29sIGh2YV90b19wZm5f ZmFzdChzdHJ1Y3Qga3ZtX2ZvbGxvd19wZm4gKmZvbGwsIGt2bV9wZm5fdCAqcGZuKQo+ID4gICAg ICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKPiA+Cj4gPiAgICAgICAgIGlmIChnZXRfdXNlcl9w YWdlX2Zhc3Rfb25seShmb2xsLT5odmEsIEZPTExfV1JJVEUsIHBhZ2UpKSB7Cj4gPiAtICAgICAg ICAgICAgICAgKnBmbiA9IHBhZ2VfdG9fcGZuKHBhZ2VbMF0pOwo+ID4gICAgICAgICAgICAgICAg IGZvbGwtPndyaXRhYmxlID0gZm9sbC0+YWxsb3dfd3JpdGVfbWFwcGluZzsKPiA+IC0gICAgICAg ICAgICAgICBmb2xsLT5pc19yZWZjb3VudGVkX3BhZ2UgPSB0cnVlOwo+ID4gLSAgICAgICAgICAg ICAgIGlmICghKGZvbGwtPmZsYWdzICYgRk9MTF9HRVQpKQo+ID4gLSAgICAgICAgICAgICAgICAg ICAgICAgcHV0X3BhZ2UocGFnZVswXSk7Cj4gPiArCj4gPiArICAgICAgICAgICAgICAgKnBmbiA9 IGt2bV9mb2xsb3dfcmVmY291bnRlZF9wZm4oZm9sbCwgcGFnZVswXSk7Cj4gPiAgICAgICAgICAg ICAgICAgcmV0dXJuIHRydWU7Cj4gPiAgICAgICAgIH0KPiA+Cj4gPiBAQCAtMjUyOCw3ICsyNTQ1 LDYgQEAgc3RhdGljIGludCBodmFfdG9fcGZuX3Nsb3coc3RydWN0IGt2bV9mb2xsb3dfcGZuICpm b2xsLCBrdm1fcGZuX3QgKnBmbikKPiA+ICAgICAgICAgICAgICAgICByZXR1cm4gbnBhZ2VzOwo+ ID4KPiA+ICAgICAgICAgZm9sbC0+d3JpdGFibGUgPSAoZm9sbC0+ZmxhZ3MgJiBGT0xMX1dSSVRF KSAmJiBmb2xsLT5hbGxvd193cml0ZV9tYXBwaW5nOwo+ID4gLSAgICAgICBmb2xsLT5pc19yZWZj b3VudGVkX3BhZ2UgPSB0cnVlOwo+ID4KPiA+ICAgICAgICAgLyogbWFwIHJlYWQgZmF1bHQgYXMg d3JpdGFibGUgaWYgcG9zc2libGUgKi8KPiA+ICAgICAgICAgaWYgKHVubGlrZWx5KCFmb2xsLT53 cml0YWJsZSkgJiYgZm9sbC0+YWxsb3dfd3JpdGVfbWFwcGluZykgewo+ID4gQEAgLTI1NDAsOSAr MjU1Niw4IEBAIHN0YXRpYyBpbnQgaHZhX3RvX3Bmbl9zbG93KHN0cnVjdCBrdm1fZm9sbG93X3Bm biAqZm9sbCwga3ZtX3Bmbl90ICpwZm4pCj4gPiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdl ID0gd3BhZ2U7Cj4gPiAgICAgICAgICAgICAgICAgfQo+ID4gICAgICAgICB9Cj4gPiAtICAgICAg ICpwZm4gPSBwYWdlX3RvX3BmbihwYWdlKTsKPiA+IC0gICAgICAgaWYgKCEoZm9sbC0+ZmxhZ3Mg JiBGT0xMX0dFVCkpCj4gPiAtICAgICAgICAgICAgICAgcHV0X3BhZ2UocGFnZSk7Cj4gPiArCj4g PiArICAgICAgICpwZm4gPSBrdm1fZm9sbG93X3JlZmNvdW50ZWRfcGZuKGZvbGwsIHBhZ2UpOwo+ ID4gICAgICAgICByZXR1cm4gbnBhZ2VzOwo+ID4gIH0KPiA+Cj4gPiBAQCAtMjYxMCwxNyArMjYy NSwxNiBAQCBzdGF0aWMgaW50IGh2YV90b19wZm5fcmVtYXBwZWQoc3RydWN0IHZtX2FyZWFfc3Ry dWN0ICp2bWEsIHN0cnVjdCBrdm1fZm9sbG93X3Bmbgo+ID4gICAgICAgICBpZiAoIXBhZ2UpCj4g PiAgICAgICAgICAgICAgICAgZ290byBvdXQ7Cj4gPgo+ID4gLSAgICAgICBpZiAoZ2V0X3BhZ2Vf dW5sZXNzX3plcm8ocGFnZSkpIHsKPiA+IC0gICAgICAgICAgICAgICBmb2xsLT5pc19yZWZjb3Vu dGVkX3BhZ2UgPSB0cnVlOwo+ID4gLSAgICAgICAgICAgICAgIGlmICghKGZvbGwtPmZsYWdzICYg Rk9MTF9HRVQpKQo+ID4gLSAgICAgICAgICAgICAgICAgICAgICAgcHV0X3BhZ2UocGFnZSk7Cj4g PiAtICAgICAgIH0gZWxzZSBpZiAoZm9sbC0+ZmxhZ3MgJiBGT0xMX0dFVCkgewo+ID4gLSAgICAg ICAgICAgICAgIHIgPSAtRUZBVUxUOwo+ID4gLSAgICAgICB9Cj4gPiAtCj4gPiArICAgICAgIGlm IChnZXRfcGFnZV91bmxlc3NfemVybyhwYWdlKSkKPiA+ICsgICAgICAgICAgICAgICBXQVJOX09O X09OQ0Uoa3ZtX2ZvbGxvd19yZWZjb3VudGVkX3Bmbihmb2xsLCBwYWdlKSAhPSBwZm4pOwo+ID4g IG91dDoKPiA+ICAgICAgICAgcHRlX3VubWFwX3VubG9jayhwdGVwLCBwdGwpOwo+ID4gLSAgICAg ICAqcF9wZm4gPSBwZm47Cj4gPiArCj4gPiArICAgICAgIGlmICghZm9sbC0+aXNfcmVmY291bnRl ZF9wYWdlICYmICFmb2xsLT5ndWFyZGVkX2J5X21tdV9ub3RpZmllciAmJgo+ID4gKyAgICAgICAg ICAgIWFsbG93X3Vuc2FmZV9tYXBwaW5ncykKPiA+ICsgICAgICAgICAgICAgICByID0gLUVGQVVM VDsKPiA+ICsgICAgICAgZWxzZQo+ID4gKyAgICAgICAgICAgICAgICpwX3BmbiA9IHBmbjsKPiA+ Cj4gPiAgICAgICAgIHJldHVybiByOwo+ID4gIH0KPiA+Cj4gCj4gQXMgSSBwb2ludGVkIG91dCBh Ym92ZSwgdGhpcyBzdWdnZXN0aW9uIGlzIGJyb2tlbiBiZWNhdXNlIGEgRk9MTF9HRVQKPiAmJiAh Z3VhcmRlZF9ieV9tbXVfbm90aWZpZXIgcmVxdWVzdCAoZS5nLiBrdm1fdmNwdV9tYXApIGZvciBh Cj4gbm9uLXJlZmNvdW50ZWQgcGFnZSB3aWxsIHJlc3VsdCBpbiB0aGUgcmVmY291bnQgZXZlbnR1 YWxseSBiZWluZwo+IGNvcnJ1cHRlZC4KCkkgZG9uJ3QgdGhpbmsgc28sIHVubGVzcyBJJ20gbWlz dW5kZXJzdGFuZGluZyB0aGUgY29uY2Vybi4gIEl0IGp1c3Qgd2Fzbid0IGEKY29tcGxldGUgcGF0 Y2gsIGFuZCB3YXNuJ3QgaW50ZW5kZWQgdG8gYmUuCgo+IFdoYXQgZG8geW91IHRoaW5rIG9mIHRo aXMgaW1wbGVtZW50YXRpb24/IElmIGl0IG1ha2VzIHNlbnNlLCBJIGNhbgo+IHNlbmQgb3V0IGFu IHVwZGF0ZWQgcGF0Y2ggc2VyaWVzLgo+Cj4gLyoKPiAgKiBJZiBGT0xMX0dFVCBpcyBzZXQsIHRo ZW4gdGhlIGNhbGxlciB3YW50cyB1cyB0byB0YWtlIGEgcmVmZXJlbmNlIHRvCj4gICoga2VlcCB0 aGUgcGZuIGFsaXZlLiBJZiBGT0xMX0dFVCBpc24ndCBzZXQsIHRoZW4gX19rdm1fZm9sbG93X3Bm bgo+ICAqIGd1YXJhbnRlZXMgdGhhdCBndWFyZGVkX2J5X21tdV9ub3RpZmllciBpcyBzZXQsIHNv IHRoZXJlIGFyZW4ndCBhbnkKPiAgKiB1c2UtYWZ0ZXItZnJlZSBjb25jZXJucy4KPiAgKi8KPiBw YWdlID0ga3ZtX3Bmbl90b19yZWZjb3VudGVkX3BhZ2UocGZuKTsKPiBpZiAocGFnZSkgewo+ICAg ICAgICAgaWYgKGdldF9wYWdlX3VubGVzc196ZXJvKHBhZ2UpKSB7Cj4gICAgICAgICAgICAgICAg IFdBUk5fT05fT05DRShrdm1fZm9sbG93X3JlZmNvdW50ZWRfcGZuKGZvbGwsIHBhZ2UpICE9IHBm bik7Cj4gICAgICAgICB9IGVsc2UgaWYgKGZvbGwtPmZsYWdzICYgRk9MTF9HRVQpIHsKPiAgICAg ICAgICAgICAgICAgLyoKPiAgICAgICAgICAgICAgICAgICogQ2VydGFpbiBJTyBvciBQRk5NQVAg bWFwcGluZ3MgY2FuIGJlIGJhY2tlZCB3aXRoCj4gICAgICAgICAgICAgICAgICAqIHZhbGlkIHN0 cnVjdCBwYWdlcyBidXQgYmUgYWxsb2NhdGVkIHdpdGhvdXQKPiAgICAgICAgICAgICAgICAgICog cmVmY291bnRpbmcgZS5nLiwgdGFpbCBwYWdlcyBvZiBub24tY29tcG91bmQgaGlnaGVyCj4gICAg ICAgICAgICAgICAgICAqIG9yZGVyIGFsbG9jYXRpb25zLiBUaGUgY2FsbGVyIGFza2VkIGZvciBh IHJlZiwgYnV0Cj4gICAgICAgICAgICAgICAgICAqIHdlIGNhbid0IHRha2Ugb25lLCBzaW5jZSBy ZWxlYXNpbmcgc3VjaCBhIHJlZiB3b3VsZAo+ICAgICAgICAgICAgICAgICAgKiBmcmVlIHRoZSBw YWdlLgo+ICAgICAgICAgICAgICAgICAgKi8KPiAgICAgICAgICAgICAgICAgciA9IC1FRkFVTFQ7 Cj4gICAgICAgICB9Cj4gfSBlbHNlIGlmIChmb2xsLT5mbGFncyAmIEZPTExfR0VUKSB7Cj4gICAg ICAgICAvKgo+ICAgICAgICAgICogV2hlbiB0aGVyZSdzIG5vIHN0cnVjdCBwYWdlIHRvIHJlZmNv dW50IGFuZCBubyBNTVUgbm90aWZpZXIsCj4gICAgICAgICAgKiB0aGVuIEtWTSBjYW4ndCBiZSBn dWFyYW50ZWUgdG8gYXZvaWQgdXNlLWFmdGVyLWZyZWUuIEhvd2V2ZXIsCj4gICAgICAgICAgKiB0 aGVyZSBhcmUgdmFsaWQgcmVhc29ucyB0byBzZXQgdXAgc3VjaCBtYXBwaW5ncy4gSWYgdXNlcnNw YWNlCj4gICAgICAgICAgKiBpcyB0cnVzdGVkIGFuZCB3aWxsaW5nIHRvIGZvcmVnbyBrZXJuZWwg c2FmZXR5IGd1YXJhbnRlZXMsCj4gICAgICAgICAgKiBhbGxvdyB0aGlzIGNoZWNrIHRvIGJlIGJ5 cGFzc2VkLgo+ICAgICAgICAgICovCj4gICAgICAgICBpZiAoZm9sbC0+Z3VhcmRlZF9ieV9tbXVf bm90aWZpZXIgJiYgIWFsbG93X3Vuc2FmZV9tYXBwaW5ncykKCkkgYXNzdW1lIHlvdSBtZWFuOgoK CWlmICghZm9sbC0+Z3VhcmRlZF9ieV9tbXVfbm90aWZpZXIgJiYgIWFsbG93X3Vuc2FmZV9tYXBw aW5ncykKCj4gICAgICAgICAgICAgICAgIHIgPSAtRUZBVUxUOwo+IH0KClBsZWFzZSBuby4gIEkg ZG9uJ3Qgd2FudCB0byBvdmVybG9hZCBGT0xMX0dFVCBvciBoYXZlIGRlcGVuZGVuY2llcyBiZXR3 ZWVuCkZPTExfR0VUIGFuZCBndWFyZGVkX2J5X21tdV9ub3RpZmllci4gIFRoZSBndWVzdCBwYWdl IGZhdWx0IHBhdGggc2hvdWxkIGJlIGFibGUKdG8gb21pdCBGT0xMX0dFVCwgYW5kIGl0IG9idmlv dXNseSBzaG91bGQgc2V0IGd1YXJkZWRfYnlfbW11X25vdGlmaWVyLiAgQW5kCmt2bV92Y3B1X21h cCgpIHNob3VsZCBiZSBhYmxlIHRvIHNldCBGT0xMX0dFVCwgb21pdCBndWFyZGVkX2J5X21tdV9u b3RpZmllciwgX2FuZF8KcGxheSBuaWNlIHdpdGggInVuc2FmZSIsIG5vbi1yZWZjb3VudGVkIG1l bW9yeSB3aGVuIGFsbG93X3Vuc2FmZV9tYXBwaW5ncyBpcyB0cnVlLgoKVGhlIGFib3ZlIGZpdHMg eW91ciB1c2UgY2FzZSBiZWNhdXNlIG5vdGhpbmcgaW4gS1ZNIG5lZWRzIHRvIGRvIGt2bV92Y3B1 X21hcCgpCm9uIHRoZSBHUFUncyBidWZmZXIsIGJ1dCBhcyBhIGdlbmVyYWwgc29sdXRpb24gdGhl IHNlbWFudGljcyBhcmUgdmVyeSBvZGQuICBFLmcuCmluIGxvbmcgZm9ybSwgdGhleSBhcmU6Cgog IEdldCBnZXQgYSByZWZlcmVuY2UgaWYgYSB0aGVyZSdzIGEgcmVmY291bnRlZCBwYWdlLCBmYWls IHdpdGggLUVGQVVMVCBpZiB0aGVyZSdzCiAgYSBzdHJ1Y3QgcGFnZSBidXQgaXQncyBub3QgcmVm Y291bnRlZCwgYW5kIGZhaWwgd2l0aCAtRUZBVUxUIGlmIHRoZXJlJ3Mgbm90IHN0cnVjdAogIHBh Z2UgdW5sZXNzIHRoZSBjYWxsZXIgaXMgcHJvdGVjdGVkIGJ5IG1tdV9ub3RpZmllcnMgb3IgdW5z YWZlIG1hcHBpbmdzIGFyZSBhbGxvd2VkLgoKVGhhdCdzIHJhdGhlciBib25rZXJzLiAgV2hhdCBJ IGluc3RlYWQgd2FudCBpcyBGT0xMX0dFVCB0byBiZToKCiAgR2V0IGEgcmVmZXJlbmNlIGlmIHRo ZXJlJ3MgYSByZWZjb3VudGVkIHBhZ2UuCgpBbmQgdGhlbiBhbGxvd191bnNhZmVfbWFwcGluZ3Mg aXMgc2ltcGx5OgoKICBBbGxvdyBtYXBwaW5nIG5vbi1yZWZjb3VudGVkIG1lbW9yeSBpbnRvIHRo ZSBndWVzdCBldmVuIGlmIHRoZSBtYXBwaW5nIGlzbid0CiAgZ3VhcmRlZCBieSBtbXVfbm90aWZp ZXIgZXZlbnRzLgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X18KbGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5p bmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8v bGludXgtYXJtLWtlcm5lbAo=