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=-4.0 required=3.0 tests=BAYES_00, 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 8D3F5C433E3 for ; Tue, 4 Aug 2020 13:56:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7982C21744 for ; Tue, 4 Aug 2020 13:56:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728605AbgHDN4K (ORCPT ); Tue, 4 Aug 2020 09:56:10 -0400 Received: from foss.arm.com ([217.140.110.172]:44226 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726897AbgHDN4J (ORCPT ); Tue, 4 Aug 2020 09:56:09 -0400 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 987D431B; Tue, 4 Aug 2020 06:56:08 -0700 (PDT) Received: from C02TD0UTHF1T.local (unknown [10.57.37.104]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 585463F718; Tue, 4 Aug 2020 06:56:06 -0700 (PDT) Date: Tue, 4 Aug 2020 14:55:58 +0100 From: Mark Rutland To: "Madhavan T. Venkataraman" Cc: Andy Lutomirski , Kernel Hardening , Linux API , linux-arm-kernel , Linux FS Devel , linux-integrity , LKML , LSM List , Oleg Nesterov , X86 ML Subject: Re: [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor Message-ID: <20200804135558.GA7440@C02TD0UTHF1T.local> 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> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <86625441-80f3-2909-2f56-e18e2b60957d@linux.microsoft.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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=-4.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,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 099B2C433DF for ; Tue, 4 Aug 2020 13:57:35 +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 BD7152086A for ; Tue, 4 Aug 2020 13:57:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="BnAz+7S7" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BD7152086A 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+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:References:Message-ID: Subject:To:From:Date:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=seSjTTo8zGVrWUVr/oHNhjIVzBgKgJm76PoOJoThS9w=; b=BnAz+7S7H8Dy8j2GeVyUIxkHg G/jiIloCWdWVn7JvEgbG6kqa2D+YNkSRIuOvLU6x6LSUs/f4NnBbqANAcQ7gKY7/GeJg1krRBwOvc /9POrI5afBY0cAfU9qwiXZpjNsOSNopxvzI0SGLYkhODDSaksFa3wdik/HVRdqpl//lHnxM0Q2mFr v1lIEOd7q/9L8nFjC+MZuN0PdJfhGrmVP49FUkx8obEMic5N7gxRDbpLGmN0Oz5HFQTeGI+xx0KOI cbftBQlRROpxBZ15ovsqFuKb5SQnJzXl+u+OUOKZ4bOp/pK182HpPLn4Py5G2Ww1e9mnjVH0gyGqX 2uh29/wWA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1k2xQK-0000Ux-QF; Tue, 04 Aug 2020 13:56:12 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1k2xQH-0000U9-TJ for linux-arm-kernel@lists.infradead.org; Tue, 04 Aug 2020 13:56:10 +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 987D431B; Tue, 4 Aug 2020 06:56:08 -0700 (PDT) Received: from C02TD0UTHF1T.local (unknown [10.57.37.104]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 585463F718; Tue, 4 Aug 2020 06:56:06 -0700 (PDT) Date: Tue, 4 Aug 2020 14:55:58 +0100 From: Mark Rutland To: "Madhavan T. Venkataraman" Subject: Re: [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor Message-ID: <20200804135558.GA7440@C02TD0UTHF1T.local> 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> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <86625441-80f3-2909-2f56-e18e2b60957d@linux.microsoft.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200804_095610_060780_2C0E7D7D X-CRM114-Status: GOOD ( 46.56 ) 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 T24gTW9uLCBBdWcgMDMsIDIwMjAgYXQgMTI6NTg6MDRQTSAtMDUwMCwgTWFkaGF2YW4gVC4gVmVu a2F0YXJhbWFuIHdyb3RlOgo+IE9uIDcvMzEvMjAgMTozMSBQTSwgTWFyayBSdXRsYW5kIHdyb3Rl Ogo+ID4gT24gRnJpLCBKdWwgMzEsIDIwMjAgYXQgMTI6MTM6NDlQTSAtMDUwMCwgTWFkaGF2YW4g VC4gVmVua2F0YXJhbWFuIHdyb3RlOgo+ID4+IE9uIDcvMzAvMjAgMzo1NCBQTSwgQW5keSBMdXRv bWlyc2tpIHdyb3RlOgo+ID4+PiBPbiBUaHUsIEp1bCAzMCwgMjAyMCBhdCA3OjI0IEFNIE1hZGhh dmFuIFQuIFZlbmthdGFyYW1hbgo+ID4+PiA8bWFkdmVua2FAbGludXgubWljcm9zb2Z0LmNvbT4g d3JvdGU6Cj4+ID4+IFdoZW4gdGhlIGtlcm5lbCBnZW5lcmF0ZXMgdGhlIGNvZGUgZm9yIGEgdHJh bXBvbGluZSwgaXQgY2FuIGhhcmQgY29kZSBkYXRhIHZhbHVlcwo+ID4+IGluIHRoZSBnZW5lcmF0 ZWQgY29kZSBpdHNlbGYgc28gaXQgZG9lcyBub3QgbmVlZCBQQy1yZWxhdGl2ZSBkYXRhIHJlZmVy ZW5jaW5nLgo+ID4+Cj4gPj4gQW5kLCBmb3IgSVNBcyB0aGF0IGRvIHN1cHBvcnQgdGhlIGxhcmdl IG9mZnNldCwgd2UgZG8gaGF2ZSB0byBpbXBsZW1lbnQgYW5kCj4gPj4gbWFpbnRhaW4gdGhlIGNv ZGUgcGFnZSBzdHVmZiBmb3IgZGlmZmVyZW50IElTQXMgZm9yIGVhY2ggYXBwbGljYXRpb24gYW5k IGxpYnJhcnkKPiA+PiBpZiB3ZSBkaWQgbm90IHVzZSB0cmFtcGZkLgo+ID4gVHJhbXBvbGluZSBj b2RlIGlzIGFyY2hpdGVjdHVyZSBzcGVjaWZpYyB0b2RheSwgc28gSSBkb24ndCBzZWUgdGhhdCBh cyBhCj4gPiBtYWpvciBpc3N1ZS4gQ29tbW9uIHN0cnVjdHVyYWwgYml0cyBjYW4gcHJvYmFibHkg YmUgc2hhcmVkIGV2ZW4gaWYgdGhlCj4gPiBzcGVjaWZpZCBtYWNoaW5lIGNvZGUgY2Fubm90Lgo+ IAo+IFRydWUuIEJ1dCBhbiBpbXBsZW1lbnRvciBtYXkgcHJlZmVyIGEgc3RhbmRhcmQgbWVjaGFu aXNtIHByb3ZpZGVkIGJ5Cj4gdGhlIGtlcm5lbCBzbyBhbGwgb2YgaGlzIGFyY2hpdGVjdHVyZXMg Y2FuIGJlIHN1cHBvcnRlZCBlYXNpbHkgd2l0aCBsZXNzCj4gZWZmb3J0Lgo+IAo+IElmIHlvdSBs b29rIGF0IHRoZSBsaWJmZmkgcmVmZXJlbmNlIHBhdGNoIEkgaGF2ZSBpbmNsdWRlZCwgdGhlIGFy Y2hpdGVjdHVyZQo+IHNwZWNpZmljIGNoYW5nZXMgdG8gdXNlIHRyYW1wZmQganVzdCBpbnZvbHZl IGEgc2luZ2xlIEMgZnVuY3Rpb24gY2FsbCB0bwo+IGEgY29tbW9uIGNvZGUgZnVuY3Rpb24uCgpT dXJlIGJ1dCBpbiBhZGRpdGlvbiB0byB0aGF0IGVhY2ggYXJjaGl0ZWN0dXJlIGJhY2tlbmQgaGFk IHRvIGRlZmluZSBhCnNldCBvZiBhcmd1bWVudHMgdG8gdGhhdC4gSSB2aWV3IHRoZSBDIGZ1bmN0 aW9uIGlzIGFuYWxhZ291cyB0byB0aGUKImNvbW1vbiBzdHJ1Y3R1cmFsIGJpdHMiLgoKSSBhcHBy ZWNpYXRlIHRoYXQgeW91ciBwYXRjaCBpcyBzbWFsbCB0b2RheSAoYW5kIGFyY2hpdGVjdHVyZXMg c2VlbSB0bwpsYXJnZWx5IGFsaWduIG9uIHdoYXQgdGhleSBuZWVkKSwgYnV0IEkgZG9uJ3QgdGhp bmsgaXQncyBuZWNlc3NhcmlseQp0cnVlIHRoYXQgdGhpbmdzIHdpbGwgcmVtYWluIHNvIHNpbXBs ZSBhcyBhcmNoaXRlY3R1cmUgYXJlIGV4dGVuZGVkIGFuZAp0aGVpciBjYWxsaW5nIGNvbnZlbnRp b25zIGV2b2x2ZSwgYW5kIEkgYWxzbyBkb24ndCB0aGluayBpdCdzIGNsZWFyIHRoYXQKdGhpcyB3 aWxsIHdvcmsgZm9yIG1vcmUgY29tcGxleCBjYXNlcyBlbHNld2hlcmUuCgpbLi4uXQoKPiA+PiBX aXRoIHRoZSB1c2VyIGxldmVsIHRyYW1wb2xpbmUgdGFibGUgYXBwcm9hY2gsIHRoZSBkYXRhIHBh cnQgb2YgdGhlIHRyYW1wb2xpbmUgdGFibGUKPiA+PiBjYW4gYmUgaGFja2VkIGJ5IGFuIGF0dGFj a2VyIGlmIGFuIGFwcGxpY2F0aW9uIGhhcyBhIHZ1bG5lcmFiaWxpdHkuIFNwZWNpZmljYWxseSwg dGhlCj4gPj4gdGFyZ2V0IFBDIGNhbiBiZSBhbHRlcmVkIHRvIHNvbWUgYXJiaXRyYXJ5IGxvY2F0 aW9uLiBUcmFtcGZkIGltcGxlbWVudHMgYW4KPiA+PiAiQWxsb3dlZCBQQ1MiIGNvbnRleHQuIElu IHRoZSBsaWJmZmkgY2hhbmdlcywgSSBoYXZlIGNyZWF0ZWQgYSByZWFkLW9ubHkgYXJyYXkgb2YK PiA+PiBhbGwgQUJJIGhhbmRsZXJzIHVzZWQgaW4gY2xvc3VyZXMgZm9yIGVhY2ggYXJjaGl0ZWN0 dXJlLiBUaGlzIHJlYWQtb25seSBhcnJheQo+ID4+IGNhbiBiZSB1c2VkIHRvIHJlc3RyaWN0IHRo ZSBQQyB2YWx1ZXMgZm9yIGxpYmZmaSB0cmFtcG9saW5lcyB0byBwcmV2ZW50IGhhY2tpbmcuCj4g Pj4KPiA+PiBUbyBnZW5lcmFsaXplLCB3ZSBjYW4gaW1wbGVtZW50IHNlY3VyaXR5IHJ1bGVzL2Zl YXR1cmVzIGlmIHRoZSB0cmFtcG9saW5lCj4gPj4gb2JqZWN0IGlzIGluIHRoZSBrZXJuZWwuCj4g PiBJIGRvbid0IGZvbGxvdyB0aGlzIGFyZ3VtZW50LiBJZiBpdCdzIHBvc3NpYmxlIHRvIHN0YXRp Y2FsbHkgZGVmaW5lIHRoYXQKPiA+IGluIHRoZSBrZXJuZWwsIGl0J3MgYWxzbyBwb3NzaWJsZSB0 byBkbyB0aGF0IGluIHVzZXJzcGFjZSB3aXRob3V0IGFueQo+ID4gbmV3IGtlcm5lbCBzdXBwb3J0 Lgo+IEl0IGlzIG5vdCBzdGF0aWNhbGx5IGRlZmluZWQgaW4gdGhlIGtlcm5lbC4KPiAKPiBMZXQg dXMgdGFrZSB0aGUgbGliZmZpIGV4YW1wbGUuIEluIHRoZSA2NC1iaXQgWDg2IGFyY2ggY29kZSwg dGhlcmUgYXJlIDMKPiBBQkkgaGFuZGxlcnM6Cj4gCj4gwqDCoMKgIGZmaV9jbG9zdXJlX3VuaXg2 NF9zc2UKPiDCoMKgwqAgZmZpX2Nsb3N1cmVfdW5peDY0Cj4gwqDCoMKgIGZmaV9jbG9zdXJlX3dp bjY0Cj4gCj4gSSBjb3VsZCBjcmVhdGUgYW4gIkFsbG93ZWQgUENzIiBjb250ZXh0IGxpa2UgdGhp czoKPiAKPiBzdHJ1Y3QgbXlfYWxsb3dlZF9wY3Mgewo+IMKgwqDCoCBzdHJ1Y3QgdHJhbXBmZF92 YWx1ZXMgwqDCoCBwY3M7Cj4gwqDCoMKgIF9fdTY0wqDCoMKgIMKgwqDCoCDCoMKgwqAgwqDCoMKg IMKgwqDCoCDCoMKgwqDCoCDCoMKgwqAgcGNfdmFsdWVzWzNdOwo+IH07Cj4gCj4gY29uc3Qgc3Ry dWN0IG15X2FsbG93ZWRfcGNzwqDCoMKgIG15X2FsbG93ZWRfcGNzID0gewo+IMKgwqDCoCB7IDMs IDAgfSwKPiDCoMKgwqAgKHVpbnRwdHJfdCkgZmZpX2Nsb3N1cmVfdW5peDY0X3NzZSwKPiDCoMKg wqAgKHVpbnRwdHJfdCkgZmZpX2Nsb3N1cmVfdW5peDY0LAo+IMKgwqDCoCAodWludHB0cl90KSBm ZmlfY2xvc3VyZV93aW42NCwKPiB9Owo+IAo+IEkgaGF2ZSBjcmVhdGVkIGEgcmVhZC1vbmx5IGFy cmF5IG9mIGFsbG93ZWQgQUJJIGhhbmRsZXJzIHRoYXQgY2xvc3VyZXMgdXNlLgo+IAo+IFdoZW4g SSBzZXQgdXAgdGhlIGNvbnRleHQgZm9yIGEgY2xvc3VyZSB0cmFtcG9saW5lLCBJIGNvdWxkIGRv IHRoaXM6Cj4gCj4gwqDCoMKgIHB3cml0ZSh0cmFtcGZkLCAmbXlfYWxsb3dlZF9wY3MsIHNpemVv ZihteV9hbGxvd2VkX3BjcyksIFRSQU1QRkRfQUxMT1dFRF9QQ1NfT0ZGU0VUKTsKPiDCoMKgwqAK PiBUaGlzIGNvcGllcyB0aGUgYXJyYXkgaW50byB0aGUgdHJhbXBvbGluZSBvYmplY3QgaW4gdGhl IGtlcm5lbC4KPiBXaGVuIHRoZSByZWdpc3RlciBjb250ZXh0IGlzIHNldCBmb3IgdGhlIHRyYW1w b2xpbmUsIHRoZSBrZXJuZWwgY2hlY2tzCj4gdGhlIFBDIHJlZ2lzdGVyIHZhbHVlIGFnYWluc3Qg YWxsb3dlZCBQQ3MuCj4gCj4gQmVjYXVzZSBteV9hbGxvd2VkX3BjcyBpcyByZWFkLW9ubHksIGEg aGFja2VyIGNhbm5vdCBtb2RpZnkgaXQuIFNvLCB0aGUgb25seQo+IHBlcm1pdHRlZCB0YXJnZXQg UENzIGVuZm9yY2VkIGJ5IHRoZSBrZXJuZWwgYXJlIHRoZSBBQkkgaGFuZGxlcnMuCgpTb3JyeSwg d2hlbiBJIHNhaWQgInN0YXRpY2FsbHkgZGVmaW5lIiBtZWFudCB3aGVuIHlvdSBrbmV3IGxlZ2l0 aW1hdGUKdGFyZ2V0cyBhaGVhZCBvZiB0aW1lIHdoZW4geW91IGNyZWF0ZSB0aGUgdHJhbXBvbGlu ZSAoaS5lLiB3aGV0aGVyIHlvdQpjb3VsZCBlbnVtZXJhdGUgdGhvc2UgYW5kIGtub3cgdGhleSB3 b3VsZCBub3QgY2hhbmdlIGR5bmFtaWNhbGx5KS4KCk15IHBvaW50IHdhcyB0aGF0IHlvdSBjYW4g YWNoaWV2ZSB0aGUgc2FtZSBpbiB1c2Vyc3BhY2UgaWYgdGhlCnRyYW1wb2xpbmUgYW5kIGFycmF5 IG9mIGxlZ2l0aW1hdGUgdGFyZ2V0cyBhcmUgaW4gcmVhZC1vbmx5IG1lbW9yeSwKd2l0aG91dCBo YXZpbmcgdG8gdHJhcCB0byB0aGUga2VybmVsLgoKSSB0aGluayB0aGUga2V5IHBvaW50IGhlcmUg aXMgdGhhdCBhbiBhZHZlcnNhcnkgbXVzdCBiZSBwcmV2ZW50ZWQgZnJvbQphbHRlcmluZyBhIHRy YW1wb2xpbmUgYW5kIGFueSBhc3NvY2lhdGVkIG1ldGFkYXRhLCBhbmQgSSB0aGluayB0aGF0CnRo ZXJlIGFyZSB3YXlzIG9mIGFjaGlldmluZyB0aGF0IHdpdGhvdXQgaGF2aW5nIHRvIHRyYXAgaW50 byB0aGUga2VybmVsLAphbmQgd2l0aG91dCB0aGUga2VybmVsIGhhdmluZyB0byBiZSBpbnRpbWF0 ZWx5IGF3YXJlIG9mIHRoZSBjYWxsaW5nCmNvbnZlbnRpb25zIHVzZWQgaW4gdXNlcnNwYWNlLgoK Wy4uLl0KCj4gPj4gVHJhbXBmZCBpcyBhIGZyYW1ld29yayB0aGF0IGNhbiBiZSB1c2VkIHRvIGlt cGxlbWVudCBtdWx0aXBsZSB0aGluZ3MuIE1heSBiZSwKPiA+PiBhIGZldyBvZiB0aG9zZSB0aGlu Z3MgY2FuIGFsc28gYmUgaW1wbGVtZW50ZWQgaW4gdXNlciBsYW5kIGl0c2VsZi4gQnV0IEkgdGhp bmsgaGF2aW5nCj4gPj4ganVzdCBvbmUgbWVjaGFuaXNtIHRvIGV4ZWN1dGUgZHluYW1pYyBjb2Rl IG9iamVjdHMgaXMgcHJlZmVyYWJsZSB0byBoYXZpbmcKPiA+PiBtdWx0aXBsZSBtZWNoYW5pc21z IG5vdCBzdGFuZGFyZGl6ZWQgYWNyb3NzIGFsbCBhcHBsaWNhdGlvbnMuCj4gPiBJbiBhYnN0cmFj dCwgaGF2aW5nIGEgY29tbW9uIGludGVyZmFjZSBzb3VuZHMgbmljZSwgYnV0IGluIHByYWN0aWNl Cj4gPiBlbGVtZW50cyBvZiB0aGlzIGFyZSBhbHdheXMgYXJjaGl0ZWN0dXJlLXNwZWNpZmljIChl LmcuIGludGVyYWN0aW9zbgo+ID4gd2l0aCBIVyBDRkkpLCBhbmQgdGhhdCBjb21tb24gaW50ZXJm YWNlIGNhbiByZXN1bHQgaW4gbW9yZSBwYWluIGFzIGl0Cj4gPiBkb2Vzbid0IGZpdCBuYXR1cmFs bHkgaW50byB0aGUgY29udGV4dCB0aGF0IElTQXMgd2VyZSBkZXNpZ25lZCBmb3IgKGUuZy4gCj4g PiB3aGVyZSBjb250cm9sLWZsb3cgaW5zdHJ1Y3Rpb25zIGFyZSBleHRlbmRlZCB3aXRoIG5ldyBz ZW1hbnRpY3MpLgo+IAo+IEluIHRoZSBjYXNlIG9mIHRyYW1wZmQsIHRoZSBjb2RlIGdlbmVyYXRp b24gaXMgaW5kZWVkIGFyY2hpdGVjdHVyZQo+IHNwZWNpZmljLiBCdXQgdGhhdCBpcyBpbiB0aGUg a2VybmVsLiBUaGUgYXBwbGljYXRpb24gaXMgbm90IGFmZmVjdGVkIGJ5IGl0LgoKQXMgYW4gQUJJ IGRldGFpbCwgYXBwbGljYXRpb25zIGFyZSAqZGVmaW5pdGVseSogYWZmZWN0ZWQgYnkgdGhpcywg YW5kIGl0CmlzIHdyb25nIHRvIHN1Z2dlc3QgdGhleSBhcmUgbm90IGV2ZW4gaWYgeW91IGRvbid0 IGhhdmUgYSBzcGVjaWZpYyBjYXNlCmluIG1pbmQgdG9kYXkuIEFzIHRoaXMgZm9ybXMgYSBjb250 cmFjdCBiZXR3ZWVuIHVzZXJzcGFjZSBhbmQgdGhlIGtlcm5lbAppdCdzIG92ZXJseSBzaW1wbGlz dGljIHRvIHNheSB0aGF0IGl0J3MgdGhlIGtlcm5lbCdzIHByb2JsZW0KCkZvciBleGFtcGxlLCBp biB0aGUgY2FzZSBvZiBCVEkgb24gYXJtNjQsIHdoYXQgc2hvdWxkIHRoZSB0cmFtcG9saW5lCnNl dCBQU1RBVEUuQlRZUEUgdG8/IERpZmZlcmVudCB1c2UtY2FzZXMgKndpbGwqIHdhbnQgZGlmZmVy ZW50IHZhbHVlcywKYW5kIG5vdCBuZWNlc3NhcmlseSB0aGUgdmFsdWUgb2YgUFNUQVRFIGF0IHRo ZSBpbnN0YW50IHRoZSBjYWxsIHRvIHRoZQp0cmFtcG9saW5lIHdhcyBtYWRlLiBJbiB0aGUgY2Fz ZSBvZiBsaWJmZmkgc3BlY2lmaWNhbGx5IHVzaW5nIHRoZQpvcmlnaW5hbCB2YWx1ZSBvZiBQU1RB VEUuQlRZUEUgcHJvYmFibHkgaXMgc291bmQsIGJ1dCBvdGhlciBjb2RlCnNlcXVlbmNlcyBtYXkg bmVlZCB0byByZXN0cmljdC9icm9hZGVuIG9yIGVudGlyZWx5IGNoYW5nZSB0aGF0LgoKPiBBZ2Fp biwgcmVmZXJyaW5nIHRvIHRoZSBsaWJmZmkgcmVmZXJlbmNlIHBhdGNoLCBJIGhhdmUgZGVmaW5l ZCB3cmFwcGVyCj4gZnVuY3Rpb25zIGZvciB0cmFtcGZkIGluIGNvbW1vbiBjb2RlLiBUaGUgYXJj aGl0ZWN0dXJlIHNwZWNpZmljIGNvZGUKPiBpbiBsaWJmZmkgb25seSBjYWxscyB0aGUgc2V0X2Nv bnRleHQgZnVuY3Rpb24gZGVmaW5lZCBpbiBjb21tb24gY29kZS4KPiBFdmVuIHRoaXMgaXMgcmVx dWlyZWQgb25seSBiZWNhdXNlIHJlZ2lzdGVyIG5hbWVzIGFyZSBzcGVjaWZpYyB0byBlYWNoCj4g YXJjaGl0ZWN0dXJlIGFuZCB0aGUgdGFyZ2V0IFBDICh0byB0aGUgQUJJIGhhbmRsZXIpIGlzIHNw ZWNpZmljIHRvCj4gZWFjaCBhcmNoaXRlY3R1cmUtQUJJIGNvbWJvLgo+IAo+ID4gSXQgYWxzbyBt ZWFzcyB0aGF0IHlvdSBjYW4ndCBzaGFyZSB0aGUgcm91Z2ggYXBwcm9hY2ggYWNyb3NzIE9TcyB3 aGljaAo+ID4gZG8gbm90IGltcGxlbWVudCBhbiBpZGVudGljYWwgbWVjaGFuaXNtLCBzbyBmb3Ig Y29kZSBhYnN0cmFjdGluZyBieSBJU0EKPiA+IGZpcnN0LCB0aGVuIGJ5IHBsYXRmb3JtL0FCSSwg dGhlcmUgaXNuJ3QgbXVjaCBzYXZpbmcuCj4gCj4gV2h5IGNhbiB5b3Ugbm90IHNoYXJlIHRoZSBz YW1lIGFwcHJvYWNoIGFjcm9zcyBPU2VzPyBJbiBmYWN0LAo+IEkgaGF2ZSB0cmllZCB0byBkZXNp Z24gaXQgc28gdGhhdCBvdGhlciBPU2VzIGNhbiB1c2UgdGhlIHNhbWUKPiBtZWNoYW5pc20uCgpT dXJlLCBidXQgd2hlcmUgdGhleSAqZG9uJ3QqLCB5b3UgbXVzdCBmYWxsIGJhY2sgdG8gdGhlIGV4 aXN0aW5nCnB1cmVseS11c2Vyc3BhY2UgbWVjaGFuaXNtcywgYW5kIHNvIGEgY29kZWJhc2Ugbm93 IGhhcyB0aGUgYnVyZGVuIG9mCm1haW50YWluaW5nIHR3byBkaXN0aW5jdCBtZWNoYW5pc21zLgoK V2hlcmVhcyBpZiB0aGVyZSdzIGEgd2F5IG9mIGRvaW5nIHRoaXMgaW4gdXNlcnNwYWNlIHdpdGgg KHN0cm9uZ2VyKQplbmZvcmNlbWVudCBvZiBtZW1vcnkgcGVybWlzc2lvbnMgdGhlIHRyYW1wb2xp bmUgY29kZSBjYW4gYmUgY29tbW9uIGZvcgp3aGVuIHRoaXMgaXMgcHJlc2VudCBvciBhYnNlbnQs IHdoaWNoIGlzIG11Y2ggZWFzaWVyIGZvciBhIGNvZGViYXNlIHJ0bwptYWludGFpbiwgYW5kIGNv dWxkIG1ha2UgdXNlIG9mIHdlYWtlciBleGlzdGluZyBtZWNoYW5pc21zIHRvIGltcHJvdmUKdGhl IHNpdHVhdGlvbiBvbiBzeXN0ZW1zIHdpdGhvdXQgdGhlIG5ldyBmdW5jdGlvbmFsaXR5LgoKVGhh bmtzLApNYXJrLgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X18KbGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5p bmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8v bGludXgtYXJtLWtlcm5lbAo=