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 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 7BA90C433B4 for ; Wed, 14 Apr 2021 22:12:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4D3C16115C for ; Wed, 14 Apr 2021 22:12:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231340AbhDNWNN (ORCPT ); Wed, 14 Apr 2021 18:13:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51038 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231190AbhDNWNL (ORCPT ); Wed, 14 Apr 2021 18:13:11 -0400 Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D1F71C061574; Wed, 14 Apr 2021 15:12:49 -0700 (PDT) Received: by mail-pf1-x434.google.com with SMTP id a85so14247002pfa.0; Wed, 14 Apr 2021 15:12:49 -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=EK884MpOCBxdWk5mXA0bTv5YDCU2uHVx/oqS0Cf9P8E=; b=DWMXi7COl7xpo//yBLsqLpvw0K7BJ8rK2lEwFmiJavCqo0Q5eZY+Aun3FbBXr36k4a wx5ZVscDHGFaTJbqbYoC2bJVwhmvIaVZJx7MGLBqwlHeysC4+OZQFV6chn7dETBrgevM XEUgU+fsWu2idieJbhT9wYhwT2k7B8ww9lmNtvP6xJ3CWN/0K/11yc3pV7Smc4mNDhX/ qsceulJT1j6Z0v1jvdMctDUGALow6Tgply7al77wSaBzK7wR/Z0ZMKMozbY9DHJbHgZk FZQ70ONIdBwCgGBub/1GhxT8nQQTdSr4pMv9s+rCSMgpLKB1mXXcuGtBPzJ0nY2j7MVV zrPg== 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=EK884MpOCBxdWk5mXA0bTv5YDCU2uHVx/oqS0Cf9P8E=; b=ocANfmzc6oCsSAUk3Qt+Fs/SMgRYJ7HjOGUpm40dy6edUa5b/xf6tysSlMLOqwW/n8 D3D19B6YJ5Ps+EctHvR4LiHhyN2/W2BK2+thvtsHy1HJ6CIPmrcrNs0lFQNJoXtl9gyR WU9VFLakldE4m/HJbwAvU8eMQ6b6ZwCvwBHW+7grXe8jrj5rrd2GwHrrSs/teA2j0KtP sfE20ZDbJGsr0LdMj3nrOkYqfb9s3QCqVNRAAiwYmojwA3VqNVNNYqNfMiRoEpour6vD I8/viGqUQS4q5OULbXbCT64dMlBFBX7vKq9eu+0yJJXU1tXe+sN2OiBE4/9dGxsKW759 GsgQ== X-Gm-Message-State: AOAM532jmUsGlyfZo9nREdm7cpVIdOgUfYJXEgMVnDpiEOFOR7zjH4I/ fXxS5be18gx7vcc3xnI9PmU= X-Google-Smtp-Source: ABdhPJxYihVqjxbTGniiZF0nmmXc3U5+mhPVSc6vvXqf9jKLNvxLc9QTmVoGku1gUPxZP+sHhIA+Dw== X-Received: by 2002:aa7:91d1:0:b029:1fe:2a02:73b9 with SMTP id z17-20020aa791d10000b02901fe2a0273b9mr247958pfa.2.1618438369166; Wed, 14 Apr 2021 15:12:49 -0700 (PDT) Received: from gmail.com ([2601:600:8500:5f14:d627:c51e:516e:a105]) by smtp.gmail.com with ESMTPSA id mz20sm305131pjb.55.2021.04.14.15.12.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 14 Apr 2021 15:12:48 -0700 (PDT) Date: Wed, 14 Apr 2021 15:10:12 -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 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-kernel@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... We definitely can invent more specific interfaces for each of these problems. Sure, they will handle their use-cases a bit better than this generic one. But do we want to have two very specific interfaces with separate kernel implementations? My previous experiences showed that the kernel community doesn't like interfaces that are specific for only one narrow use-case. So when I was working on process_vm_exec, I was thinking how to make one interfaces that will be good enough for all these use-cases. > > > 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 > 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. We are ready to discuss this sort of interfaces if the community will agree to accept it. Are there any other users except sandboxes that will need something like this? Will the sandbox use-case enough to justify the addition of this interface? > > > Another use-case is CRIU (Checkpoint/Restore in User-space). Several > > process properties can be received only from the process itself. Right > > now, we use a parasite code that is injected into the process. We do > > this with ptrace but it is slow, unsafe, and tricky. > > But this API will only let you run code under the *mm* of the target > process, not fully in the context of a target *task*, right? So you > still won't be able to use this for accessing anything other than > memory? That doesn't seem very generically useful to me. You are right, this will not rid us of the need to run a parasite code. I wrote that it will make a process of injecting a parasite code a bit simpler. > > Also, I don't doubt that anything involving ptrace is kinda tricky, > but it would be nice to have some more detail on what exactly makes > this slow, unsafe and tricky. Are there API additions for ptrace that > would make this work better? I imagine you're thinking of things like > an API for injecting a syscall into the target process without having > to first somehow find an existing SYSCALL instruction in the target > process? You describe the first problem right. We need to find or inject a syscall instruction to a target process. Right now, we need to do these steps to execute a system call: * inject the syscall instruction (PTRACE_PEEKDATA/PTRACE_POKEDATA). * get origin registers * set new registers * get a signal mask. * block signals * resume the process * stop it on the next syscall-exit * get registers * set origin registers * restore a signal mask. One of the CRIU principals is to avoid changing a process state, so if criu is interrupted, processes must be resumed and continue running. The procedure of injecting a system call creates a window when a process is in an inconsistent state, and a disappearing CRIU at such moments will be fatal for the process. We don't think that we can eliminate such windows, but we want to make them smaller. In CRIU, we have a self-healed parasite. The idea is to inject a parasite code with a signal frame that contains the origin process state. The parasite runs in an "RPC daemon mode" and gets commands from criu via a unix socket. If it detects that criu disappeared, it calls rt_sigreturn and resumes the origin process. As for the performance of the ptrace, there are a few reasons why it is slow. First, it is a number of steps what we need to do. Second, it is two synchronious context switches. Even if we will solve the first problem with a new ptrace command, it will be not enough to stop using a parasite in CRIU. > > > process_vm_exec can > > simplify the process of injecting a parasite code and it will allow > > pre-dump memory without stopping processes. The pre-dump here is when we > > enable a memory tracker and dump the memory while a process is continue > > running. On each interaction we dump memory that has been changed from > > the previous iteration. In the final step, we will stop processes and > > dump their full state. Right now the most effective way to dump process > > memory is to create a set of pipes and splice memory into these pipes > > from the parasite code. With process_vm_exec, we will be able to call > > vmsplice directly. It means that we will not need to stop a process to > > inject the parasite code. > > Alternatively you could add splice support to /proc/$pid/mem or add a > syscall similar to process_vm_readv() that splices into a pipe, right? We send patches to introcude process_vm_splice: https://lore.kernel.org/patchwork/cover/871116/ but they were not merged and the main reason was a lack of enough users to justify its addition. From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pg1-x534.google.com ([2607:f8b0:4864:20::534]) by bombadil.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lWnkj-0088Vl-2K for linux-um@lists.infradead.org; Wed, 14 Apr 2021 22:12:54 +0000 Received: by mail-pg1-x534.google.com with SMTP id y32so15435149pga.11 for ; Wed, 14 Apr 2021 15:12:49 -0700 (PDT) Date: Wed, 14 Apr 2021 15:10:12 -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 T24gV2VkLCBBcHIgMTQsIDIwMjEgYXQgMDg6NDY6NDBBTSArMDIwMCwgSmFubiBIb3JuIHdyb3Rl Ogo+IE9uIFdlZCwgQXByIDE0LCAyMDIxIGF0IDc6NTkgQU0gQW5kcmVpIFZhZ2luIDxhdmFnaW5A Z21haWwuY29tPiB3cm90ZToKPiA+IFdlIGFscmVhZHkgaGF2ZSBwcm9jZXNzX3ZtX3JlYWR2IGFu ZCBwcm9jZXNzX3ZtX3dyaXRldiB0byByZWFkIGFuZCB3cml0ZQo+ID4gdG8gYSBwcm9jZXNzIG1l bW9yeSBmYXN0ZXIgdGhhbiB3ZSBjYW4gZG8gdGhpcyB3aXRoIHB0cmFjZS4gQW5kIG5vdyBpdAo+ ID4gaXMgdGltZSBmb3IgcHJvY2Vzc192bV9leGVjIHRoYXQgYWxsb3dzIGV4ZWN1dGluZyBjb2Rl IGluIGFuIGFkZHJlc3MKPiA+IHNwYWNlIG9mIGFub3RoZXIgcHJvY2Vzcy4gV2UgY2FuIGRvIHRo aXMgd2l0aCBwdHJhY2UgYnV0IGl0IGlzIG11Y2gKPiA+IHNsb3dlci4KPiA+Cj4gPiA9IFVzZS1j YXNlcyA9Cj4gCj4gSXQgc2VlbXMgdG8gbWUgbGlrZSB5b3VyIHByb3Bvc2VkIEFQSSBkb2Vzbid0 IHJlYWxseSBmaXQgZWl0aGVyIG9uZSBvZgo+IHRob3NlIHVzZWNhc2VzIHdlbGwuLi4KCldlIGRl ZmluaXRlbHkgY2FuIGludmVudCBtb3JlIHNwZWNpZmljIGludGVyZmFjZXMgZm9yIGVhY2ggb2Yg dGhlc2UKcHJvYmxlbXMuIFN1cmUsIHRoZXkgd2lsbCBoYW5kbGUgdGhlaXIgdXNlLWNhc2VzIGEg Yml0IGJldHRlciB0aGFuIHRoaXMKZ2VuZXJpYyBvbmUuIEJ1dCBkbyB3ZSB3YW50IHRvIGhhdmUg dHdvIHZlcnkgc3BlY2lmaWMgaW50ZXJmYWNlcyB3aXRoCnNlcGFyYXRlIGtlcm5lbCBpbXBsZW1l bnRhdGlvbnM/IE15IHByZXZpb3VzIGV4cGVyaWVuY2VzIHNob3dlZCB0aGF0IHRoZQprZXJuZWwg Y29tbXVuaXR5IGRvZXNuJ3QgbGlrZSBpbnRlcmZhY2VzIHRoYXQgYXJlIHNwZWNpZmljIGZvciBv bmx5IG9uZQpuYXJyb3cgdXNlLWNhc2UuCgpTbyB3aGVuIEkgd2FzIHdvcmtpbmcgb24gcHJvY2Vz c192bV9leGVjLCBJIHdhcyB0aGlua2luZyBob3cgdG8gbWFrZQpvbmUgaW50ZXJmYWNlcyB0aGF0 IHdpbGwgYmUgZ29vZCBlbm91Z2ggZm9yIGFsbCB0aGVzZSB1c2UtY2FzZXMuCgo+IAo+ID4gSGVy ZSBhcmUgdHdvIGtub3duIHVzZS1jYXNlcy4gVGhlIGZpcnN0IG9uZSBpcyDigJxhcHBsaWNhdGlv biBrZXJuZWzigJ0KPiA+IHNhbmRib3hlcyBsaWtlIFVzZXItbW9kZSBMaW51eCBhbmQgZ1Zpc29y LiBJbiB0aGlzIGNhc2UsIHdlIGhhdmUgYQo+ID4gcHJvY2VzcyB0aGF0IHJ1bnMgdGhlIHNhbmRi b3gga2VybmVsIGFuZCBhIHNldCBvZiBzdHViIHByb2Nlc3NlcyB0aGF0Cj4gPiBhcmUgdXNlZCB0 byBtYW5hZ2UgZ3Vlc3QgYWRkcmVzcyBzcGFjZXMuIEd1ZXN0IGNvZGUgaXMgZXhlY3V0ZWQgaW4g dGhlCj4gPiBjb250ZXh0IG9mIHN0dWIgcHJvY2Vzc2VzIGJ1dCBhbGwgc3lzdGVtIGNhbGxzIGFy ZSBpbnRlcmNlcHRlZCBhbmQKPiA+IGhhbmRsZWQgaW4gdGhlIHNhbmRib3gga2VybmVsLiBSaWdo dCBub3csIHRoZXNlIHNvcnQgb2Ygc2FuZGJveGVzIHVzZQo+ID4gUFRSQUNFX1NZU0VNVSB0byB0 cmFwIHN5c3RlbSBjYWxscywgYnV0IHRoZSBwcm9jZXNzX3ZtX2V4ZWMgY2FuCj4gPiBzaWduaWZp Y2FudGx5IHNwZWVkIHRoZW0gdXAuCj4gCj4gSW4gdGhpcyBjYXNlLCBzaW5jZSB5b3UgcmVhbGx5 IG9ubHkgd2FudCBhbiBtbV9zdHJ1Y3QgdG8gcnVuIGNvZGUKPiB1bmRlciwgaXQgc2VlbXMgd2Vp cmQgdG8gY3JlYXRlIGEgd2hvbGUgdGFzayB3aXRoIGl0cyBvd24gUElEIGFuZCBzbwo+IG9uLiBJ dCBzZWVtcyB0byBtZSBsaWtlIHNvbWV0aGluZyBzaW1pbGFyIHRvIHRoZSAvZGV2L2t2bSBBUEkg d291bGQgYmUKPiBtb3JlIGFwcHJvcHJpYXRlIGhlcmU/IEltcGxlbWVudGF0aW9uIG9wdGlvbnMg dGhhdCBJIHNlZSBmb3IgdGhhdAo+IHdvdWxkIGJlOgo+IAo+IDEuIG1tX3N0cnVjdC1iYXNlZDoK PiAgICAgICBhIHNldCBvZiBzeXNjYWxscyB0byBjcmVhdGUgYSBuZXcgbW1fc3RydWN0LAo+ICAg ICAgIGNoYW5nZSBtZW1vcnkgbWFwcGluZ3MgdW5kZXIgdGhhdCBtbV9zdHJ1Y3QsIGFuZCBzd2l0 Y2ggdG8gaXQKPiAyLiBwYWdldGFibGUtbWlycm9yaW5nLWJhc2VkOgo+ICAgICAgIGxpa2UgL2Rl di9rdm0sIGFuIEFQSSB0byBjcmVhdGUgYSBuZXcgcGFnZXRhYmxlLCBtaXJyb3IgcGFydHMgb2YK PiAgICAgICB0aGUgbW1fc3RydWN0J3MgcGFnZXRhYmxlcyBvdmVyIGludG8gaXQgd2l0aCBtb2Rp ZmllZCBwZXJtaXNzaW9ucwo+ICAgICAgIChsaWtlIEtWTV9TRVRfVVNFUl9NRU1PUllfUkVHSU9O KSwKPiAgICAgICBhbmQgcnVuIGNvZGUgdW5kZXIgdGhhdCBjb250ZXh0Lgo+ICAgICAgIHBhZ2Ug ZmF1bHQgaGFuZGxpbmcgd291bGQgZmlyc3QgaGFuZGxlIHRoZSBmYXVsdCBhZ2FpbnN0IG1tLT5w Z2QKPiAgICAgICBhcyBub3JtYWwsIHRoZW4gbWlycm9yIHRoZSBQVEUgb3ZlciBpbnRvIHRoZSBz ZWNvbmRhcnkgcGFnZXRhYmxlcy4KPiAgICAgICBpbnZhbGlkYXRpb24gY291bGQgYmUgaGFuZGxl ZCB3aXRoIE1NVSBub3RpZmllcnMuCgpXZSBhcmUgcmVhZHkgdG8gZGlzY3VzcyB0aGlzIHNvcnQg b2YgaW50ZXJmYWNlcyBpZiB0aGUgY29tbXVuaXR5IHdpbGwKYWdyZWUgdG8gYWNjZXB0IGl0LiBB cmUgdGhlcmUgYW55IG90aGVyIHVzZXJzIGV4Y2VwdCBzYW5kYm94ZXMgdGhhdCB3aWxsCm5lZWQg c29tZXRoaW5nIGxpa2UgdGhpcz8gV2lsbCB0aGUgc2FuZGJveCB1c2UtY2FzZSBlbm91Z2ggdG8g anVzdGlmeQp0aGUgYWRkaXRpb24gb2YgdGhpcyBpbnRlcmZhY2U/Cgo+IAo+ID4gQW5vdGhlciB1 c2UtY2FzZSBpcyBDUklVIChDaGVja3BvaW50L1Jlc3RvcmUgaW4gVXNlci1zcGFjZSkuIFNldmVy YWwKPiA+IHByb2Nlc3MgcHJvcGVydGllcyBjYW4gYmUgcmVjZWl2ZWQgb25seSBmcm9tIHRoZSBw cm9jZXNzIGl0c2VsZi4gUmlnaHQKPiA+IG5vdywgd2UgdXNlIGEgcGFyYXNpdGUgY29kZSB0aGF0 IGlzIGluamVjdGVkIGludG8gdGhlIHByb2Nlc3MuIFdlIGRvCj4gPiB0aGlzIHdpdGggcHRyYWNl IGJ1dCBpdCBpcyBzbG93LCB1bnNhZmUsIGFuZCB0cmlja3kuCj4gCj4gQnV0IHRoaXMgQVBJIHdp bGwgb25seSBsZXQgeW91IHJ1biBjb2RlIHVuZGVyIHRoZSAqbW0qIG9mIHRoZSB0YXJnZXQKPiBw cm9jZXNzLCBub3QgZnVsbHkgaW4gdGhlIGNvbnRleHQgb2YgYSB0YXJnZXQgKnRhc2sqLCByaWdo dD8gU28geW91Cj4gc3RpbGwgd29uJ3QgYmUgYWJsZSB0byB1c2UgdGhpcyBmb3IgYWNjZXNzaW5n IGFueXRoaW5nIG90aGVyIHRoYW4KPiBtZW1vcnk/IFRoYXQgZG9lc24ndCBzZWVtIHZlcnkgZ2Vu ZXJpY2FsbHkgdXNlZnVsIHRvIG1lLgoKWW91IGFyZSByaWdodCwgdGhpcyB3aWxsIG5vdCByaWQg dXMgb2YgdGhlIG5lZWQgdG8gcnVuIGEgcGFyYXNpdGUgY29kZS4KSSB3cm90ZSB0aGF0IGl0IHdp bGwgbWFrZSBhIHByb2Nlc3Mgb2YgaW5qZWN0aW5nIGEgcGFyYXNpdGUgY29kZSBhIGJpdApzaW1w bGVyLgoKPiAKPiBBbHNvLCBJIGRvbid0IGRvdWJ0IHRoYXQgYW55dGhpbmcgaW52b2x2aW5nIHB0 cmFjZSBpcyBraW5kYSB0cmlja3ksCj4gYnV0IGl0IHdvdWxkIGJlIG5pY2UgdG8gaGF2ZSBzb21l IG1vcmUgZGV0YWlsIG9uIHdoYXQgZXhhY3RseSBtYWtlcwo+IHRoaXMgc2xvdywgdW5zYWZlIGFu ZCB0cmlja3kuIEFyZSB0aGVyZSBBUEkgYWRkaXRpb25zIGZvciBwdHJhY2UgdGhhdAo+IHdvdWxk IG1ha2UgdGhpcyB3b3JrIGJldHRlcj8gSSBpbWFnaW5lIHlvdSdyZSB0aGlua2luZyBvZiB0aGlu Z3MgbGlrZQo+IGFuIEFQSSBmb3IgaW5qZWN0aW5nIGEgc3lzY2FsbCBpbnRvIHRoZSB0YXJnZXQg cHJvY2VzcyB3aXRob3V0IGhhdmluZwo+IHRvIGZpcnN0IHNvbWVob3cgZmluZCBhbiBleGlzdGlu ZyBTWVNDQUxMIGluc3RydWN0aW9uIGluIHRoZSB0YXJnZXQKPiBwcm9jZXNzPwoKCllvdSBkZXNj cmliZSB0aGUgZmlyc3QgcHJvYmxlbSByaWdodC4gV2UgbmVlZCB0byBmaW5kIG9yIGluamVjdCBh CnN5c2NhbGwgaW5zdHJ1Y3Rpb24gdG8gYSB0YXJnZXQgcHJvY2Vzcy4KUmlnaHQgbm93LCB3ZSBu ZWVkIHRvIGRvIHRoZXNlIHN0ZXBzIHRvIGV4ZWN1dGUgYSBzeXN0ZW0gY2FsbDoKCiogaW5qZWN0 IHRoZSBzeXNjYWxsIGluc3RydWN0aW9uIChQVFJBQ0VfUEVFS0RBVEEvUFRSQUNFX1BPS0VEQVRB KS4KKiBnZXQgb3JpZ2luIHJlZ2lzdGVycwoqIHNldCBuZXcgcmVnaXN0ZXJzCiogZ2V0IGEgc2ln bmFsIG1hc2suCiogYmxvY2sgc2lnbmFscwoqIHJlc3VtZSB0aGUgcHJvY2VzcwoqIHN0b3AgaXQg b24gdGhlIG5leHQgc3lzY2FsbC1leGl0CiogZ2V0IHJlZ2lzdGVycwoqIHNldCBvcmlnaW4gcmVn aXN0ZXJzCiogcmVzdG9yZSBhIHNpZ25hbCBtYXNrLgoKT25lIG9mIHRoZSBDUklVIHByaW5jaXBh bHMgaXMgdG8gYXZvaWQgY2hhbmdpbmcgYSBwcm9jZXNzIHN0YXRlLCBzbyBpZgpjcml1IGlzIGlu dGVycnVwdGVkLCBwcm9jZXNzZXMgbXVzdCBiZSByZXN1bWVkIGFuZCBjb250aW51ZSBydW5uaW5n LiBUaGUKcHJvY2VkdXJlIG9mIGluamVjdGluZyBhIHN5c3RlbSBjYWxsIGNyZWF0ZXMgYSB3aW5k b3cgd2hlbiBhIHByb2Nlc3MgaXMKaW4gYW4gaW5jb25zaXN0ZW50IHN0YXRlLCBhbmQgYSBkaXNh cHBlYXJpbmcgQ1JJVSBhdCBzdWNoIG1vbWVudHMgd2lsbApiZSBmYXRhbCBmb3IgdGhlIHByb2Nl c3MuIFdlIGRvbid0IHRoaW5rIHRoYXQgd2UgY2FuIGVsaW1pbmF0ZSBzdWNoCndpbmRvd3MsIGJ1 dCB3ZSB3YW50IHRvIG1ha2UgdGhlbSBzbWFsbGVyLgoKSW4gQ1JJVSwgd2UgaGF2ZSBhIHNlbGYt aGVhbGVkIHBhcmFzaXRlLiBUaGUgaWRlYSBpcyB0byBpbmplY3QgYQpwYXJhc2l0ZSBjb2RlIHdp dGggYSBzaWduYWwgZnJhbWUgdGhhdCBjb250YWlucyB0aGUgb3JpZ2luIHByb2Nlc3MKc3RhdGUu IFRoZSBwYXJhc2l0ZSBydW5zIGluIGFuICJSUEMgZGFlbW9uIG1vZGUiIGFuZCBnZXRzIGNvbW1h bmRzIGZyb20KY3JpdSB2aWEgYSB1bml4IHNvY2tldC4gSWYgaXQgZGV0ZWN0cyB0aGF0IGNyaXUg ZGlzYXBwZWFyZWQsIGl0IGNhbGxzCnJ0X3NpZ3JldHVybiBhbmQgcmVzdW1lcyB0aGUgb3JpZ2lu IHByb2Nlc3MuCgpBcyBmb3IgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBwdHJhY2UsIHRoZXJlIGFy ZSBhIGZldyByZWFzb25zIHdoeSBpdCBpcwpzbG93LiBGaXJzdCwgaXQgaXMgYSBudW1iZXIgb2Yg c3RlcHMgd2hhdCB3ZSBuZWVkIHRvIGRvLiBTZWNvbmQsIGl0IGlzCnR3byBzeW5jaHJvbmlvdXMg Y29udGV4dCBzd2l0Y2hlcy4gRXZlbiBpZiB3ZSB3aWxsIHNvbHZlIHRoZSBmaXJzdApwcm9ibGVt IHdpdGggYSBuZXcgcHRyYWNlIGNvbW1hbmQsIGl0IHdpbGwgYmUgbm90IGVub3VnaCB0byBzdG9w IHVzaW5nIGEKcGFyYXNpdGUgaW4gQ1JJVS4KCj4gCj4gPiBwcm9jZXNzX3ZtX2V4ZWMgY2FuCj4g PiBzaW1wbGlmeSB0aGUgcHJvY2VzcyBvZiBpbmplY3RpbmcgYSBwYXJhc2l0ZSBjb2RlIGFuZCBp dCB3aWxsIGFsbG93Cj4gPiBwcmUtZHVtcCBtZW1vcnkgd2l0aG91dCBzdG9wcGluZyBwcm9jZXNz ZXMuIFRoZSBwcmUtZHVtcCBoZXJlIGlzIHdoZW4gd2UKPiA+IGVuYWJsZSBhIG1lbW9yeSB0cmFj a2VyIGFuZCBkdW1wIHRoZSBtZW1vcnkgd2hpbGUgYSBwcm9jZXNzIGlzIGNvbnRpbnVlCj4gPiBy dW5uaW5nLiBPbiBlYWNoIGludGVyYWN0aW9uIHdlIGR1bXAgbWVtb3J5IHRoYXQgaGFzIGJlZW4g Y2hhbmdlZCBmcm9tCj4gPiB0aGUgcHJldmlvdXMgaXRlcmF0aW9uLiBJbiB0aGUgZmluYWwgc3Rl cCwgd2Ugd2lsbCBzdG9wIHByb2Nlc3NlcyBhbmQKPiA+IGR1bXAgdGhlaXIgZnVsbCBzdGF0ZS4g UmlnaHQgbm93IHRoZSBtb3N0IGVmZmVjdGl2ZSB3YXkgdG8gZHVtcCBwcm9jZXNzCj4gPiBtZW1v cnkgaXMgdG8gY3JlYXRlIGEgc2V0IG9mIHBpcGVzIGFuZCBzcGxpY2UgbWVtb3J5IGludG8gdGhl c2UgcGlwZXMKPiA+IGZyb20gdGhlIHBhcmFzaXRlIGNvZGUuIFdpdGggcHJvY2Vzc192bV9leGVj LCB3ZSB3aWxsIGJlIGFibGUgdG8gY2FsbAo+ID4gdm1zcGxpY2UgZGlyZWN0bHkuIEl0IG1lYW5z IHRoYXQgd2Ugd2lsbCBub3QgbmVlZCB0byBzdG9wIGEgcHJvY2VzcyB0bwo+ID4gaW5qZWN0IHRo ZSBwYXJhc2l0ZSBjb2RlLgo+IAo+IEFsdGVybmF0aXZlbHkgeW91IGNvdWxkIGFkZCBzcGxpY2Ug c3VwcG9ydCB0byAvcHJvYy8kcGlkL21lbSBvciBhZGQgYQo+IHN5c2NhbGwgc2ltaWxhciB0byBw cm9jZXNzX3ZtX3JlYWR2KCkgdGhhdCBzcGxpY2VzIGludG8gYSBwaXBlLCByaWdodD8KCldlIHNl bmQgcGF0Y2hlcyB0byBpbnRyb2N1ZGUgcHJvY2Vzc192bV9zcGxpY2U6Cmh0dHBzOi8vbG9yZS5r ZXJuZWwub3JnL3BhdGNod29yay9jb3Zlci84NzExMTYvCgpidXQgdGhleSB3ZXJlIG5vdCBtZXJn ZWQgYW5kIHRoZSBtYWluIHJlYXNvbiB3YXMgYSBsYWNrIG9mIGVub3VnaCB1c2Vycwp0byBqdXN0 aWZ5IGl0cyBhZGRpdGlvbi4KCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fCmxpbnV4LXVtIG1haWxpbmcgbGlzdApsaW51eC11bUBsaXN0cy5pbmZyYWRlYWQu b3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtdW0K