From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vincenzo Frascino Subject: Re: [PATCH v6 1/2] arm64: Define Documentation/arm64/tagged-address-abi.rst Date: Tue, 30 Jul 2019 14:25:17 +0100 Message-ID: References: <20190725135044.24381-1-vincenzo.frascino@arm.com> <20190725135044.24381-2-vincenzo.frascino@arm.com> <52fa2cfc-f7a6-af6f-0dc2-f9ea0e41ac3c@arm.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Return-path: In-Reply-To: <52fa2cfc-f7a6-af6f-0dc2-f9ea0e41ac3c@arm.com> Content-Language: en-US Sender: linux-kernel-owner@vger.kernel.org To: Kevin Brodsky , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Szabolcs Nagy , Catalin Marinas , Will Deacon , Andrey Konovalov List-Id: linux-arch.vger.kernel.org Hi Kevin, On 7/30/19 11:32 AM, Kevin Brodsky wrote: > Some more comments. Mostly minor wording issues, except the prctl() exclusion at > the end. > > On 25/07/2019 14:50, Vincenzo Frascino wrote: >> On arm64 the TCR_EL1.TBI0 bit has been always enabled hence >> the userspace (EL0) is allowed to set a non-zero value in the >> top byte but the resulting pointers are not allowed at the >> user-kernel syscall ABI boundary. >> >> With the relaxed ABI proposed through this document, it is now possible >> to pass tagged pointers to the syscalls, when these pointers are in >> memory ranges obtained by an anonymous (MAP_ANONYMOUS) mmap(). >> >> This change in the ABI requires a mechanism to requires the userspace >> to opt-in to such an option. >> >> Specify and document the way in which sysctl and prctl() can be used >> in combination to allow the userspace to opt-in this feature. >> >> Cc: Catalin Marinas >> Cc: Will Deacon >> CC: Andrey Konovalov >> Signed-off-by: Vincenzo Frascino >> Acked-by: Szabolcs Nagy >> --- >>   Documentation/arm64/tagged-address-abi.rst | 148 +++++++++++++++++++++ >>   1 file changed, 148 insertions(+) >>   create mode 100644 Documentation/arm64/tagged-address-abi.rst >> >> diff --git a/Documentation/arm64/tagged-address-abi.rst >> b/Documentation/arm64/tagged-address-abi.rst >> new file mode 100644 >> index 000000000000..a8ecb991de82 >> --- /dev/null >> +++ b/Documentation/arm64/tagged-address-abi.rst >> @@ -0,0 +1,148 @@ >> +======================== >> +ARM64 TAGGED ADDRESS ABI >> +======================== >> + >> +Author: Vincenzo Frascino >> + >> +Date: 25 July 2019 >> + >> +This document describes the usage and semantics of the Tagged Address >> +ABI on arm64. >> + >> +1. Introduction >> +--------------- >> + >> +On arm64 the TCR_EL1.TBI0 bit has always been enabled on the kernel, hence >> +the userspace (EL0) is entitled to perform a user memory access through a >> +64-bit pointer with a non-zero top byte but the resulting pointers are not >> +allowed at the user-kernel syscall ABI boundary. >> + >> +This document describes a relaxation of the ABI that makes it possible to >> +to pass tagged pointers to the syscalls, when these pointers are in memory > > One too many "to" (at the end the previous line). > Yep will fix in v7. >> +ranges obtained as described in section 2. >> + >> +Since it is not desirable to relax the ABI to allow tagged user addresses >> +into the kernel indiscriminately, arm64 provides a new sysctl interface >> +(/proc/sys/abi/tagged_addr) that is used to prevent the applications from >> +enabling the relaxed ABI and a new prctl() interface that can be used to >> +enable or disable the relaxed ABI. >> +A detailed description of the newly introduced mechanisms will be provided >> +in section 2. >> + >> +2. ARM64 Tagged Address ABI >> +--------------------------- >> + >> +From the kernel syscall interface perspective, we define, for the purposes >> +of this document, a "valid tagged pointer" as a pointer that either has a >> +zero value set in the top byte or has a non-zero value, is in memory ranges >> +privately owned by a userspace process and is obtained in one of the >> +following ways: >> +- mmap() done by the process itself, where either: >> + >> +  - flags have **MAP_PRIVATE** and **MAP_ANONYMOUS** >> +  - flags have **MAP_PRIVATE** and the file descriptor refers to a regular >> +    file or **/dev/zero** >> + >> +- brk() system call done by the process itself (i.e. the heap area between >> +  the initial location of the program break at process creation and its >> +  current location). >> +- any memory mapped by the kernel in the process's address space during >> +  creation and with the same restrictions as for mmap() (e.g. data, bss, >> +  stack). >> + >> +The ARM64 Tagged Address ABI is an opt-in feature, and an application can >> +control it using the following: >> + >> +- **/proc/sys/abi/tagged_addr**: a new sysctl interface that can be used to >> +  prevent the applications from enabling the access to the relaxed ABI. >> +  The sysctl supports the following configuration options: >> + >> +  - **0**: Disable the access to the ARM64 Tagged Address ABI for all >> +    the applications. >> +  - **1** (Default): Enable the access to the ARM64 Tagged Address ABI for >> +    all the applications. >> + >> +   If the access to the ARM64 Tagged Address ABI is disabled at a certain >> +   point in time, all the applications that were using tagging before this >> +   event occurs, will continue to use tagging. > > "tagging" may be misinterpreted here. I would be more explicit by saying that > the tagged address ABI remains enabled in processes that opted in before the > access got disabled. > Assuming that ARM64 Tagged Address ABI gives access to "tagging" and since it is what this document is talking about, I do not see how it can be misinterpreted ;) >> +- **prctl()s**: >> + >> +  - **PR_SET_TAGGED_ADDR_CTRL**: Invoked by a process, can be used to enable or >> +    disable its access to the ARM64 Tagged Address ABI. > > I still find the wording confusing, because "access to the ABI" is not used > consistently. The "tagged_addr" sysctl enables *access to the ABI*, that's fine. > However, PR_SET_TAGGED_ADDR_CTRL enables *the ABI itself* (which is only > possible if access to the ABI is enabled). > As it stands, it enables or disables the ABI itself when used with PR_TAGGED_ADDR_ENABLE, or can enable other things in future. IMHO the only thing that these features have in common is the access to the ABI which is granted by this prctl(). >> + >> +    The (unsigned int) arg2 argument is a bit mask describing the control mode >> +    used: >> + >> +    - **PR_TAGGED_ADDR_ENABLE**: Enable ARM64 Tagged Address ABI. >> + >> +    The prctl(PR_SET_TAGGED_ADDR_CTRL, ...) will return -EINVAL if the ARM64 >> +    Tagged Address ABI is not available. > > For clarity, it would be good to mention that one possible reason for the ABI > not to be available is tagged_addr == 0. > The logical implication is already quite clear tagged_addr == 0 (Disabled) => Tagged Address ABI not available => return -EINVAL. I do not see the need to repeat the concept twice. >> + >> +    The arguments arg3, arg4, and arg5 are ignored. >> +  - **PR_GET_TAGGED_ADDR_CTRL**: can be used to check the status of the Tagged >> +    Address ABI. >> + >> +    The arguments arg2, arg3, arg4, and arg5 are ignored. >> + >> +The ABI properties set by the mechanisms described above are inherited by >> threads >> +of the same application and fork()'ed children but cleared by execve(). >> + >> +When a process has successfully opted into the new ABI by invoking >> +PR_SET_TAGGED_ADDR_CTRL prctl(), this guarantees the following behaviours: >> + >> + - Every currently available syscall, except the cases mentioned in section >> 3, can >> +   accept any valid tagged pointer. The same rule is applicable to any syscall >> +   introduced in the future. > > I thought Catalin wanted to drop this guarantee? > The guarantee is changed and explicitly includes the syscalls that can be added in the future. IMHO since we are defining an ABI, we cannot leave that topic in an uncharted territory, we need to address it. >> + - If a non valid tagged pointer is passed to a syscall then the behaviour >> +   is undefined. >> + - Every valid tagged pointer is expected to work as an untagged one. >> + - The kernel preserves any valid tagged pointer and returns it to the >> +   userspace unchanged (i.e. on syscall return) in all the cases except the >> +   ones documented in the "Preserving tags" section of tagged-pointers.txt. >> + >> +A definition of the meaning of tagged pointers on arm64 can be found in: >> +Documentation/arm64/tagged-pointers.txt. >> + >> +3. ARM64 Tagged Address ABI Exceptions >> +-------------------------------------- >> + >> +The behaviours described in section 2, with particular reference to the >> +acceptance by the syscalls of any valid tagged pointer are not applicable >> +to the following cases: >> + >> + - mmap() addr parameter. >> + - mremap() new_address parameter. >> + - prctl(PR_SET_MM, PR_SET_MM_MAP, ...) struct prctl_mm_map fields. >> + - prctl(PR_SET_MM, PR_SET_MM_MAP_SIZE, ...) struct prctl_mm_map fields. > > All the PR_SET_MM options that specify pointers (PR_SET_MM_START_CODE, > PR_SET_MM_END_CODE, ...) should be excluded as well. AFAICT (but don't take my > word for it), that's all of them except PR_SET_MM_EXE_FILE. Conversely, > PR_SET_MM_MAP_SIZE should not be excluded (it does not pass a prctl_mm_map > struct, and the pointer to unsigned int can be tagged). > Agreed, I clearly misread the prctl() man page here. Fill fix in v7. PR_SET_MM_MAP_SIZE _returns_ struct prctl_mm_map, does not take it as a parameter. Vincenzo > Kevin > >> + >> +Any attempt to use non-zero tagged pointers will lead to undefined behaviour. >> + >> +4. Example of correct usage >> +--------------------------- >> +.. code-block:: c >> + >> +   void main(void) >> +   { >> +           static int tbi_enabled = 0; >> +           unsigned long tag = 0; >> + >> +           char *ptr = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, >> +                            MAP_ANONYMOUS, -1, 0); >> + >> +           if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, >> +                     0, 0, 0) == 0) >> +                   tbi_enabled = 1; >> + >> +           if (ptr == (void *)-1) /* MAP_FAILED */ >> +                   return -1; >> + >> +           if (tbi_enabled) >> +                   tag = rand() & 0xff; >> + >> +           ptr = (char *)((unsigned long)ptr | (tag << TAG_SHIFT)); >> + >> +           *ptr = 'a'; >> + >> +           ... >> +   } >> + > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- Regards, Vincenzo 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=-8.3 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=ham 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 29C0DC31E40 for ; Tue, 30 Jul 2019 13:24:13 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id F0FDC2089E for ; Tue, 30 Jul 2019 13:24:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="WVQAj4Us" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F0FDC2089E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date: Message-ID:From:References:To:Subject:Reply-To:Content-ID:Content-Description :Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=yhsLQu0hYLaQEr1k3WUcxLD5Vs8uq1gpw8F16Yx1RDg=; b=WVQAj4UsBXkirE CkmvguxmMXCHt0VCiZVJ75HcKx+l74V36/mc11NH+k+YF3HbtCMI+kR38uyeCz8SX1VTZvAcQ6gym Zc6FJchmPHG2Zd5EhacT3GIF6Q1tGid9QRpo9oatZ2/jO/chXI+QiCH/2bMubw5+P15dgXL1dZete UcEheJTUMG2Uj22aBoIU/VFwEIUSnG5Rz3aHy8LGqzfOOvwnUX3g/VimBHX3uX4BDivMre9KNNo5R lWSKPP2JQ5Kd0kF8R6v+8uiRlZepUutWPM2i6XKKKewctf7n7K//fDW8AEPom5Jr1HijDCMDFiona 07+B578kQ0BBQeLKeHNg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1hsS6u-0003jQ-Ju; Tue, 30 Jul 2019 13:24:12 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1hsS6r-0003hg-Ku for linux-arm-kernel@lists.infradead.org; Tue, 30 Jul 2019 13:24:11 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 811B828; Tue, 30 Jul 2019 06:24:07 -0700 (PDT) Received: from [10.37.12.80] (unknown [10.37.12.80]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9E97B3F694; Tue, 30 Jul 2019 06:24:05 -0700 (PDT) Subject: Re: [PATCH v6 1/2] arm64: Define Documentation/arm64/tagged-address-abi.rst To: Kevin Brodsky , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org References: <20190725135044.24381-1-vincenzo.frascino@arm.com> <20190725135044.24381-2-vincenzo.frascino@arm.com> <52fa2cfc-f7a6-af6f-0dc2-f9ea0e41ac3c@arm.com> From: Vincenzo Frascino Message-ID: Date: Tue, 30 Jul 2019 14:25:17 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.2 MIME-Version: 1.0 In-Reply-To: <52fa2cfc-f7a6-af6f-0dc2-f9ea0e41ac3c@arm.com> Content-Language: en-US X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190730_062409_775685_4AA8E96F X-CRM114-Status: GOOD ( 37.73 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Szabolcs Nagy , Catalin Marinas , Will Deacon , Andrey Konovalov Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org SGkgS2V2aW4sCgpPbiA3LzMwLzE5IDExOjMyIEFNLCBLZXZpbiBCcm9kc2t5IHdyb3RlOgo+IFNv bWUgbW9yZSBjb21tZW50cy4gTW9zdGx5IG1pbm9yIHdvcmRpbmcgaXNzdWVzLCBleGNlcHQgdGhl IHByY3RsKCkgZXhjbHVzaW9uIGF0Cj4gdGhlIGVuZC4KPiAKPiBPbiAyNS8wNy8yMDE5IDE0OjUw LCBWaW5jZW56byBGcmFzY2lubyB3cm90ZToKPj4gT24gYXJtNjQgdGhlIFRDUl9FTDEuVEJJMCBi aXQgaGFzIGJlZW4gYWx3YXlzIGVuYWJsZWQgaGVuY2UKPj4gdGhlIHVzZXJzcGFjZSAoRUwwKSBp cyBhbGxvd2VkIHRvIHNldCBhIG5vbi16ZXJvIHZhbHVlIGluIHRoZQo+PiB0b3AgYnl0ZSBidXQg dGhlIHJlc3VsdGluZyBwb2ludGVycyBhcmUgbm90IGFsbG93ZWQgYXQgdGhlCj4+IHVzZXIta2Vy bmVsIHN5c2NhbGwgQUJJIGJvdW5kYXJ5Lgo+Pgo+PiBXaXRoIHRoZSByZWxheGVkIEFCSSBwcm9w b3NlZCB0aHJvdWdoIHRoaXMgZG9jdW1lbnQsIGl0IGlzIG5vdyBwb3NzaWJsZQo+PiB0byBwYXNz IHRhZ2dlZCBwb2ludGVycyB0byB0aGUgc3lzY2FsbHMsIHdoZW4gdGhlc2UgcG9pbnRlcnMgYXJl IGluCj4+IG1lbW9yeSByYW5nZXMgb2J0YWluZWQgYnkgYW4gYW5vbnltb3VzIChNQVBfQU5PTllN T1VTKSBtbWFwKCkuCj4+Cj4+IFRoaXMgY2hhbmdlIGluIHRoZSBBQkkgcmVxdWlyZXMgYSBtZWNo YW5pc20gdG8gcmVxdWlyZXMgdGhlIHVzZXJzcGFjZQo+PiB0byBvcHQtaW4gdG8gc3VjaCBhbiBv cHRpb24uCj4+Cj4+IFNwZWNpZnkgYW5kIGRvY3VtZW50IHRoZSB3YXkgaW4gd2hpY2ggc3lzY3Rs IGFuZCBwcmN0bCgpIGNhbiBiZSB1c2VkCj4+IGluIGNvbWJpbmF0aW9uIHRvIGFsbG93IHRoZSB1 c2Vyc3BhY2UgdG8gb3B0LWluIHRoaXMgZmVhdHVyZS4KPj4KPj4gQ2M6IENhdGFsaW4gTWFyaW5h cyA8Y2F0YWxpbi5tYXJpbmFzQGFybS5jb20+Cj4+IENjOiBXaWxsIERlYWNvbiA8d2lsbC5kZWFj b25AYXJtLmNvbT4KPj4gQ0M6IEFuZHJleSBLb25vdmFsb3YgPGFuZHJleWtudmxAZ29vZ2xlLmNv bT4KPj4gU2lnbmVkLW9mZi1ieTogVmluY2Vuem8gRnJhc2Npbm8gPHZpbmNlbnpvLmZyYXNjaW5v QGFybS5jb20+Cj4+IEFja2VkLWJ5OiBTemFib2xjcyBOYWd5IDxzemFib2xjcy5uYWd5QGFybS5j b20+Cj4+IC0tLQo+PiDCoCBEb2N1bWVudGF0aW9uL2FybTY0L3RhZ2dlZC1hZGRyZXNzLWFiaS5y c3QgfCAxNDggKysrKysrKysrKysrKysrKysrKysrCj4+IMKgIDEgZmlsZSBjaGFuZ2VkLCAxNDgg aW5zZXJ0aW9ucygrKQo+PiDCoCBjcmVhdGUgbW9kZSAxMDA2NDQgRG9jdW1lbnRhdGlvbi9hcm02 NC90YWdnZWQtYWRkcmVzcy1hYmkucnN0Cj4+Cj4+IGRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9u L2FybTY0L3RhZ2dlZC1hZGRyZXNzLWFiaS5yc3QKPj4gYi9Eb2N1bWVudGF0aW9uL2FybTY0L3Rh Z2dlZC1hZGRyZXNzLWFiaS5yc3QKPj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPj4gaW5kZXggMDAw MDAwMDAwMDAwLi5hOGVjYjk5MWRlODIKPj4gLS0tIC9kZXYvbnVsbAo+PiArKysgYi9Eb2N1bWVu dGF0aW9uL2FybTY0L3RhZ2dlZC1hZGRyZXNzLWFiaS5yc3QKPj4gQEAgLTAsMCArMSwxNDggQEAK Pj4gKz09PT09PT09PT09PT09PT09PT09PT09PQo+PiArQVJNNjQgVEFHR0VEIEFERFJFU1MgQUJJ Cj4+ICs9PT09PT09PT09PT09PT09PT09PT09PT0KPj4gKwo+PiArQXV0aG9yOiBWaW5jZW56byBG cmFzY2lubyA8dmluY2Vuem8uZnJhc2Npbm9AYXJtLmNvbT4KPj4gKwo+PiArRGF0ZTogMjUgSnVs eSAyMDE5Cj4+ICsKPj4gK1RoaXMgZG9jdW1lbnQgZGVzY3JpYmVzIHRoZSB1c2FnZSBhbmQgc2Vt YW50aWNzIG9mIHRoZSBUYWdnZWQgQWRkcmVzcwo+PiArQUJJIG9uIGFybTY0Lgo+PiArCj4+ICsx LiBJbnRyb2R1Y3Rpb24KPj4gKy0tLS0tLS0tLS0tLS0tLQo+PiArCj4+ICtPbiBhcm02NCB0aGUg VENSX0VMMS5UQkkwIGJpdCBoYXMgYWx3YXlzIGJlZW4gZW5hYmxlZCBvbiB0aGUga2VybmVsLCBo ZW5jZQo+PiArdGhlIHVzZXJzcGFjZSAoRUwwKSBpcyBlbnRpdGxlZCB0byBwZXJmb3JtIGEgdXNl ciBtZW1vcnkgYWNjZXNzIHRocm91Z2ggYQo+PiArNjQtYml0IHBvaW50ZXIgd2l0aCBhIG5vbi16 ZXJvIHRvcCBieXRlIGJ1dCB0aGUgcmVzdWx0aW5nIHBvaW50ZXJzIGFyZSBub3QKPj4gK2FsbG93 ZWQgYXQgdGhlIHVzZXIta2VybmVsIHN5c2NhbGwgQUJJIGJvdW5kYXJ5Lgo+PiArCj4+ICtUaGlz IGRvY3VtZW50IGRlc2NyaWJlcyBhIHJlbGF4YXRpb24gb2YgdGhlIEFCSSB0aGF0IG1ha2VzIGl0 IHBvc3NpYmxlIHRvCj4+ICt0byBwYXNzIHRhZ2dlZCBwb2ludGVycyB0byB0aGUgc3lzY2FsbHMs IHdoZW4gdGhlc2UgcG9pbnRlcnMgYXJlIGluIG1lbW9yeQo+IAo+IE9uZSB0b28gbWFueSAidG8i IChhdCB0aGUgZW5kIHRoZSBwcmV2aW91cyBsaW5lKS4KPiAKClllcCB3aWxsIGZpeCBpbiB2Ny4K Cj4+ICtyYW5nZXMgb2J0YWluZWQgYXMgZGVzY3JpYmVkIGluIHNlY3Rpb24gMi4KPj4gKwo+PiAr U2luY2UgaXQgaXMgbm90IGRlc2lyYWJsZSB0byByZWxheCB0aGUgQUJJIHRvIGFsbG93IHRhZ2dl ZCB1c2VyIGFkZHJlc3Nlcwo+PiAraW50byB0aGUga2VybmVsIGluZGlzY3JpbWluYXRlbHksIGFy bTY0IHByb3ZpZGVzIGEgbmV3IHN5c2N0bCBpbnRlcmZhY2UKPj4gKygvcHJvYy9zeXMvYWJpL3Rh Z2dlZF9hZGRyKSB0aGF0IGlzIHVzZWQgdG8gcHJldmVudCB0aGUgYXBwbGljYXRpb25zIGZyb20K Pj4gK2VuYWJsaW5nIHRoZSByZWxheGVkIEFCSSBhbmQgYSBuZXcgcHJjdGwoKSBpbnRlcmZhY2Ug dGhhdCBjYW4gYmUgdXNlZCB0bwo+PiArZW5hYmxlIG9yIGRpc2FibGUgdGhlIHJlbGF4ZWQgQUJJ Lgo+PiArQSBkZXRhaWxlZCBkZXNjcmlwdGlvbiBvZiB0aGUgbmV3bHkgaW50cm9kdWNlZCBtZWNo YW5pc21zIHdpbGwgYmUgcHJvdmlkZWQKPj4gK2luIHNlY3Rpb24gMi4KPj4gKwo+PiArMi4gQVJN NjQgVGFnZ2VkIEFkZHJlc3MgQUJJCj4+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPj4g Kwo+PiArRnJvbSB0aGUga2VybmVsIHN5c2NhbGwgaW50ZXJmYWNlIHBlcnNwZWN0aXZlLCB3ZSBk ZWZpbmUsIGZvciB0aGUgcHVycG9zZXMKPj4gK29mIHRoaXMgZG9jdW1lbnQsIGEgInZhbGlkIHRh Z2dlZCBwb2ludGVyIiBhcyBhIHBvaW50ZXIgdGhhdCBlaXRoZXIgaGFzIGEKPj4gK3plcm8gdmFs dWUgc2V0IGluIHRoZSB0b3AgYnl0ZSBvciBoYXMgYSBub24temVybyB2YWx1ZSwgaXMgaW4gbWVt b3J5IHJhbmdlcwo+PiArcHJpdmF0ZWx5IG93bmVkIGJ5IGEgdXNlcnNwYWNlIHByb2Nlc3MgYW5k IGlzIG9idGFpbmVkIGluIG9uZSBvZiB0aGUKPj4gK2ZvbGxvd2luZyB3YXlzOgo+PiArLSBtbWFw KCkgZG9uZSBieSB0aGUgcHJvY2VzcyBpdHNlbGYsIHdoZXJlIGVpdGhlcjoKPj4gKwo+PiArwqAg LSBmbGFncyBoYXZlICoqTUFQX1BSSVZBVEUqKiBhbmQgKipNQVBfQU5PTllNT1VTKioKPj4gK8Kg IC0gZmxhZ3MgaGF2ZSAqKk1BUF9QUklWQVRFKiogYW5kIHRoZSBmaWxlIGRlc2NyaXB0b3IgcmVm ZXJzIHRvIGEgcmVndWxhcgo+PiArwqDCoMKgIGZpbGUgb3IgKiovZGV2L3plcm8qKgo+PiArCj4+ ICstIGJyaygpIHN5c3RlbSBjYWxsIGRvbmUgYnkgdGhlIHByb2Nlc3MgaXRzZWxmIChpLmUuIHRo ZSBoZWFwIGFyZWEgYmV0d2Vlbgo+PiArwqAgdGhlIGluaXRpYWwgbG9jYXRpb24gb2YgdGhlIHBy b2dyYW0gYnJlYWsgYXQgcHJvY2VzcyBjcmVhdGlvbiBhbmQgaXRzCj4+ICvCoCBjdXJyZW50IGxv Y2F0aW9uKS4KPj4gKy0gYW55IG1lbW9yeSBtYXBwZWQgYnkgdGhlIGtlcm5lbCBpbiB0aGUgcHJv Y2VzcydzIGFkZHJlc3Mgc3BhY2UgZHVyaW5nCj4+ICvCoCBjcmVhdGlvbiBhbmQgd2l0aCB0aGUg c2FtZSByZXN0cmljdGlvbnMgYXMgZm9yIG1tYXAoKSAoZS5nLiBkYXRhLCBic3MsCj4+ICvCoCBz dGFjaykuCj4+ICsKPj4gK1RoZSBBUk02NCBUYWdnZWQgQWRkcmVzcyBBQkkgaXMgYW4gb3B0LWlu IGZlYXR1cmUsIGFuZCBhbiBhcHBsaWNhdGlvbiBjYW4KPj4gK2NvbnRyb2wgaXQgdXNpbmcgdGhl IGZvbGxvd2luZzoKPj4gKwo+PiArLSAqKi9wcm9jL3N5cy9hYmkvdGFnZ2VkX2FkZHIqKjogYSBu ZXcgc3lzY3RsIGludGVyZmFjZSB0aGF0IGNhbiBiZSB1c2VkIHRvCj4+ICvCoCBwcmV2ZW50IHRo ZSBhcHBsaWNhdGlvbnMgZnJvbSBlbmFibGluZyB0aGUgYWNjZXNzIHRvIHRoZSByZWxheGVkIEFC SS4KPj4gK8KgIFRoZSBzeXNjdGwgc3VwcG9ydHMgdGhlIGZvbGxvd2luZyBjb25maWd1cmF0aW9u IG9wdGlvbnM6Cj4+ICsKPj4gK8KgIC0gKiowKio6IERpc2FibGUgdGhlIGFjY2VzcyB0byB0aGUg QVJNNjQgVGFnZ2VkIEFkZHJlc3MgQUJJIGZvciBhbGwKPj4gK8KgwqDCoCB0aGUgYXBwbGljYXRp b25zLgo+PiArwqAgLSAqKjEqKiAoRGVmYXVsdCk6IEVuYWJsZSB0aGUgYWNjZXNzIHRvIHRoZSBB Uk02NCBUYWdnZWQgQWRkcmVzcyBBQkkgZm9yCj4+ICvCoMKgwqAgYWxsIHRoZSBhcHBsaWNhdGlv bnMuCj4+ICsKPj4gK8KgwqAgSWYgdGhlIGFjY2VzcyB0byB0aGUgQVJNNjQgVGFnZ2VkIEFkZHJl c3MgQUJJIGlzIGRpc2FibGVkIGF0IGEgY2VydGFpbgo+PiArwqDCoCBwb2ludCBpbiB0aW1lLCBh bGwgdGhlIGFwcGxpY2F0aW9ucyB0aGF0IHdlcmUgdXNpbmcgdGFnZ2luZyBiZWZvcmUgdGhpcwo+ PiArwqDCoCBldmVudCBvY2N1cnMsIHdpbGwgY29udGludWUgdG8gdXNlIHRhZ2dpbmcuCj4gCj4g InRhZ2dpbmciIG1heSBiZSBtaXNpbnRlcnByZXRlZCBoZXJlLiBJIHdvdWxkIGJlIG1vcmUgZXhw bGljaXQgYnkgc2F5aW5nIHRoYXQKPiB0aGUgdGFnZ2VkIGFkZHJlc3MgQUJJIHJlbWFpbnMgZW5h YmxlZCBpbiBwcm9jZXNzZXMgdGhhdCBvcHRlZCBpbiBiZWZvcmUgdGhlCj4gYWNjZXNzIGdvdCBk aXNhYmxlZC4KPiAKCkFzc3VtaW5nIHRoYXQgQVJNNjQgVGFnZ2VkIEFkZHJlc3MgQUJJIGdpdmVz IGFjY2VzcyB0byAidGFnZ2luZyIgYW5kIHNpbmNlIGl0IGlzCndoYXQgdGhpcyBkb2N1bWVudCBp cyB0YWxraW5nIGFib3V0LCBJIGRvIG5vdCBzZWUgaG93IGl0IGNhbiBiZSBtaXNpbnRlcnByZXRl ZCA7KQoKPj4gKy0gKipwcmN0bCgpcyoqOgo+PiArCj4+ICvCoCAtICoqUFJfU0VUX1RBR0dFRF9B RERSX0NUUkwqKjogSW52b2tlZCBieSBhIHByb2Nlc3MsIGNhbiBiZSB1c2VkIHRvIGVuYWJsZSBv cgo+PiArwqDCoMKgIGRpc2FibGUgaXRzIGFjY2VzcyB0byB0aGUgQVJNNjQgVGFnZ2VkIEFkZHJl c3MgQUJJLgo+IAo+IEkgc3RpbGwgZmluZCB0aGUgd29yZGluZyBjb25mdXNpbmcsIGJlY2F1c2Ug ImFjY2VzcyB0byB0aGUgQUJJIiBpcyBub3QgdXNlZAo+IGNvbnNpc3RlbnRseS4gVGhlICJ0YWdn ZWRfYWRkciIgc3lzY3RsIGVuYWJsZXMgKmFjY2VzcyB0byB0aGUgQUJJKiwgdGhhdCdzIGZpbmUu Cj4gSG93ZXZlciwgUFJfU0VUX1RBR0dFRF9BRERSX0NUUkwgZW5hYmxlcyAqdGhlIEFCSSBpdHNl bGYqICh3aGljaCBpcyBvbmx5Cj4gcG9zc2libGUgaWYgYWNjZXNzIHRvIHRoZSBBQkkgaXMgZW5h YmxlZCkuCj4gCgpBcyBpdCBzdGFuZHMsIGl0IGVuYWJsZXMgb3IgZGlzYWJsZXMgdGhlIEFCSSBp dHNlbGYgd2hlbiB1c2VkIHdpdGgKUFJfVEFHR0VEX0FERFJfRU5BQkxFLCBvciBjYW4gZW5hYmxl IG90aGVyIHRoaW5ncyBpbiBmdXR1cmUuIElNSE8gdGhlIG9ubHkgdGhpbmcKdGhhdCB0aGVzZSBm ZWF0dXJlcyBoYXZlIGluIGNvbW1vbiBpcyB0aGUgYWNjZXNzIHRvIHRoZSBBQkkgd2hpY2ggaXMg Z3JhbnRlZCBieQp0aGlzIHByY3RsKCkuCgo+PiArCj4+ICvCoMKgwqAgVGhlICh1bnNpZ25lZCBp bnQpIGFyZzIgYXJndW1lbnQgaXMgYSBiaXQgbWFzayBkZXNjcmliaW5nIHRoZSBjb250cm9sIG1v ZGUKPj4gK8KgwqDCoCB1c2VkOgo+PiArCj4+ICvCoMKgwqAgLSAqKlBSX1RBR0dFRF9BRERSX0VO QUJMRSoqOiBFbmFibGUgQVJNNjQgVGFnZ2VkIEFkZHJlc3MgQUJJLgo+PiArCj4+ICvCoMKgwqAg VGhlIHByY3RsKFBSX1NFVF9UQUdHRURfQUREUl9DVFJMLCAuLi4pIHdpbGwgcmV0dXJuIC1FSU5W QUwgaWYgdGhlIEFSTTY0Cj4+ICvCoMKgwqAgVGFnZ2VkIEFkZHJlc3MgQUJJIGlzIG5vdCBhdmFp bGFibGUuCj4gCj4gRm9yIGNsYXJpdHksIGl0IHdvdWxkIGJlIGdvb2QgdG8gbWVudGlvbiB0aGF0 IG9uZSBwb3NzaWJsZSByZWFzb24gZm9yIHRoZSBBQkkKPiBub3QgdG8gYmUgYXZhaWxhYmxlIGlz IHRhZ2dlZF9hZGRyID09IDAuCj4gCgpUaGUgbG9naWNhbCBpbXBsaWNhdGlvbiBpcyBhbHJlYWR5 IHF1aXRlIGNsZWFyIHRhZ2dlZF9hZGRyID09IDAgKERpc2FibGVkKSA9PgpUYWdnZWQgQWRkcmVz cyBBQkkgbm90IGF2YWlsYWJsZSA9PiByZXR1cm4gLUVJTlZBTC4gSSBkbyBub3Qgc2VlIHRoZSBu ZWVkIHRvCnJlcGVhdCB0aGUgY29uY2VwdCB0d2ljZS4KCj4+ICsKPj4gK8KgwqDCoCBUaGUgYXJn dW1lbnRzIGFyZzMsIGFyZzQsIGFuZCBhcmc1IGFyZSBpZ25vcmVkLgo+PiArwqAgLSAqKlBSX0dF VF9UQUdHRURfQUREUl9DVFJMKio6IGNhbiBiZSB1c2VkIHRvIGNoZWNrIHRoZSBzdGF0dXMgb2Yg dGhlIFRhZ2dlZAo+PiArwqDCoMKgIEFkZHJlc3MgQUJJLgo+PiArCj4+ICvCoMKgwqAgVGhlIGFy Z3VtZW50cyBhcmcyLCBhcmczLCBhcmc0LCBhbmQgYXJnNSBhcmUgaWdub3JlZC4KPj4gKwo+PiAr VGhlIEFCSSBwcm9wZXJ0aWVzIHNldCBieSB0aGUgbWVjaGFuaXNtcyBkZXNjcmliZWQgYWJvdmUg YXJlIGluaGVyaXRlZCBieQo+PiB0aHJlYWRzCj4+ICtvZiB0aGUgc2FtZSBhcHBsaWNhdGlvbiBh bmQgZm9yaygpJ2VkIGNoaWxkcmVuIGJ1dCBjbGVhcmVkIGJ5IGV4ZWN2ZSgpLgo+PiArCj4+ICtX aGVuIGEgcHJvY2VzcyBoYXMgc3VjY2Vzc2Z1bGx5IG9wdGVkIGludG8gdGhlIG5ldyBBQkkgYnkg aW52b2tpbmcKPj4gK1BSX1NFVF9UQUdHRURfQUREUl9DVFJMIHByY3RsKCksIHRoaXMgZ3VhcmFu dGVlcyB0aGUgZm9sbG93aW5nIGJlaGF2aW91cnM6Cj4+ICsKPj4gKyAtIEV2ZXJ5IGN1cnJlbnRs eSBhdmFpbGFibGUgc3lzY2FsbCwgZXhjZXB0IHRoZSBjYXNlcyBtZW50aW9uZWQgaW4gc2VjdGlv bgo+PiAzLCBjYW4KPj4gK8KgwqAgYWNjZXB0IGFueSB2YWxpZCB0YWdnZWQgcG9pbnRlci4gVGhl IHNhbWUgcnVsZSBpcyBhcHBsaWNhYmxlIHRvIGFueSBzeXNjYWxsCj4+ICvCoMKgIGludHJvZHVj ZWQgaW4gdGhlIGZ1dHVyZS4KPiAKPiBJIHRob3VnaHQgQ2F0YWxpbiB3YW50ZWQgdG8gZHJvcCB0 aGlzIGd1YXJhbnRlZT8KPiAKClRoZSBndWFyYW50ZWUgaXMgY2hhbmdlZCBhbmQgZXhwbGljaXRs eSBpbmNsdWRlcyB0aGUgc3lzY2FsbHMgdGhhdCBjYW4gYmUgYWRkZWQKaW4gdGhlIGZ1dHVyZS4g SU1ITyBzaW5jZSB3ZSBhcmUgZGVmaW5pbmcgYW4gQUJJLCB3ZSBjYW5ub3QgbGVhdmUgdGhhdCB0 b3BpYyBpbgphbiB1bmNoYXJ0ZWQgdGVycml0b3J5LCB3ZSBuZWVkIHRvIGFkZHJlc3MgaXQuCgo+ PiArIC0gSWYgYSBub24gdmFsaWQgdGFnZ2VkIHBvaW50ZXIgaXMgcGFzc2VkIHRvIGEgc3lzY2Fs bCB0aGVuIHRoZSBiZWhhdmlvdXIKPj4gK8KgwqAgaXMgdW5kZWZpbmVkLgo+PiArIC0gRXZlcnkg dmFsaWQgdGFnZ2VkIHBvaW50ZXIgaXMgZXhwZWN0ZWQgdG8gd29yayBhcyBhbiB1bnRhZ2dlZCBv bmUuCj4+ICsgLSBUaGUga2VybmVsIHByZXNlcnZlcyBhbnkgdmFsaWQgdGFnZ2VkIHBvaW50ZXIg YW5kIHJldHVybnMgaXQgdG8gdGhlCj4+ICvCoMKgIHVzZXJzcGFjZSB1bmNoYW5nZWQgKGkuZS4g b24gc3lzY2FsbCByZXR1cm4pIGluIGFsbCB0aGUgY2FzZXMgZXhjZXB0IHRoZQo+PiArwqDCoCBv bmVzIGRvY3VtZW50ZWQgaW4gdGhlICJQcmVzZXJ2aW5nIHRhZ3MiIHNlY3Rpb24gb2YgdGFnZ2Vk LXBvaW50ZXJzLnR4dC4KPj4gKwo+PiArQSBkZWZpbml0aW9uIG9mIHRoZSBtZWFuaW5nIG9mIHRh Z2dlZCBwb2ludGVycyBvbiBhcm02NCBjYW4gYmUgZm91bmQgaW46Cj4+ICtEb2N1bWVudGF0aW9u L2FybTY0L3RhZ2dlZC1wb2ludGVycy50eHQuCj4+ICsKPj4gKzMuIEFSTTY0IFRhZ2dlZCBBZGRy ZXNzIEFCSSBFeGNlcHRpb25zCj4+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLQo+PiArCj4+ICtUaGUgYmVoYXZpb3VycyBkZXNjcmliZWQgaW4gc2VjdGlvbiAyLCB3aXRo IHBhcnRpY3VsYXIgcmVmZXJlbmNlIHRvIHRoZQo+PiArYWNjZXB0YW5jZSBieSB0aGUgc3lzY2Fs bHMgb2YgYW55IHZhbGlkIHRhZ2dlZCBwb2ludGVyIGFyZSBub3QgYXBwbGljYWJsZQo+PiArdG8g dGhlIGZvbGxvd2luZyBjYXNlczoKPj4gKwo+PiArIC0gbW1hcCgpIGFkZHIgcGFyYW1ldGVyLgo+ PiArIC0gbXJlbWFwKCkgbmV3X2FkZHJlc3MgcGFyYW1ldGVyLgo+PiArIC0gcHJjdGwoUFJfU0VU X01NLCBQUl9TRVRfTU1fTUFQLCAuLi4pIHN0cnVjdCBwcmN0bF9tbV9tYXAgZmllbGRzLgo+PiAr IC0gcHJjdGwoUFJfU0VUX01NLCBQUl9TRVRfTU1fTUFQX1NJWkUsIC4uLikgc3RydWN0IHByY3Rs X21tX21hcCBmaWVsZHMuCj4gCj4gQWxsIHRoZSBQUl9TRVRfTU0gb3B0aW9ucyB0aGF0IHNwZWNp ZnkgcG9pbnRlcnMgKFBSX1NFVF9NTV9TVEFSVF9DT0RFLAo+IFBSX1NFVF9NTV9FTkRfQ09ERSwg Li4uKSBzaG91bGQgYmUgZXhjbHVkZWQgYXMgd2VsbC4gQUZBSUNUIChidXQgZG9uJ3QgdGFrZSBt eQo+IHdvcmQgZm9yIGl0KSwgdGhhdCdzIGFsbCBvZiB0aGVtIGV4Y2VwdCBQUl9TRVRfTU1fRVhF X0ZJTEUuIENvbnZlcnNlbHksCj4gUFJfU0VUX01NX01BUF9TSVpFIHNob3VsZCBub3QgYmUgZXhj bHVkZWQgKGl0IGRvZXMgbm90IHBhc3MgYSBwcmN0bF9tbV9tYXAKPiBzdHJ1Y3QsIGFuZCB0aGUg cG9pbnRlciB0byB1bnNpZ25lZCBpbnQgY2FuIGJlIHRhZ2dlZCkuCj4gCgpBZ3JlZWQsIEkgY2xl YXJseSBtaXNyZWFkIHRoZSBwcmN0bCgpIG1hbiBwYWdlIGhlcmUuIEZpbGwgZml4IGluIHY3LgpQ Ul9TRVRfTU1fTUFQX1NJWkUgX3JldHVybnNfICBzdHJ1Y3QgcHJjdGxfbW1fbWFwLCBkb2VzIG5v dCB0YWtlIGl0IGFzIGEgcGFyYW1ldGVyLgoKVmluY2Vuem8KCj4gS2V2aW4KPiAKPj4gKwo+PiAr QW55IGF0dGVtcHQgdG8gdXNlIG5vbi16ZXJvIHRhZ2dlZCBwb2ludGVycyB3aWxsIGxlYWQgdG8g dW5kZWZpbmVkIGJlaGF2aW91ci4KPj4gKwo+PiArNC4gRXhhbXBsZSBvZiBjb3JyZWN0IHVzYWdl Cj4+ICstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPj4gKy4uIGNvZGUtYmxvY2s6OiBjCj4+ ICsKPj4gK8KgwqAgdm9pZCBtYWluKHZvaWQpCj4+ICvCoMKgIHsKPj4gK8KgwqDCoMKgwqDCoMKg wqDCoMKgIHN0YXRpYyBpbnQgdGJpX2VuYWJsZWQgPSAwOwo+PiArwqDCoMKgwqDCoMKgwqDCoMKg wqAgdW5zaWduZWQgbG9uZyB0YWcgPSAwOwo+PiArCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoCBj aGFyICpwdHIgPSBtbWFwKE5VTEwsIFBBR0VfU0laRSwgUFJPVF9SRUFEIHwgUFJPVF9XUklURSwK Pj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oCBNQVBfQU5PTllNT1VTLCAtMSwgMCk7Cj4+ICsKPj4gK8KgwqDCoMKgwqDCoMKgwqDCoMKgIGlm IChwcmN0bChQUl9TRVRfVEFHR0VEX0FERFJfQ1RSTCwgUFJfVEFHR0VEX0FERFJfRU5BQkxFLAo+ PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAwLCAwLCAwKSA9PSAw KQo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgIHRiaV9lbmFibGVkID0g MTsKPj4gKwo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqAgaWYgKHB0ciA9PSAodm9pZCAqKS0xKSAv KiBNQVBfRkFJTEVEICovCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAg cmV0dXJuIC0xOwo+PiArCj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoCBpZiAodGJpX2VuYWJsZWQp Cj4+ICvCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqAgdGFnID0gcmFuZCgpICYg MHhmZjsKPj4gKwo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqAgcHRyID0gKGNoYXIgKikoKHVuc2ln bmVkIGxvbmcpcHRyIHwgKHRhZyA8PCBUQUdfU0hJRlQpKTsKPj4gKwo+PiArwqDCoMKgwqDCoMKg wqDCoMKgwqAgKnB0ciA9ICdhJzsKPj4gKwo+PiArwqDCoMKgwqDCoMKgwqDCoMKgwqAgLi4uCj4+ ICvCoMKgIH0KPj4gKwo+IAo+IF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fCj4gbGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKPiBsaW51eC1hcm0ta2Vy bmVsQGxpc3RzLmluZnJhZGVhZC5vcmcKPiBodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWls bWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwKCi0tIApSZWdhcmRzLApWaW5jZW56bwoKX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtYXJtLWtl cm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCmh0 dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5l bAo=