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=-14.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1,USER_IN_DEF_DKIM_WL 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 1EF9BC433DF for ; Tue, 4 Aug 2020 15:46:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 01CCE21744 for ; Tue, 4 Aug 2020 15:46:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="EutcuYNA" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729174AbgHDPqr (ORCPT ); Tue, 4 Aug 2020 11:46:47 -0400 Received: from linux.microsoft.com ([13.77.154.182]:53610 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728295AbgHDPqo (ORCPT ); Tue, 4 Aug 2020 11:46:44 -0400 Received: from [192.168.254.32] (unknown [47.187.206.220]) by linux.microsoft.com (Postfix) with ESMTPSA id 9B23A20B4908; Tue, 4 Aug 2020 08:46:41 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 9B23A20B4908 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1596556002; bh=wHC31skMgFt/ebqHymj769kGPOKXA4hyoGb1xMjf0fI=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=EutcuYNAeGhOfkiO8T1sIvfJSLcvl24ddG2j+NfgLnwZCraC2VozjLawrJmUJlmea uMTlKW22ne7ngBbcz+KuCNluoJpU8MvjXq4d9Zax32BecuA0bRhi+seD3ikjWvtxPt m71EidTy92505Hg9DsZNgxuxfBJvroeKJTm5VwQk= Subject: Re: [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor To: Mark Rutland Cc: Andy Lutomirski , Kernel Hardening , Linux API , linux-arm-kernel , Linux FS Devel , linux-integrity , LKML , LSM List , Oleg Nesterov , X86 ML References: <20200728131050.24443-1-madvenka@linux.microsoft.com> <6540b4b7-3f70-adbf-c922-43886599713a@linux.microsoft.com> <46a1adef-65f0-bd5e-0b17-54856fb7e7ee@linux.microsoft.com> <20200731183146.GD67415@C02TD0UTHF1T.local> <86625441-80f3-2909-2f56-e18e2b60957d@linux.microsoft.com> <20200804135558.GA7440@C02TD0UTHF1T.local> From: "Madhavan T. Venkataraman" Message-ID: <874ec700-405f-bad8-175f-884b4f6f66f2@linux.microsoft.com> Date: Tue, 4 Aug 2020 10:46:40 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: <20200804135558.GA7440@C02TD0UTHF1T.local> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-Language: en-US Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hey Mark, I am working on putting together an improved definition of trampfd per Andy's comment. I will try to address your comments in that improved definition. Once I send that out, I will respond to your emails as well. Thanks. Madhavan On 8/4/20 8:55 AM, Mark Rutland wrote: > On Mon, Aug 03, 2020 at 12:58:04PM -0500, Madhavan T. Venkataraman wrote: >> On 7/31/20 1:31 PM, Mark Rutland wrote: >>> On Fri, Jul 31, 2020 at 12:13:49PM -0500, Madhavan T. Venkataraman wrote: >>>> On 7/30/20 3:54 PM, Andy Lutomirski wrote: >>>>> On Thu, Jul 30, 2020 at 7:24 AM Madhavan T. Venkataraman >>>>> wrote: >>>>> When the kernel generates the code for a trampoline, it can hard code data values >>>> in the generated code itself so it does not need PC-relative data referencing. >>>> >>>> And, for ISAs that do support the large offset, we do have to implement and >>>> maintain the code page stuff for different ISAs for each application and library >>>> if we did not use trampfd. >>> Trampoline code is architecture specific today, so I don't see that as a >>> major issue. Common structural bits can probably be shared even if the >>> specifid machine code cannot. >> True. But an implementor may prefer a standard mechanism provided by >> the kernel so all of his architectures can be supported easily with less >> effort. >> >> If you look at the libffi reference patch I have included, the architecture >> specific changes to use trampfd just involve a single C function call to >> a common code function. > Sure but in addition to that each architecture backend had to define a > set of arguments to that. I view the C function is analagous to the > "common structural bits". > > I appreciate that your patch is small today (and architectures seem to > largely align on what they need), but I don't think it's necessarily > true that things will remain so simple as architecture are extended and > their calling conventions evolve, and I also don't think it's clear that > this will work for more complex cases elsewhere. > > [...] > >>>> With the user level trampoline table approach, the data part of the trampoline table >>>> can be hacked by an attacker if an application has a vulnerability. Specifically, the >>>> target PC can be altered to some arbitrary location. Trampfd implements an >>>> "Allowed PCS" context. In the libffi changes, I have created a read-only array of >>>> all ABI handlers used in closures for each architecture. This read-only array >>>> can be used to restrict the PC values for libffi trampolines to prevent hacking. >>>> >>>> To generalize, we can implement security rules/features if the trampoline >>>> object is in the kernel. >>> I don't follow this argument. If it's possible to statically define that >>> in the kernel, it's also possible to do that in userspace without any >>> new kernel support. >> It is not statically defined in the kernel. >> >> Let us take the libffi example. In the 64-bit X86 arch code, there are 3 >> ABI handlers: >> >>     ffi_closure_unix64_sse >>     ffi_closure_unix64 >>     ffi_closure_win64 >> >> I could create an "Allowed PCs" context like this: >> >> struct my_allowed_pcs { >>     struct trampfd_values    pcs; >>     __u64                             pc_values[3]; >> }; >> >> const struct my_allowed_pcs    my_allowed_pcs = { >>     { 3, 0 }, >>     (uintptr_t) ffi_closure_unix64_sse, >>     (uintptr_t) ffi_closure_unix64, >>     (uintptr_t) ffi_closure_win64, >> }; >> >> I have created a read-only array of allowed ABI handlers that closures use. >> >> When I set up the context for a closure trampoline, I could do this: >> >>     pwrite(trampfd, &my_allowed_pcs, sizeof(my_allowed_pcs), TRAMPFD_ALLOWED_PCS_OFFSET); >>     >> This copies the array into the trampoline object in the kernel. >> When the register context is set for the trampoline, the kernel checks >> the PC register value against allowed PCs. >> >> Because my_allowed_pcs is read-only, a hacker cannot modify it. So, the only >> permitted target PCs enforced by the kernel are the ABI handlers. > Sorry, when I said "statically define" meant when you knew legitimate > targets ahead of time when you create the trampoline (i.e. whether you > could enumerate those and know they would not change dynamically). > > My point was that you can achieve the same in userspace if the > trampoline and array of legitimate targets are in read-only memory, > without having to trap to the kernel. > > I think the key point here is that an adversary must be prevented from > altering a trampoline and any associated metadata, and I think that > there are ways of achieving that without having to trap into the kernel, > and without the kernel having to be intimately aware of the calling > conventions used in userspace. > > [...] > >>>> Trampfd is a framework that can be used to implement multiple things. May be, >>>> a few of those things can also be implemented in user land itself. But I think having >>>> just one mechanism to execute dynamic code objects is preferable to having >>>> multiple mechanisms not standardized across all applications. >>> In abstract, having a common interface sounds nice, but in practice >>> elements of this are always architecture-specific (e.g. interactiosn >>> with HW CFI), and that common interface can result in more pain as it >>> doesn't fit naturally into the context that ISAs were designed for (e.g. >>> where control-flow instructions are extended with new semantics). >> In the case of trampfd, the code generation is indeed architecture >> specific. But that is in the kernel. The application is not affected by it. > As an ABI detail, applications are *definitely* affected by this, and it > is wrong to suggest they are not even if you don't have a specific case > in mind today. As this forms a contract between userspace and the kernel > it's overly simplistic to say that it's the kernel's problem > > For example, in the case of BTI on arm64, what should the trampoline > set PSTATE.BTYPE to? Different use-cases *will* want different values, > and not necessarily the value of PSTATE at the instant the call to the > trampoline was made. In the case of libffi specifically using the > original value of PSTATE.BTYPE probably is sound, but other code > sequences may need to restrict/broaden or entirely change that. > >> Again, referring to the libffi reference patch, I have defined wrapper >> functions for trampfd in common code. The architecture specific code >> in libffi only calls the set_context function defined in common code. >> Even this is required only because register names are specific to each >> architecture and the target PC (to the ABI handler) is specific to >> each architecture-ABI combo. >> >>> It also meass that you can't share the rough approach across OSs which >>> do not implement an identical mechanism, so for code abstracting by ISA >>> first, then by platform/ABI, there isn't much saving. >> Why can you not share the same approach across OSes? In fact, >> I have tried to design it so that other OSes can use the same >> mechanism. > Sure, but where they *don't*, you must fall back to the existing > purely-userspace mechanisms, and so a codebase now has the burden of > maintaining two distinct mechanisms. > > Whereas if there's a way of doing this in userspace with (stronger) > enforcement of memory permissions the trampoline code can be common for > when this is present or absent, which is much easier for a codebase rto > maintain, and could make use of weaker existing mechanisms to improve > the situation on systems without the new functionality. > > Thanks, > Mark. 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=-7.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 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 B2524C433DF for ; Tue, 4 Aug 2020 15:48:10 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 7CDC421744 for ; Tue, 4 Aug 2020 15:48:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="MMXc3AI9"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="EutcuYNA" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7CDC421744 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.microsoft.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+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=merlin.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=UweoV0hkFFciJEgm9ZRv6622/N0GGAhhFXeSYinkjyA=; b=MMXc3AI9ZjKGm1tgmadQg5s+e QYN5AEFw0FryBId2EBdOFnf/5l1lj507XBqEkaTJ6xTU7+eI21Ug0WCAut/3Fs1/zraSlxe3z26Tp eD4a35VSi4OmspXx9mMtqwVh7cwVOTCEu+EBwjtutpMVwNhOXlFHTo86jV0QpgkIHGaIaV0WLymce 6jALnbXULv9pvK3t3Dm1e00YaPG7TPI1/CJg3m4Rz0ZV9BBrgsMShb/FCt3ALcLnlsMaaZRtLroWL MOKhtm7o0tu1CC4+isX9J81cpYLSxBlHV2WPUhMh0ZBQRsQUSSVvwVACxI2zuCwiO5aWmd7PNhr/F F+WV48q0w==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1k2z9K-0000zo-Jd; Tue, 04 Aug 2020 15:46:46 +0000 Received: from linux.microsoft.com ([13.77.154.182]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1k2z9H-0000yb-F7 for linux-arm-kernel@lists.infradead.org; Tue, 04 Aug 2020 15:46:44 +0000 Received: from [192.168.254.32] (unknown [47.187.206.220]) by linux.microsoft.com (Postfix) with ESMTPSA id 9B23A20B4908; Tue, 4 Aug 2020 08:46:41 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 9B23A20B4908 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1596556002; bh=wHC31skMgFt/ebqHymj769kGPOKXA4hyoGb1xMjf0fI=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=EutcuYNAeGhOfkiO8T1sIvfJSLcvl24ddG2j+NfgLnwZCraC2VozjLawrJmUJlmea uMTlKW22ne7ngBbcz+KuCNluoJpU8MvjXq4d9Zax32BecuA0bRhi+seD3ikjWvtxPt m71EidTy92505Hg9DsZNgxuxfBJvroeKJTm5VwQk= Subject: Re: [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor To: Mark Rutland References: <20200728131050.24443-1-madvenka@linux.microsoft.com> <6540b4b7-3f70-adbf-c922-43886599713a@linux.microsoft.com> <46a1adef-65f0-bd5e-0b17-54856fb7e7ee@linux.microsoft.com> <20200731183146.GD67415@C02TD0UTHF1T.local> <86625441-80f3-2909-2f56-e18e2b60957d@linux.microsoft.com> <20200804135558.GA7440@C02TD0UTHF1T.local> From: "Madhavan T. Venkataraman" Message-ID: <874ec700-405f-bad8-175f-884b4f6f66f2@linux.microsoft.com> Date: Tue, 4 Aug 2020 10:46:40 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: <20200804135558.GA7440@C02TD0UTHF1T.local> Content-Language: en-US X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200804_114643_639249_C7328DE9 X-CRM114-Status: GOOD ( 43.77 ) 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: Kernel Hardening , Linux API , X86 ML , LKML , Oleg Nesterov , LSM List , Andy Lutomirski , Linux FS Devel , linux-integrity , linux-arm-kernel 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 SGV5IE1hcmssCgpJIGFtIHdvcmtpbmcgb24gcHV0dGluZyB0b2dldGhlciBhbiBpbXByb3ZlZCBk ZWZpbml0aW9uIG9mIHRyYW1wZmQgcGVyCkFuZHkncyBjb21tZW50LiBJIHdpbGwgdHJ5IHRvIGFk ZHJlc3MgeW91ciBjb21tZW50cyBpbiB0aGF0IGltcHJvdmVkCmRlZmluaXRpb24uIE9uY2UgSSBz ZW5kIHRoYXQgb3V0LCBJIHdpbGwgcmVzcG9uZCB0byB5b3VyIGVtYWlscyBhcyB3ZWxsLgoKVGhh bmtzLgoKTWFkaGF2YW4KCk9uIDgvNC8yMCA4OjU1IEFNLCBNYXJrIFJ1dGxhbmQgd3JvdGU6Cj4g T24gTW9uLCBBdWcgMDMsIDIwMjAgYXQgMTI6NTg6MDRQTSAtMDUwMCwgTWFkaGF2YW4gVC4gVmVu a2F0YXJhbWFuIHdyb3RlOgo+PiBPbiA3LzMxLzIwIDE6MzEgUE0sIE1hcmsgUnV0bGFuZCB3cm90 ZToKPj4+IE9uIEZyaSwgSnVsIDMxLCAyMDIwIGF0IDEyOjEzOjQ5UE0gLTA1MDAsIE1hZGhhdmFu IFQuIFZlbmthdGFyYW1hbiB3cm90ZToKPj4+PiBPbiA3LzMwLzIwIDM6NTQgUE0sIEFuZHkgTHV0 b21pcnNraSB3cm90ZToKPj4+Pj4gT24gVGh1LCBKdWwgMzAsIDIwMjAgYXQgNzoyNCBBTSBNYWRo YXZhbiBULiBWZW5rYXRhcmFtYW4KPj4+Pj4gPG1hZHZlbmthQGxpbnV4Lm1pY3Jvc29mdC5jb20+ IHdyb3RlOgo+Pj4+PiBXaGVuIHRoZSBrZXJuZWwgZ2VuZXJhdGVzIHRoZSBjb2RlIGZvciBhIHRy YW1wb2xpbmUsIGl0IGNhbiBoYXJkIGNvZGUgZGF0YSB2YWx1ZXMKPj4+PiBpbiB0aGUgZ2VuZXJh dGVkIGNvZGUgaXRzZWxmIHNvIGl0IGRvZXMgbm90IG5lZWQgUEMtcmVsYXRpdmUgZGF0YSByZWZl cmVuY2luZy4KPj4+Pgo+Pj4+IEFuZCwgZm9yIElTQXMgdGhhdCBkbyBzdXBwb3J0IHRoZSBsYXJn ZSBvZmZzZXQsIHdlIGRvIGhhdmUgdG8gaW1wbGVtZW50IGFuZAo+Pj4+IG1haW50YWluIHRoZSBj b2RlIHBhZ2Ugc3R1ZmYgZm9yIGRpZmZlcmVudCBJU0FzIGZvciBlYWNoIGFwcGxpY2F0aW9uIGFu ZCBsaWJyYXJ5Cj4+Pj4gaWYgd2UgZGlkIG5vdCB1c2UgdHJhbXBmZC4KPj4+IFRyYW1wb2xpbmUg Y29kZSBpcyBhcmNoaXRlY3R1cmUgc3BlY2lmaWMgdG9kYXksIHNvIEkgZG9uJ3Qgc2VlIHRoYXQg YXMgYQo+Pj4gbWFqb3IgaXNzdWUuIENvbW1vbiBzdHJ1Y3R1cmFsIGJpdHMgY2FuIHByb2JhYmx5 IGJlIHNoYXJlZCBldmVuIGlmIHRoZQo+Pj4gc3BlY2lmaWQgbWFjaGluZSBjb2RlIGNhbm5vdC4K Pj4gVHJ1ZS4gQnV0IGFuIGltcGxlbWVudG9yIG1heSBwcmVmZXIgYSBzdGFuZGFyZCBtZWNoYW5p c20gcHJvdmlkZWQgYnkKPj4gdGhlIGtlcm5lbCBzbyBhbGwgb2YgaGlzIGFyY2hpdGVjdHVyZXMg Y2FuIGJlIHN1cHBvcnRlZCBlYXNpbHkgd2l0aCBsZXNzCj4+IGVmZm9ydC4KPj4KPj4gSWYgeW91 IGxvb2sgYXQgdGhlIGxpYmZmaSByZWZlcmVuY2UgcGF0Y2ggSSBoYXZlIGluY2x1ZGVkLCB0aGUg YXJjaGl0ZWN0dXJlCj4+IHNwZWNpZmljIGNoYW5nZXMgdG8gdXNlIHRyYW1wZmQganVzdCBpbnZv bHZlIGEgc2luZ2xlIEMgZnVuY3Rpb24gY2FsbCB0bwo+PiBhIGNvbW1vbiBjb2RlIGZ1bmN0aW9u Lgo+IFN1cmUgYnV0IGluIGFkZGl0aW9uIHRvIHRoYXQgZWFjaCBhcmNoaXRlY3R1cmUgYmFja2Vu ZCBoYWQgdG8gZGVmaW5lIGEKPiBzZXQgb2YgYXJndW1lbnRzIHRvIHRoYXQuIEkgdmlldyB0aGUg QyBmdW5jdGlvbiBpcyBhbmFsYWdvdXMgdG8gdGhlCj4gImNvbW1vbiBzdHJ1Y3R1cmFsIGJpdHMi Lgo+Cj4gSSBhcHByZWNpYXRlIHRoYXQgeW91ciBwYXRjaCBpcyBzbWFsbCB0b2RheSAoYW5kIGFy Y2hpdGVjdHVyZXMgc2VlbSB0bwo+IGxhcmdlbHkgYWxpZ24gb24gd2hhdCB0aGV5IG5lZWQpLCBi dXQgSSBkb24ndCB0aGluayBpdCdzIG5lY2Vzc2FyaWx5Cj4gdHJ1ZSB0aGF0IHRoaW5ncyB3aWxs IHJlbWFpbiBzbyBzaW1wbGUgYXMgYXJjaGl0ZWN0dXJlIGFyZSBleHRlbmRlZCBhbmQKPiB0aGVp ciBjYWxsaW5nIGNvbnZlbnRpb25zIGV2b2x2ZSwgYW5kIEkgYWxzbyBkb24ndCB0aGluayBpdCdz IGNsZWFyIHRoYXQKPiB0aGlzIHdpbGwgd29yayBmb3IgbW9yZSBjb21wbGV4IGNhc2VzIGVsc2V3 aGVyZS4KPgo+IFsuLi5dCj4KPj4+PiBXaXRoIHRoZSB1c2VyIGxldmVsIHRyYW1wb2xpbmUgdGFi bGUgYXBwcm9hY2gsIHRoZSBkYXRhIHBhcnQgb2YgdGhlIHRyYW1wb2xpbmUgdGFibGUKPj4+PiBj YW4gYmUgaGFja2VkIGJ5IGFuIGF0dGFja2VyIGlmIGFuIGFwcGxpY2F0aW9uIGhhcyBhIHZ1bG5l cmFiaWxpdHkuIFNwZWNpZmljYWxseSwgdGhlCj4+Pj4gdGFyZ2V0IFBDIGNhbiBiZSBhbHRlcmVk IHRvIHNvbWUgYXJiaXRyYXJ5IGxvY2F0aW9uLiBUcmFtcGZkIGltcGxlbWVudHMgYW4KPj4+PiAi QWxsb3dlZCBQQ1MiIGNvbnRleHQuIEluIHRoZSBsaWJmZmkgY2hhbmdlcywgSSBoYXZlIGNyZWF0 ZWQgYSByZWFkLW9ubHkgYXJyYXkgb2YKPj4+PiBhbGwgQUJJIGhhbmRsZXJzIHVzZWQgaW4gY2xv c3VyZXMgZm9yIGVhY2ggYXJjaGl0ZWN0dXJlLiBUaGlzIHJlYWQtb25seSBhcnJheQo+Pj4+IGNh biBiZSB1c2VkIHRvIHJlc3RyaWN0IHRoZSBQQyB2YWx1ZXMgZm9yIGxpYmZmaSB0cmFtcG9saW5l cyB0byBwcmV2ZW50IGhhY2tpbmcuCj4+Pj4KPj4+PiBUbyBnZW5lcmFsaXplLCB3ZSBjYW4gaW1w bGVtZW50IHNlY3VyaXR5IHJ1bGVzL2ZlYXR1cmVzIGlmIHRoZSB0cmFtcG9saW5lCj4+Pj4gb2Jq ZWN0IGlzIGluIHRoZSBrZXJuZWwuCj4+PiBJIGRvbid0IGZvbGxvdyB0aGlzIGFyZ3VtZW50LiBJ ZiBpdCdzIHBvc3NpYmxlIHRvIHN0YXRpY2FsbHkgZGVmaW5lIHRoYXQKPj4+IGluIHRoZSBrZXJu ZWwsIGl0J3MgYWxzbyBwb3NzaWJsZSB0byBkbyB0aGF0IGluIHVzZXJzcGFjZSB3aXRob3V0IGFu eQo+Pj4gbmV3IGtlcm5lbCBzdXBwb3J0Lgo+PiBJdCBpcyBub3Qgc3RhdGljYWxseSBkZWZpbmVk IGluIHRoZSBrZXJuZWwuCj4+Cj4+IExldCB1cyB0YWtlIHRoZSBsaWJmZmkgZXhhbXBsZS4gSW4g dGhlIDY0LWJpdCBYODYgYXJjaCBjb2RlLCB0aGVyZSBhcmUgMwo+PiBBQkkgaGFuZGxlcnM6Cj4+ Cj4+IMKgwqDCoCBmZmlfY2xvc3VyZV91bml4NjRfc3NlCj4+IMKgwqDCoCBmZmlfY2xvc3VyZV91 bml4NjQKPj4gwqDCoMKgIGZmaV9jbG9zdXJlX3dpbjY0Cj4+Cj4+IEkgY291bGQgY3JlYXRlIGFu ICJBbGxvd2VkIFBDcyIgY29udGV4dCBsaWtlIHRoaXM6Cj4+Cj4+IHN0cnVjdCBteV9hbGxvd2Vk X3BjcyB7Cj4+IMKgwqDCoCBzdHJ1Y3QgdHJhbXBmZF92YWx1ZXMgwqDCoCBwY3M7Cj4+IMKgwqDC oCBfX3U2NMKgwqDCoCDCoMKgwqAgwqDCoMKgIMKgwqDCoCDCoMKgwqAgwqDCoMKgwqAgwqDCoMKg IHBjX3ZhbHVlc1szXTsKPj4gfTsKPj4KPj4gY29uc3Qgc3RydWN0IG15X2FsbG93ZWRfcGNzwqDC oMKgIG15X2FsbG93ZWRfcGNzID0gewo+PiDCoMKgwqAgeyAzLCAwIH0sCj4+IMKgwqDCoCAodWlu dHB0cl90KSBmZmlfY2xvc3VyZV91bml4NjRfc3NlLAo+PiDCoMKgwqAgKHVpbnRwdHJfdCkgZmZp X2Nsb3N1cmVfdW5peDY0LAo+PiDCoMKgwqAgKHVpbnRwdHJfdCkgZmZpX2Nsb3N1cmVfd2luNjQs Cj4+IH07Cj4+Cj4+IEkgaGF2ZSBjcmVhdGVkIGEgcmVhZC1vbmx5IGFycmF5IG9mIGFsbG93ZWQg QUJJIGhhbmRsZXJzIHRoYXQgY2xvc3VyZXMgdXNlLgo+Pgo+PiBXaGVuIEkgc2V0IHVwIHRoZSBj b250ZXh0IGZvciBhIGNsb3N1cmUgdHJhbXBvbGluZSwgSSBjb3VsZCBkbyB0aGlzOgo+Pgo+PiDC oMKgwqAgcHdyaXRlKHRyYW1wZmQsICZteV9hbGxvd2VkX3Bjcywgc2l6ZW9mKG15X2FsbG93ZWRf cGNzKSwgVFJBTVBGRF9BTExPV0VEX1BDU19PRkZTRVQpOwo+PiDCoMKgwqAKPj4gVGhpcyBjb3Bp ZXMgdGhlIGFycmF5IGludG8gdGhlIHRyYW1wb2xpbmUgb2JqZWN0IGluIHRoZSBrZXJuZWwuCj4+ IFdoZW4gdGhlIHJlZ2lzdGVyIGNvbnRleHQgaXMgc2V0IGZvciB0aGUgdHJhbXBvbGluZSwgdGhl IGtlcm5lbCBjaGVja3MKPj4gdGhlIFBDIHJlZ2lzdGVyIHZhbHVlIGFnYWluc3QgYWxsb3dlZCBQ Q3MuCj4+Cj4+IEJlY2F1c2UgbXlfYWxsb3dlZF9wY3MgaXMgcmVhZC1vbmx5LCBhIGhhY2tlciBj YW5ub3QgbW9kaWZ5IGl0LiBTbywgdGhlIG9ubHkKPj4gcGVybWl0dGVkIHRhcmdldCBQQ3MgZW5m b3JjZWQgYnkgdGhlIGtlcm5lbCBhcmUgdGhlIEFCSSBoYW5kbGVycy4KPiBTb3JyeSwgd2hlbiBJ IHNhaWQgInN0YXRpY2FsbHkgZGVmaW5lIiBtZWFudCB3aGVuIHlvdSBrbmV3IGxlZ2l0aW1hdGUK PiB0YXJnZXRzIGFoZWFkIG9mIHRpbWUgd2hlbiB5b3UgY3JlYXRlIHRoZSB0cmFtcG9saW5lIChp LmUuIHdoZXRoZXIgeW91Cj4gY291bGQgZW51bWVyYXRlIHRob3NlIGFuZCBrbm93IHRoZXkgd291 bGQgbm90IGNoYW5nZSBkeW5hbWljYWxseSkuCj4KPiBNeSBwb2ludCB3YXMgdGhhdCB5b3UgY2Fu IGFjaGlldmUgdGhlIHNhbWUgaW4gdXNlcnNwYWNlIGlmIHRoZQo+IHRyYW1wb2xpbmUgYW5kIGFy cmF5IG9mIGxlZ2l0aW1hdGUgdGFyZ2V0cyBhcmUgaW4gcmVhZC1vbmx5IG1lbW9yeSwKPiB3aXRo b3V0IGhhdmluZyB0byB0cmFwIHRvIHRoZSBrZXJuZWwuCj4KPiBJIHRoaW5rIHRoZSBrZXkgcG9p bnQgaGVyZSBpcyB0aGF0IGFuIGFkdmVyc2FyeSBtdXN0IGJlIHByZXZlbnRlZCBmcm9tCj4gYWx0 ZXJpbmcgYSB0cmFtcG9saW5lIGFuZCBhbnkgYXNzb2NpYXRlZCBtZXRhZGF0YSwgYW5kIEkgdGhp bmsgdGhhdAo+IHRoZXJlIGFyZSB3YXlzIG9mIGFjaGlldmluZyB0aGF0IHdpdGhvdXQgaGF2aW5n IHRvIHRyYXAgaW50byB0aGUga2VybmVsLAo+IGFuZCB3aXRob3V0IHRoZSBrZXJuZWwgaGF2aW5n IHRvIGJlIGludGltYXRlbHkgYXdhcmUgb2YgdGhlIGNhbGxpbmcKPiBjb252ZW50aW9ucyB1c2Vk IGluIHVzZXJzcGFjZS4KPgo+IFsuLi5dCj4KPj4+PiBUcmFtcGZkIGlzIGEgZnJhbWV3b3JrIHRo YXQgY2FuIGJlIHVzZWQgdG8gaW1wbGVtZW50IG11bHRpcGxlIHRoaW5ncy4gTWF5IGJlLAo+Pj4+ IGEgZmV3IG9mIHRob3NlIHRoaW5ncyBjYW4gYWxzbyBiZSBpbXBsZW1lbnRlZCBpbiB1c2VyIGxh bmQgaXRzZWxmLiBCdXQgSSB0aGluayBoYXZpbmcKPj4+PiBqdXN0IG9uZSBtZWNoYW5pc20gdG8g ZXhlY3V0ZSBkeW5hbWljIGNvZGUgb2JqZWN0cyBpcyBwcmVmZXJhYmxlIHRvIGhhdmluZwo+Pj4+ IG11bHRpcGxlIG1lY2hhbmlzbXMgbm90IHN0YW5kYXJkaXplZCBhY3Jvc3MgYWxsIGFwcGxpY2F0 aW9ucy4KPj4+IEluIGFic3RyYWN0LCBoYXZpbmcgYSBjb21tb24gaW50ZXJmYWNlIHNvdW5kcyBu aWNlLCBidXQgaW4gcHJhY3RpY2UKPj4+IGVsZW1lbnRzIG9mIHRoaXMgYXJlIGFsd2F5cyBhcmNo aXRlY3R1cmUtc3BlY2lmaWMgKGUuZy4gaW50ZXJhY3Rpb3NuCj4+PiB3aXRoIEhXIENGSSksIGFu ZCB0aGF0IGNvbW1vbiBpbnRlcmZhY2UgY2FuIHJlc3VsdCBpbiBtb3JlIHBhaW4gYXMgaXQKPj4+ IGRvZXNuJ3QgZml0IG5hdHVyYWxseSBpbnRvIHRoZSBjb250ZXh0IHRoYXQgSVNBcyB3ZXJlIGRl c2lnbmVkIGZvciAoZS5nLiAKPj4+IHdoZXJlIGNvbnRyb2wtZmxvdyBpbnN0cnVjdGlvbnMgYXJl IGV4dGVuZGVkIHdpdGggbmV3IHNlbWFudGljcykuCj4+IEluIHRoZSBjYXNlIG9mIHRyYW1wZmQs IHRoZSBjb2RlIGdlbmVyYXRpb24gaXMgaW5kZWVkIGFyY2hpdGVjdHVyZQo+PiBzcGVjaWZpYy4g QnV0IHRoYXQgaXMgaW4gdGhlIGtlcm5lbC4gVGhlIGFwcGxpY2F0aW9uIGlzIG5vdCBhZmZlY3Rl ZCBieSBpdC4KPiBBcyBhbiBBQkkgZGV0YWlsLCBhcHBsaWNhdGlvbnMgYXJlICpkZWZpbml0ZWx5 KiBhZmZlY3RlZCBieSB0aGlzLCBhbmQgaXQKPiBpcyB3cm9uZyB0byBzdWdnZXN0IHRoZXkgYXJl IG5vdCBldmVuIGlmIHlvdSBkb24ndCBoYXZlIGEgc3BlY2lmaWMgY2FzZQo+IGluIG1pbmQgdG9k YXkuIEFzIHRoaXMgZm9ybXMgYSBjb250cmFjdCBiZXR3ZWVuIHVzZXJzcGFjZSBhbmQgdGhlIGtl cm5lbAo+IGl0J3Mgb3Zlcmx5IHNpbXBsaXN0aWMgdG8gc2F5IHRoYXQgaXQncyB0aGUga2VybmVs J3MgcHJvYmxlbQo+Cj4gRm9yIGV4YW1wbGUsIGluIHRoZSBjYXNlIG9mIEJUSSBvbiBhcm02NCwg d2hhdCBzaG91bGQgdGhlIHRyYW1wb2xpbmUKPiBzZXQgUFNUQVRFLkJUWVBFIHRvPyBEaWZmZXJl bnQgdXNlLWNhc2VzICp3aWxsKiB3YW50IGRpZmZlcmVudCB2YWx1ZXMsCj4gYW5kIG5vdCBuZWNl c3NhcmlseSB0aGUgdmFsdWUgb2YgUFNUQVRFIGF0IHRoZSBpbnN0YW50IHRoZSBjYWxsIHRvIHRo ZQo+IHRyYW1wb2xpbmUgd2FzIG1hZGUuIEluIHRoZSBjYXNlIG9mIGxpYmZmaSBzcGVjaWZpY2Fs bHkgdXNpbmcgdGhlCj4gb3JpZ2luYWwgdmFsdWUgb2YgUFNUQVRFLkJUWVBFIHByb2JhYmx5IGlz IHNvdW5kLCBidXQgb3RoZXIgY29kZQo+IHNlcXVlbmNlcyBtYXkgbmVlZCB0byByZXN0cmljdC9i cm9hZGVuIG9yIGVudGlyZWx5IGNoYW5nZSB0aGF0Lgo+Cj4+IEFnYWluLCByZWZlcnJpbmcgdG8g dGhlIGxpYmZmaSByZWZlcmVuY2UgcGF0Y2gsIEkgaGF2ZSBkZWZpbmVkIHdyYXBwZXIKPj4gZnVu Y3Rpb25zIGZvciB0cmFtcGZkIGluIGNvbW1vbiBjb2RlLiBUaGUgYXJjaGl0ZWN0dXJlIHNwZWNp ZmljIGNvZGUKPj4gaW4gbGliZmZpIG9ubHkgY2FsbHMgdGhlIHNldF9jb250ZXh0IGZ1bmN0aW9u IGRlZmluZWQgaW4gY29tbW9uIGNvZGUuCj4+IEV2ZW4gdGhpcyBpcyByZXF1aXJlZCBvbmx5IGJl Y2F1c2UgcmVnaXN0ZXIgbmFtZXMgYXJlIHNwZWNpZmljIHRvIGVhY2gKPj4gYXJjaGl0ZWN0dXJl IGFuZCB0aGUgdGFyZ2V0IFBDICh0byB0aGUgQUJJIGhhbmRsZXIpIGlzIHNwZWNpZmljIHRvCj4+ IGVhY2ggYXJjaGl0ZWN0dXJlLUFCSSBjb21iby4KPj4KPj4+IEl0IGFsc28gbWVhc3MgdGhhdCB5 b3UgY2FuJ3Qgc2hhcmUgdGhlIHJvdWdoIGFwcHJvYWNoIGFjcm9zcyBPU3Mgd2hpY2gKPj4+IGRv IG5vdCBpbXBsZW1lbnQgYW4gaWRlbnRpY2FsIG1lY2hhbmlzbSwgc28gZm9yIGNvZGUgYWJzdHJh Y3RpbmcgYnkgSVNBCj4+PiBmaXJzdCwgdGhlbiBieSBwbGF0Zm9ybS9BQkksIHRoZXJlIGlzbid0 IG11Y2ggc2F2aW5nLgo+PiBXaHkgY2FuIHlvdSBub3Qgc2hhcmUgdGhlIHNhbWUgYXBwcm9hY2gg YWNyb3NzIE9TZXM/IEluIGZhY3QsCj4+IEkgaGF2ZSB0cmllZCB0byBkZXNpZ24gaXQgc28gdGhh dCBvdGhlciBPU2VzIGNhbiB1c2UgdGhlIHNhbWUKPj4gbWVjaGFuaXNtLgo+IFN1cmUsIGJ1dCB3 aGVyZSB0aGV5ICpkb24ndCosIHlvdSBtdXN0IGZhbGwgYmFjayB0byB0aGUgZXhpc3RpbmcKPiBw dXJlbHktdXNlcnNwYWNlIG1lY2hhbmlzbXMsIGFuZCBzbyBhIGNvZGViYXNlIG5vdyBoYXMgdGhl IGJ1cmRlbiBvZgo+IG1haW50YWluaW5nIHR3byBkaXN0aW5jdCBtZWNoYW5pc21zLgo+Cj4gV2hl cmVhcyBpZiB0aGVyZSdzIGEgd2F5IG9mIGRvaW5nIHRoaXMgaW4gdXNlcnNwYWNlIHdpdGggKHN0 cm9uZ2VyKQo+IGVuZm9yY2VtZW50IG9mIG1lbW9yeSBwZXJtaXNzaW9ucyB0aGUgdHJhbXBvbGlu ZSBjb2RlIGNhbiBiZSBjb21tb24gZm9yCj4gd2hlbiB0aGlzIGlzIHByZXNlbnQgb3IgYWJzZW50 LCB3aGljaCBpcyBtdWNoIGVhc2llciBmb3IgYSBjb2RlYmFzZSBydG8KPiBtYWludGFpbiwgYW5k IGNvdWxkIG1ha2UgdXNlIG9mIHdlYWtlciBleGlzdGluZyBtZWNoYW5pc21zIHRvIGltcHJvdmUK PiB0aGUgc2l0dWF0aW9uIG9uIHN5c3RlbXMgd2l0aG91dCB0aGUgbmV3IGZ1bmN0aW9uYWxpdHku Cj4KPiBUaGFua3MsCj4gTWFyay4KCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2Vy bmVsQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1h bi9saXN0aW5mby9saW51eC1hcm0ta2VybmVsCg==