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 X-Spam-Level: X-Spam-Status: No, score=-2.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DA2A2C11F6A for ; Fri, 2 Jul 2021 07:01:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BE1CA613EE for ; Fri, 2 Jul 2021 07:01:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229956AbhGBHEA (ORCPT ); Fri, 2 Jul 2021 03:04:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54450 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229542AbhGBHD7 (ORCPT ); Fri, 2 Jul 2021 03:03:59 -0400 Received: from mail-pl1-x633.google.com (mail-pl1-x633.google.com [IPv6:2607:f8b0:4864:20::633]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 083B2C061762; Fri, 2 Jul 2021 00:01:26 -0700 (PDT) Received: by mail-pl1-x633.google.com with SMTP id d1so5092258plg.6; Fri, 02 Jul 2021 00:01:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=pOxwy4S8+CMaHsFPZCERpcLAZFzgkbgCU7ysS2kserA=; b=C7iqWm/wesRNy/TjG2rGEA+W4kQ+TyHVuuL7z1F62PhJmxaaEoArlcQc84EmSneSqz iznC5OCPYsOsUJxJhgRSMTidOscJf/aghiOmDfzN8vcOyS9Ktom0AAY3oZkSKKjSXO1d bNX6lm2SULxR5MVs+e4vybMcekoS7NI2FBZQjmcpcDVbq1yNnSJqb1zN5kPr2Z1pUbNk A5G6ojm9VhQ8EdJjli5tjWX9R26cjvQG9ITwcfWD6VHn+xMCAGOok6yLzhJ4HNTQ0yGZ /Y/LCtDHcowpYrJJLDpAoIzycnxxFSBNvQyxIEhjKJ4y6wPKqpXxQSs7x9PXOvzmkcds oZlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=pOxwy4S8+CMaHsFPZCERpcLAZFzgkbgCU7ysS2kserA=; b=Huu+9TsdpC67OgbLtHNe97lTzt0BMZGwO1TZvd24qV+NJdw7gnEWIp5Uwuv6LHBn6f c6eAxbeZtsOsoqKHPgunxvYoEpgAUd1mZ/efIr2eCOZ8wbsNFAwjpwkNsHP4Q3Wk+l7U nnjbYGPrvgyN0cZSeqF3e9U0hwNzHvuIk4TrJ76lXzWgt5FyggnjwpOPWs8FHdM/Fzfv HyA/6AG6TLYR31bbHPsLqpEwxW4MPvzPlXYg4dSZhu5KRwhSJ3ZDvyrJfmPQVVK8yMGM vlg4C+CUvyJJzm/PbUy2K3Bn1ULQOTfswHII3PbJMSuebLUW6T6Pa5Q5/uqqHn/2fen5 mrVA== X-Gm-Message-State: AOAM532/9WmDYzMI5jjeNew+IGS7zo07YLsSuNgdPUp6UtYdnqj0T2Cw GkHXysuYazLxjWC3VTCIoSI= X-Google-Smtp-Source: ABdhPJyfi/fuR+AXjHafBzne+j9YCvbhOaUZINfEYssRYGLtqsbz0Nrvakl5C11G5EnSvNYHMM3PVw== X-Received: by 2002:a17:90b:4c4b:: with SMTP id np11mr13875779pjb.125.1625209286236; Fri, 02 Jul 2021 00:01:26 -0700 (PDT) Received: from gmail.com ([2601:600:8500:5f14:d627:c51e:516e:a105]) by smtp.gmail.com with ESMTPSA id p14sm2378495pgb.2.2021.07.02.00.01.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Jul 2021 00:01:25 -0700 (PDT) Date: Thu, 1 Jul 2021 23:57:53 -0700 From: Andrei Vagin To: Jann Horn Cc: kernel list , Linux API , linux-um@lists.infradead.org, criu@openvz.org, avagin@google.com, Andrew Morton , Andy Lutomirski , Anton Ivanov , Christian Brauner , Dmitry Safonov <0x7f454c46@gmail.com>, Ingo Molnar , Jeff Dike , Mike Rapoport , Michael Kerrisk , Oleg Nesterov , Peter Zijlstra , Richard Weinberger , Thomas Gleixner , linux-mm@kvack.org Subject: Re: [PATCH 0/4 POC] Allow executing code and syscalls in another address space Message-ID: References: <20210414055217.543246-1-avagin@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-api@vger.kernel.org On Wed, Apr 14, 2021 at 08:46:40AM +0200, Jann Horn wrote: > On Wed, Apr 14, 2021 at 7:59 AM Andrei Vagin wrote: > > We already have process_vm_readv and process_vm_writev to read and write > > to a process memory faster than we can do this with ptrace. And now it > > is time for process_vm_exec that allows executing code in an address > > space of another process. We can do this with ptrace but it is much > > slower. > > > > = Use-cases = > > It seems to me like your proposed API doesn't really fit either one of > those usecases well... > > > Here are two known use-cases. The first one is “application kernel” > > sandboxes like User-mode Linux and gVisor. In this case, we have a > > process that runs the sandbox kernel and a set of stub processes that > > are used to manage guest address spaces. Guest code is executed in the > > context of stub processes but all system calls are intercepted and > > handled in the sandbox kernel. Right now, these sort of sandboxes use > > PTRACE_SYSEMU to trap system calls, but the process_vm_exec can > > significantly speed them up. > > In this case, since you really only want an mm_struct to run code > under, it seems weird to create a whole task with its own PID and so > on. It seems to me like something similar to the /dev/kvm API would be > more appropriate here? Implementation options that I see for that > would be: > > 1. mm_struct-based: > a set of syscalls to create a new mm_struct, > change memory mappings under that mm_struct, and switch to it I like the idea to have a handle for mm. Instead of pid, we will pass this handle to process_vm_exec. We have pidfd for processes and we can introduce mmfd for mm_struct. > 2. pagetable-mirroring-based: > like /dev/kvm, an API to create a new pagetable, mirror parts of > the mm_struct's pagetables over into it with modified permissions > (like KVM_SET_USER_MEMORY_REGION), > and run code under that context. > page fault handling would first handle the fault against mm->pgd > as normal, then mirror the PTE over into the secondary pagetables. > invalidation could be handled with MMU notifiers. > I found this idea interesting and decided to look at it more closely. After reading the kernel code for a few days, I realized that it would not be easy to implement something like this, but more important is that I don’t understand what problem it solves. Will it simplify the user-space code? I don’t think so. Will it improve performance? It is unclear for me too. First, in the KVM case, we have a few big linear mappings and need to support one “shadow” address space. In the case of sandboxes, we can have a tremendous amount of mappings and many address spaces that we need to manage. Memory mappings will be mapped with different addresses in a supervisor address space and “guest” address spaces. If guest address spaces will not have their mm_structs, we will need to reinvent vma-s in some form. If guest address spaces have mm_structs, this will look similar to https://lwn.net/Articles/830648/. Second, each pagetable is tied up with mm_stuct. You suggest creating new pagetables that will not have their mm_struct-s (sorry if I misunderstood something). I am not sure that it will be easy to implement. How many corner cases will be there? As for page faults in a secondary address space, we will need to find a fault address in the main address space, handle the fault there and then mirror the PTE to the secondary pagetable. Effectively, it means that page faults will be handled in two address spaces. Right now, we use memfd and shared mappings. It means that each fault is handled only in one address space, and we map a guest memory region to the supervisor address space only when we need to access it. A large portion of guest anonymous memory is never mapped to the supervisor address space. Will an overhead of mirrored address spaces be smaller than memfd shared mappings? I am not sure. Third, this approach will not get rid of having process_vm_exec. We will need to switch to a guest address space with a specified state and switch back on faults or syscalls. If the main concern is the ability to run syscalls on a remote mm, we can think about how to fix this. I see two ways what we can do here: * Specify the exact list of system calls that are allowed. The first three candidates are mmap, munmap, and vmsplice. * Instead of allowing us to run system calls, we can implement this in the form of commands. In the case of sandboxes, we need to implement only two commands to create and destroy memory mappings in a target address space. Thanks, Andrei From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x1034.google.com ([2607:f8b0:4864:20::1034]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1lzDB1-002LNP-4k for linux-um@lists.infradead.org; Fri, 02 Jul 2021 07:01:30 +0000 Received: by mail-pj1-x1034.google.com with SMTP id in17-20020a17090b4391b0290170ba0ec7fcso8232041pjb.4 for ; Fri, 02 Jul 2021 00:01:26 -0700 (PDT) Date: Thu, 1 Jul 2021 23:57:53 -0700 From: Andrei Vagin Subject: Re: [PATCH 0/4 POC] Allow executing code and syscalls in another address space Message-ID: References: <20210414055217.543246-1-avagin@gmail.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: 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-um" Errors-To: linux-um-bounces+geert=linux-m68k.org@lists.infradead.org To: Jann Horn Cc: kernel list , Linux API , linux-um@lists.infradead.org, criu@openvz.org, avagin@google.com, Andrew Morton , Andy Lutomirski , Anton Ivanov , Christian Brauner , Dmitry Safonov <0x7f454c46@gmail.com>, Ingo Molnar , Jeff Dike , Mike Rapoport , Michael Kerrisk , Oleg Nesterov , Peter Zijlstra , Richard Weinberger , Thomas Gleixner , linux-mm@kvack.org T24gV2VkLCBBcHIgMTQsIDIwMjEgYXQgMDg6NDY6NDBBTSArMDIwMCwgSmFubiBIb3JuIHdyb3Rl Ogo+IE9uIFdlZCwgQXByIDE0LCAyMDIxIGF0IDc6NTkgQU0gQW5kcmVpIFZhZ2luIDxhdmFnaW5A Z21haWwuY29tPiB3cm90ZToKPiA+IFdlIGFscmVhZHkgaGF2ZSBwcm9jZXNzX3ZtX3JlYWR2IGFu ZCBwcm9jZXNzX3ZtX3dyaXRldiB0byByZWFkIGFuZCB3cml0ZQo+ID4gdG8gYSBwcm9jZXNzIG1l bW9yeSBmYXN0ZXIgdGhhbiB3ZSBjYW4gZG8gdGhpcyB3aXRoIHB0cmFjZS4gQW5kIG5vdyBpdAo+ ID4gaXMgdGltZSBmb3IgcHJvY2Vzc192bV9leGVjIHRoYXQgYWxsb3dzIGV4ZWN1dGluZyBjb2Rl IGluIGFuIGFkZHJlc3MKPiA+IHNwYWNlIG9mIGFub3RoZXIgcHJvY2Vzcy4gV2UgY2FuIGRvIHRo aXMgd2l0aCBwdHJhY2UgYnV0IGl0IGlzIG11Y2gKPiA+IHNsb3dlci4KPiA+Cj4gPiA9IFVzZS1j YXNlcyA9Cj4gCj4gSXQgc2VlbXMgdG8gbWUgbGlrZSB5b3VyIHByb3Bvc2VkIEFQSSBkb2Vzbid0 IHJlYWxseSBmaXQgZWl0aGVyIG9uZSBvZgo+IHRob3NlIHVzZWNhc2VzIHdlbGwuLi4KPiAKPiA+ IEhlcmUgYXJlIHR3byBrbm93biB1c2UtY2FzZXMuIFRoZSBmaXJzdCBvbmUgaXMg4oCcYXBwbGlj YXRpb24ga2VybmVs4oCdCj4gPiBzYW5kYm94ZXMgbGlrZSBVc2VyLW1vZGUgTGludXggYW5kIGdW aXNvci4gSW4gdGhpcyBjYXNlLCB3ZSBoYXZlIGEKPiA+IHByb2Nlc3MgdGhhdCBydW5zIHRoZSBz YW5kYm94IGtlcm5lbCBhbmQgYSBzZXQgb2Ygc3R1YiBwcm9jZXNzZXMgdGhhdAo+ID4gYXJlIHVz ZWQgdG8gbWFuYWdlIGd1ZXN0IGFkZHJlc3Mgc3BhY2VzLiBHdWVzdCBjb2RlIGlzIGV4ZWN1dGVk IGluIHRoZQo+ID4gY29udGV4dCBvZiBzdHViIHByb2Nlc3NlcyBidXQgYWxsIHN5c3RlbSBjYWxs cyBhcmUgaW50ZXJjZXB0ZWQgYW5kCj4gPiBoYW5kbGVkIGluIHRoZSBzYW5kYm94IGtlcm5lbC4g UmlnaHQgbm93LCB0aGVzZSBzb3J0IG9mIHNhbmRib3hlcyB1c2UKPiA+IFBUUkFDRV9TWVNFTVUg dG8gdHJhcCBzeXN0ZW0gY2FsbHMsIGJ1dCB0aGUgcHJvY2Vzc192bV9leGVjIGNhbgo+ID4gc2ln bmlmaWNhbnRseSBzcGVlZCB0aGVtIHVwLgo+IAo+IEluIHRoaXMgY2FzZSwgc2luY2UgeW91IHJl YWxseSBvbmx5IHdhbnQgYW4gbW1fc3RydWN0IHRvIHJ1biBjb2RlCj4gdW5kZXIsIGl0IHNlZW1z IHdlaXJkIHRvIGNyZWF0ZSBhIHdob2xlIHRhc2sgd2l0aCBpdHMgb3duIFBJRCBhbmQgc28KPiBv bi4gSXQgc2VlbXMgdG8gbWUgbGlrZSBzb21ldGhpbmcgc2ltaWxhciB0byB0aGUgL2Rldi9rdm0g QVBJIHdvdWxkIGJlCj4gbW9yZSBhcHByb3ByaWF0ZSBoZXJlPyBJbXBsZW1lbnRhdGlvbiBvcHRp b25zIHRoYXQgSSBzZWUgZm9yIHRoYXQKPiB3b3VsZCBiZToKPiAKPiAxLiBtbV9zdHJ1Y3QtYmFz ZWQ6Cj4gICAgICAgYSBzZXQgb2Ygc3lzY2FsbHMgdG8gY3JlYXRlIGEgbmV3IG1tX3N0cnVjdCwK PiAgICAgICBjaGFuZ2UgbWVtb3J5IG1hcHBpbmdzIHVuZGVyIHRoYXQgbW1fc3RydWN0LCBhbmQg c3dpdGNoIHRvIGl0CgpJIGxpa2UgdGhlIGlkZWEgdG8gaGF2ZSBhIGhhbmRsZSBmb3IgbW0uIElu c3RlYWQgb2YgcGlkLCB3ZSB3aWxsIHBhc3MKdGhpcyBoYW5kbGUgdG8gcHJvY2Vzc192bV9leGVj LiBXZSBoYXZlIHBpZGZkIGZvciBwcm9jZXNzZXMgYW5kIHdlIGNhbgppbnRyb2R1Y2UgbW1mZCBm b3IgbW1fc3RydWN0LgoKCj4gMi4gcGFnZXRhYmxlLW1pcnJvcmluZy1iYXNlZDoKPiAgICAgICBs aWtlIC9kZXYva3ZtLCBhbiBBUEkgdG8gY3JlYXRlIGEgbmV3IHBhZ2V0YWJsZSwgbWlycm9yIHBh cnRzIG9mCj4gICAgICAgdGhlIG1tX3N0cnVjdCdzIHBhZ2V0YWJsZXMgb3ZlciBpbnRvIGl0IHdp dGggbW9kaWZpZWQgcGVybWlzc2lvbnMKPiAgICAgICAobGlrZSBLVk1fU0VUX1VTRVJfTUVNT1JZ X1JFR0lPTiksCj4gICAgICAgYW5kIHJ1biBjb2RlIHVuZGVyIHRoYXQgY29udGV4dC4KPiAgICAg ICBwYWdlIGZhdWx0IGhhbmRsaW5nIHdvdWxkIGZpcnN0IGhhbmRsZSB0aGUgZmF1bHQgYWdhaW5z dCBtbS0+cGdkCj4gICAgICAgYXMgbm9ybWFsLCB0aGVuIG1pcnJvciB0aGUgUFRFIG92ZXIgaW50 byB0aGUgc2Vjb25kYXJ5IHBhZ2V0YWJsZXMuCj4gICAgICAgaW52YWxpZGF0aW9uIGNvdWxkIGJl IGhhbmRsZWQgd2l0aCBNTVUgbm90aWZpZXJzLgo+CgpJIGZvdW5kIHRoaXMgaWRlYSBpbnRlcmVz dGluZyBhbmQgZGVjaWRlZCB0byBsb29rIGF0IGl0IG1vcmUgY2xvc2VseS4KQWZ0ZXIgcmVhZGlu ZyB0aGUga2VybmVsIGNvZGUgZm9yIGEgZmV3IGRheXMsIEkgcmVhbGl6ZWQgdGhhdCBpdCB3b3Vs ZApub3QgYmUgZWFzeSB0byBpbXBsZW1lbnQgc29tZXRoaW5nIGxpa2UgdGhpcywgYnV0IG1vcmUg aW1wb3J0YW50IGlzIHRoYXQKSSBkb27igJl0IHVuZGVyc3RhbmQgd2hhdCBwcm9ibGVtIGl0IHNv bHZlcy4gV2lsbCBpdCBzaW1wbGlmeSB0aGUKdXNlci1zcGFjZSBjb2RlPyBJIGRvbuKAmXQgdGhp bmsgc28uIFdpbGwgaXQgaW1wcm92ZSBwZXJmb3JtYW5jZT8gSXQgaXMKdW5jbGVhciBmb3IgbWUg dG9vLgoKRmlyc3QsIGluIHRoZSBLVk0gY2FzZSwgd2UgaGF2ZSBhIGZldyBiaWcgbGluZWFyIG1h cHBpbmdzIGFuZCBuZWVkIHRvCnN1cHBvcnQgb25lIOKAnHNoYWRvd+KAnSBhZGRyZXNzIHNwYWNl LiBJbiB0aGUgY2FzZSBvZiBzYW5kYm94ZXMsIHdlIGNhbgpoYXZlIGEgdHJlbWVuZG91cyBhbW91 bnQgb2YgbWFwcGluZ3MgYW5kIG1hbnkgYWRkcmVzcyBzcGFjZXMgdGhhdCB3ZQpuZWVkIHRvIG1h bmFnZS4gIE1lbW9yeSBtYXBwaW5ncyB3aWxsIGJlIG1hcHBlZCB3aXRoIGRpZmZlcmVudCBhZGRy ZXNzZXMKaW4gYSBzdXBlcnZpc29yIGFkZHJlc3Mgc3BhY2UgYW5kIOKAnGd1ZXN04oCdIGFkZHJl c3Mgc3BhY2VzLiBJZiBndWVzdAphZGRyZXNzIHNwYWNlcyB3aWxsIG5vdCBoYXZlIHRoZWlyIG1t X3N0cnVjdHMsIHdlIHdpbGwgbmVlZCB0byByZWludmVudAp2bWEtcyBpbiBzb21lIGZvcm0uIElm IGd1ZXN0IGFkZHJlc3Mgc3BhY2VzIGhhdmUgbW1fc3RydWN0cywgdGhpcyB3aWxsCmxvb2sgc2lt aWxhciB0byBodHRwczovL2x3bi5uZXQvQXJ0aWNsZXMvODMwNjQ4Ly4KClNlY29uZCwgZWFjaCBw YWdldGFibGUgaXMgdGllZCB1cCB3aXRoIG1tX3N0dWN0LiBZb3Ugc3VnZ2VzdCBjcmVhdGluZwpu ZXcgcGFnZXRhYmxlcyB0aGF0IHdpbGwgbm90IGhhdmUgdGhlaXIgbW1fc3RydWN0LXMgKHNvcnJ5 IGlmIEkKbWlzdW5kZXJzdG9vZCBzb21ldGhpbmcpLiBJIGFtIG5vdCBzdXJlIHRoYXQgaXQgd2ls bCBiZSBlYXN5IHRvCmltcGxlbWVudC4gSG93IG1hbnkgY29ybmVyIGNhc2VzIHdpbGwgYmUgdGhl cmU/CgpBcyBmb3IgcGFnZSBmYXVsdHMgaW4gYSBzZWNvbmRhcnkgYWRkcmVzcyBzcGFjZSwgd2Ug d2lsbCBuZWVkIHRvIGZpbmQgYQpmYXVsdCBhZGRyZXNzIGluIHRoZSBtYWluIGFkZHJlc3Mgc3Bh Y2UsIGhhbmRsZSB0aGUgZmF1bHQgdGhlcmUgYW5kIHRoZW4KbWlycm9yIHRoZSBQVEUgdG8gdGhl IHNlY29uZGFyeSBwYWdldGFibGUuIEVmZmVjdGl2ZWx5LCBpdCBtZWFucyB0aGF0CnBhZ2UgZmF1 bHRzIHdpbGwgYmUgaGFuZGxlZCBpbiB0d28gYWRkcmVzcyBzcGFjZXMuIFJpZ2h0IG5vdywgd2Ug dXNlCm1lbWZkIGFuZCBzaGFyZWQgbWFwcGluZ3MuIEl0IG1lYW5zIHRoYXQgZWFjaCBmYXVsdCBp cyBoYW5kbGVkIG9ubHkgaW4Kb25lIGFkZHJlc3Mgc3BhY2UsIGFuZCB3ZSBtYXAgYSBndWVzdCBt ZW1vcnkgcmVnaW9uIHRvIHRoZSBzdXBlcnZpc29yCmFkZHJlc3Mgc3BhY2Ugb25seSB3aGVuIHdl IG5lZWQgdG8gYWNjZXNzIGl0LiBBIGxhcmdlIHBvcnRpb24gb2YgZ3Vlc3QKYW5vbnltb3VzIG1l bW9yeSBpcyBuZXZlciBtYXBwZWQgdG8gdGhlIHN1cGVydmlzb3IgYWRkcmVzcyBzcGFjZS4KV2ls bCBhbiBvdmVyaGVhZCBvZiBtaXJyb3JlZCBhZGRyZXNzIHNwYWNlcyBiZSBzbWFsbGVyIHRoYW4g bWVtZmQgc2hhcmVkCm1hcHBpbmdzPyBJIGFtIG5vdCBzdXJlLgoKVGhpcmQsIHRoaXMgYXBwcm9h Y2ggd2lsbCBub3QgZ2V0IHJpZCBvZiBoYXZpbmcgcHJvY2Vzc192bV9leGVjLiBXZSB3aWxsCm5l ZWQgdG8gc3dpdGNoIHRvIGEgZ3Vlc3QgYWRkcmVzcyBzcGFjZSB3aXRoIGEgc3BlY2lmaWVkIHN0 YXRlIGFuZApzd2l0Y2ggYmFjayBvbiBmYXVsdHMgb3Igc3lzY2FsbHMuIElmIHRoZSBtYWluIGNv bmNlcm4gaXMgdGhlIGFiaWxpdHkgdG8KcnVuIHN5c2NhbGxzIG9uIGEgcmVtb3RlIG1tLCB3ZSBj YW4gdGhpbmsgYWJvdXQgaG93IHRvIGZpeCB0aGlzLiBJIHNlZQp0d28gd2F5cyB3aGF0IHdlIGNh biBkbyBoZXJlOgoKKiBTcGVjaWZ5IHRoZSBleGFjdCBsaXN0IG9mIHN5c3RlbSBjYWxscyB0aGF0 IGFyZSBhbGxvd2VkLiBUaGUgZmlyc3QKdGhyZWUgY2FuZGlkYXRlcyBhcmUgbW1hcCwgbXVubWFw LCBhbmQgdm1zcGxpY2UuCgoqIEluc3RlYWQgb2YgYWxsb3dpbmcgdXMgdG8gcnVuIHN5c3RlbSBj YWxscywgd2UgY2FuIGltcGxlbWVudCB0aGlzIGluCnRoZSBmb3JtIG9mIGNvbW1hbmRzLiBJbiB0 aGUgY2FzZSBvZiBzYW5kYm94ZXMsIHdlIG5lZWQgdG8gaW1wbGVtZW50Cm9ubHkgdHdvIGNvbW1h bmRzIHRvIGNyZWF0ZSBhbmQgZGVzdHJveSBtZW1vcnkgbWFwcGluZ3MgaW4gYSB0YXJnZXQKYWRk cmVzcyBzcGFjZS4KClRoYW5rcywKQW5kcmVpCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fXwpsaW51eC11bSBtYWlsaW5nIGxpc3QKbGludXgtdW1AbGlzdHMu aW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZv L2xpbnV4LXVtCg==