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=-13.9 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 29F4BC433DF for ; Thu, 30 Jul 2020 14:42:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 00D7620829 for ; Thu, 30 Jul 2020 14:42:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="fr+aQ6wg" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729428AbgG3Om1 (ORCPT ); Thu, 30 Jul 2020 10:42:27 -0400 Received: from linux.microsoft.com ([13.77.154.182]:52692 "EHLO linux.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726873AbgG3OmZ (ORCPT ); Thu, 30 Jul 2020 10:42:25 -0400 Received: from [192.168.254.32] (unknown [47.187.206.220]) by linux.microsoft.com (Postfix) with ESMTPSA id 447E220B4908; Thu, 30 Jul 2020 07:42:23 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 447E220B4908 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1596120143; bh=JKjym+PetFsYNW9wkVDAjo/yZX3EUJAVDZIUKswMGaQ=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=fr+aQ6wg1KgTGw6nIBKQ+VD8DP0JAdoWoTqnBCw0HXWZsTUfyvrUFPowTbotbg6+R PVwyphPu3guW5xqko6YXK0fQawCA7Fnc48ucO0Im672RcBmUhK33lx+YLAS4Ec/fWH sWTg9Z+ywbm24khHImc0gMC6bx02ZKnhzr1M/S3I= Subject: Re: [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor To: Andy Lutomirski Cc: 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> From: "Madhavan T. Venkataraman" Message-ID: <2352c2b5-053d-fd33-80b0-4f2175dbb607@linux.microsoft.com> Date: Thu, 30 Jul 2020 09:42:22 -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: 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 For some reason my email program is not delivering to all the recipients because of some formatting issues. I am resending. I apologize. I will try to get this fixed. Sorry for the delay. I just needed to think about it a little. I will respond to your first suggestion in this email. I will respond to the others in separate emails if that is alright with you. On 7/28/20 12:31 PM, Andy Lutomirski wrote: >> On Jul 28, 2020, at 6:11 AM, madvenka@linux.microsoft.com wrote: >> >> From: "Madhavan T. Venkataraman" >> >> The kernel creates the trampoline mapping without any permissions. When >> the trampoline is executed by user code, a page fault happens and the >> kernel gets control. The kernel recognizes that this is a trampoline >> invocation. It sets up the user registers based on the specified >> register context, and/or pushes values on the user stack based on the >> specified stack context, and sets the user PC to the requested target >> PC. When the kernel returns, execution continues at the target PC. >> So, the kernel does the work of the trampoline on behalf of the >> application. > This is quite clever, but now I’m wondering just how much kernel help > is really needed. In your series, the trampoline is an non-executable > page. I can think of at least two alternative approaches, and I'd > like to know the pros and cons. > > 1. Entirely userspace: a return trampoline would be something like: > > 1: > pushq %rax > pushq %rbc > pushq %rcx > ... > pushq %r15 > movq %rsp, %rdi # pointer to saved regs > leaq 1b(%rip), %rsi # pointer to the trampoline itself > callq trampoline_handler # see below > > You would fill a page with a bunch of these, possibly compacted to get > more per page, and then you would remap as many copies as needed. The > 'callq trampoline_handler' part would need to be a bit clever to make > it continue to work despite this remapping. This will be *much* > faster than trampfd. How much of your use case would it cover? For > the inverse, it's not too hard to write a bit of asm to set all > registers and jump somewhere. Let me state my understanding of what you are suggesting. Correct me if I get anything wrong. If you don't mind, I will also take the liberty of generalizing and paraphrasing your suggestion. The goal is to create two page mappings that are adjacent to each other: - a code page that contains template code for a trampoline. Since the   template code would tend to be small in size, pack as many of them   as possible within a page to conserve memory. In other words, create   an array of the template code fragments. Each element in the array   would be used for one trampoline instance. - a data page that contains an array of data elements. Corresponding   to each code element in the code page, there would be a data element   in the data page that would contain data that is specific to a   trampoline instance. - Code will access data using PC-relative addressing. The management of the code pages and allocation for each trampoline instance would all be done in user space. Is this the general idea? Creating a code page ---------------------------- We can do this in one of the following ways: - Allocate a writable page at run time, write the template code into   the page and have execute permissions on the page. - Allocate a writable page at run time, write the template code into   the page and remap the page with just execute permissions. - Allocate a writable page at run time, write the template code into   the page, write the page into a temporary file and map the file with   execute permissions. - Include the template code in a code page at build time itself and   just remap the code page each time you need a code page. Pros and Cons ------------------- As long as the OS provides the functionality to do this and the security subsystem in the OS allows the actions, this is totally feasible. If not, we need something like trampfd. As Floren mentioned, libffi does implement something like this for MACH. In fact, in my libffi changes, I use trampfd only after all the other methods have failed because of security settings. But the above approach only solves the problem for this simple type of trampoline. It does not provide a framework for addressing more complex types or even other forms of dynamic code. Also, each application would need to implement this solution for itself as opposed to relying on one implementation provided by the kernel. Trampfd-based solution ------------------------------- I outlined an enhancement to trampfd in a response to David Laight. In this enhancement, the kernel is the one that would set up the code page. The kernel would call an arch-specific support function to generate the code required to load registers, push values on the stack and jump to a PC for a trampoline instance based on its current context. The trampoline instance data could be baked into the code. My initial idea was to only have one trampoline instance per page. But I think I can implement multiple instances per page. I just have to manage the trampfd file private data and VMA private data accordingly to map an element in a code page to its trampoline object. The two approaches are similar except for the detail about who sets up and manages the trampoline pages. In both approaches, the performance problem is addressed. But trampfd can be used even when security settings are restrictive. Is my solution acceptable? A couple of things ------------------------ - In the current trampfd implementation, no physical pages are actually   allocated. It is just a virtual mapping. From a memory footprint   perspective, this is good. May be, we can let the user specify if   he wants a fast trampoline that consumes memory or a slow one that doesn't? - In the future, we may define additional types that need the kernel to do   the job. Examples:     - The kernel may have a trampoline type for which it is not willing        or able to generate code     - The kernel could emulate dynamic code for the user      - The kernel could interpret dynamic code for the user      - The kernel could allow the user to access some kernel functionality         using the framework   In such cases, there isn't any physical code page that gets mapped into   the user address space. We need the kernel to handle the address fault   and provide the functionality. One question for the reviewers ---------------------------------------- Do you think that the file descriptor based approach is fine? Or, does this need a regular system call based implementation? There are some advantages with a regular system call: - We don't consume file descriptors. E.g., in libffi, we have to   keep the file descriptor open for a closure until the closure   is freed. - Trampoline operations can be performed based on the trampoline   address instead of an fd. - Sharing of objects across processes can be implemented through   a regular ID based method rather than sending the file descriptor   over a unix domain socket. - Shared objects can be persistent. - An fd based API does structure parsing in read()/write() calls   to obtain arguments. With a regular system call, that is not   necessary. Please let me know your thoughts. Madhavan 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=-6.3 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 10A06C433DF for ; Thu, 30 Jul 2020 14:44:01 +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 C3CF420829 for ; Thu, 30 Jul 2020 14:44:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Qodty5ZD"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="fr+aQ6wg" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C3CF420829 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=pY4pRGpipVOT0gBzQhjF8VgYZPnMhmCynZVW0CTirbw=; b=Qodty5ZDDOaoh73Fz8RAgYzzO vb15EcN3oOqtxyKauGwm5zP24LTLzSAWsWJrVGX2NSZbY5QFwOfaB9eo3kE4jdzRanOjmGJOs8bjj cG+lQYVsGBJcbTKEFqNmFDoD88d0+FAe1oPffQ6FuiSjqrgm55pKWET5HqQOq9r4dgwiZzy+QAV9d QqkZ37MEUHo/nnw9JKT8f0C7PE0Y5ZlVNPD4gyGf+boGzGx6NCtHELnsC1HBwU0cKuhkz37c67Pb+ +pvo8JZo9PMrGmxZc4N4eHLHHjqwYWDe7AVMMLtWM1WWYCLVwUo8mHIt8bZkLuZBuWcp3Gv2STewr IznKIfMIw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1k19lM-0006Cq-86; Thu, 30 Jul 2020 14:42:28 +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 1k19lI-00064w-Uz for linux-arm-kernel@lists.infradead.org; Thu, 30 Jul 2020 14:42:26 +0000 Received: from [192.168.254.32] (unknown [47.187.206.220]) by linux.microsoft.com (Postfix) with ESMTPSA id 447E220B4908; Thu, 30 Jul 2020 07:42:23 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 447E220B4908 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1596120143; bh=JKjym+PetFsYNW9wkVDAjo/yZX3EUJAVDZIUKswMGaQ=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=fr+aQ6wg1KgTGw6nIBKQ+VD8DP0JAdoWoTqnBCw0HXWZsTUfyvrUFPowTbotbg6+R PVwyphPu3guW5xqko6YXK0fQawCA7Fnc48ucO0Im672RcBmUhK33lx+YLAS4Ec/fWH sWTg9Z+ywbm24khHImc0gMC6bx02ZKnhzr1M/S3I= Subject: Re: [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor To: Andy Lutomirski References: <20200728131050.24443-1-madvenka@linux.microsoft.com> From: "Madhavan T. Venkataraman" Message-ID: <2352c2b5-053d-fd33-80b0-4f2175dbb607@linux.microsoft.com> Date: Thu, 30 Jul 2020 09:42:22 -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: Content-Language: en-US X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200730_104225_131891_2BFDC5BC X-CRM114-Status: GOOD ( 39.71 ) 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 , 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 Rm9yIHNvbWUgcmVhc29uIG15IGVtYWlsIHByb2dyYW0gaXMgbm90IGRlbGl2ZXJpbmcgdG8gYWxs IHRoZQpyZWNpcGllbnRzIGJlY2F1c2Ugb2Ygc29tZSBmb3JtYXR0aW5nIGlzc3Vlcy4gSSBhbSBy ZXNlbmRpbmcuCkkgYXBvbG9naXplLiBJIHdpbGwgdHJ5IHRvIGdldCB0aGlzIGZpeGVkLgoKU29y cnkgZm9yIHRoZSBkZWxheS4gSSBqdXN0IG5lZWRlZCB0byB0aGluayBhYm91dCBpdCBhIGxpdHRs ZS4KSSB3aWxsIHJlc3BvbmQgdG8geW91ciBmaXJzdCBzdWdnZXN0aW9uIGluIHRoaXMgZW1haWwu IEkgd2lsbApyZXNwb25kIHRvIHRoZSBvdGhlcnMgaW4gc2VwYXJhdGUgZW1haWxzIGlmIHRoYXQg aXMgYWxyaWdodAp3aXRoIHlvdS4KCk9uIDcvMjgvMjAgMTI6MzEgUE0sIEFuZHkgTHV0b21pcnNr aSB3cm90ZToKPj4gT24gSnVsIDI4LCAyMDIwLCBhdCA2OjExIEFNLCBtYWR2ZW5rYUBsaW51eC5t aWNyb3NvZnQuY29tIHdyb3RlOgo+Pgo+PiDvu79Gcm9tOiAiTWFkaGF2YW4gVC4gVmVua2F0YXJh bWFuIiA8bWFkdmVua2FAbGludXgubWljcm9zb2Z0LmNvbT4KPj4KPj4gVGhlIGtlcm5lbCBjcmVh dGVzIHRoZSB0cmFtcG9saW5lIG1hcHBpbmcgd2l0aG91dCBhbnkgcGVybWlzc2lvbnMuIFdoZW4K Pj4gdGhlIHRyYW1wb2xpbmUgaXMgZXhlY3V0ZWQgYnkgdXNlciBjb2RlLCBhIHBhZ2UgZmF1bHQg aGFwcGVucyBhbmQgdGhlCj4+IGtlcm5lbCBnZXRzIGNvbnRyb2wuIFRoZSBrZXJuZWwgcmVjb2du aXplcyB0aGF0IHRoaXMgaXMgYSB0cmFtcG9saW5lCj4+IGludm9jYXRpb24uIEl0IHNldHMgdXAg dGhlIHVzZXIgcmVnaXN0ZXJzIGJhc2VkIG9uIHRoZSBzcGVjaWZpZWQKPj4gcmVnaXN0ZXIgY29u dGV4dCwgYW5kL29yIHB1c2hlcyB2YWx1ZXMgb24gdGhlIHVzZXIgc3RhY2sgYmFzZWQgb24gdGhl Cj4+IHNwZWNpZmllZCBzdGFjayBjb250ZXh0LCBhbmQgc2V0cyB0aGUgdXNlciBQQyB0byB0aGUg cmVxdWVzdGVkIHRhcmdldAo+PiBQQy4gV2hlbiB0aGUga2VybmVsIHJldHVybnMsIGV4ZWN1dGlv biBjb250aW51ZXMgYXQgdGhlIHRhcmdldCBQQy4KPj4gU28sIHRoZSBrZXJuZWwgZG9lcyB0aGUg d29yayBvZiB0aGUgdHJhbXBvbGluZSBvbiBiZWhhbGYgb2YgdGhlCj4+IGFwcGxpY2F0aW9uLgo+ IFRoaXMgaXMgcXVpdGUgY2xldmVyLCBidXQgbm93IEnigJltIHdvbmRlcmluZyBqdXN0IGhvdyBt dWNoIGtlcm5lbCBoZWxwCj4gaXMgcmVhbGx5IG5lZWRlZC4gSW4geW91ciBzZXJpZXMsIHRoZSB0 cmFtcG9saW5lIGlzIGFuIG5vbi1leGVjdXRhYmxlCj4gcGFnZS4gIEkgY2FuIHRoaW5rIG9mIGF0 IGxlYXN0IHR3byBhbHRlcm5hdGl2ZSBhcHByb2FjaGVzLCBhbmQgSSdkCj4gbGlrZSB0byBrbm93 IHRoZSBwcm9zIGFuZCBjb25zLgo+Cj4gMS4gRW50aXJlbHkgdXNlcnNwYWNlOiBhIHJldHVybiB0 cmFtcG9saW5lIHdvdWxkIGJlIHNvbWV0aGluZyBsaWtlOgo+Cj4gMToKPiBwdXNocSAlcmF4Cj4g cHVzaHEgJXJiYwo+IHB1c2hxICVyY3gKPiAuLi4KPiBwdXNocSAlcjE1Cj4gbW92cSAlcnNwLCAl cmRpICMgcG9pbnRlciB0byBzYXZlZCByZWdzCj4gbGVhcSAxYiglcmlwKSwgJXJzaSAjIHBvaW50 ZXIgdG8gdGhlIHRyYW1wb2xpbmUgaXRzZWxmCj4gY2FsbHEgdHJhbXBvbGluZV9oYW5kbGVyICMg c2VlIGJlbG93Cj4KPiBZb3Ugd291bGQgZmlsbCBhIHBhZ2Ugd2l0aCBhIGJ1bmNoIG9mIHRoZXNl LCBwb3NzaWJseSBjb21wYWN0ZWQgdG8gZ2V0Cj4gbW9yZSBwZXIgcGFnZSwgYW5kIHRoZW4geW91 IHdvdWxkIHJlbWFwIGFzIG1hbnkgY29waWVzIGFzIG5lZWRlZC4gIFRoZQo+ICdjYWxscSB0cmFt cG9saW5lX2hhbmRsZXInIHBhcnQgd291bGQgbmVlZCB0byBiZSBhIGJpdCBjbGV2ZXIgdG8gbWFr ZQo+IGl0IGNvbnRpbnVlIHRvIHdvcmsgZGVzcGl0ZSB0aGlzIHJlbWFwcGluZy4gIFRoaXMgd2ls bCBiZSAqbXVjaCoKPiBmYXN0ZXIgdGhhbiB0cmFtcGZkLiBIb3cgbXVjaCBvZiB5b3VyIHVzZSBj YXNlIHdvdWxkIGl0IGNvdmVyPyAgRm9yCj4gdGhlIGludmVyc2UsIGl0J3Mgbm90IHRvbyBoYXJk IHRvIHdyaXRlIGEgYml0IG9mIGFzbSB0byBzZXQgYWxsCj4gcmVnaXN0ZXJzIGFuZCBqdW1wIHNv bWV3aGVyZS4KCkxldCBtZSBzdGF0ZSBteSB1bmRlcnN0YW5kaW5nIG9mIHdoYXQgeW91IGFyZSBz dWdnZXN0aW5nLiBDb3JyZWN0IG1lIGlmCkkgZ2V0IGFueXRoaW5nIHdyb25nLiBJZiB5b3UgZG9u J3QgbWluZCwgSSB3aWxsIGFsc28gdGFrZSB0aGUgbGliZXJ0eQpvZiBnZW5lcmFsaXppbmcgYW5k IHBhcmFwaHJhc2luZyB5b3VyIHN1Z2dlc3Rpb24uCgpUaGUgZ29hbCBpcyB0byBjcmVhdGUgdHdv IHBhZ2UgbWFwcGluZ3MgdGhhdCBhcmUgYWRqYWNlbnQgdG8gZWFjaCBvdGhlcjoKCi0gYSBjb2Rl IHBhZ2UgdGhhdCBjb250YWlucyB0ZW1wbGF0ZSBjb2RlIGZvciBhIHRyYW1wb2xpbmUuIFNpbmNl IHRoZQrCoCB0ZW1wbGF0ZSBjb2RlIHdvdWxkIHRlbmQgdG8gYmUgc21hbGwgaW4gc2l6ZSwgcGFj ayBhcyBtYW55IG9mIHRoZW0KwqAgYXMgcG9zc2libGUgd2l0aGluIGEgcGFnZSB0byBjb25zZXJ2 ZSBtZW1vcnkuIEluIG90aGVyIHdvcmRzLCBjcmVhdGUKwqAgYW4gYXJyYXkgb2YgdGhlIHRlbXBs YXRlIGNvZGUgZnJhZ21lbnRzLiBFYWNoIGVsZW1lbnQgaW4gdGhlIGFycmF5CsKgIHdvdWxkIGJl IHVzZWQgZm9yIG9uZSB0cmFtcG9saW5lIGluc3RhbmNlLgoKLSBhIGRhdGEgcGFnZSB0aGF0IGNv bnRhaW5zIGFuIGFycmF5IG9mIGRhdGEgZWxlbWVudHMuIENvcnJlc3BvbmRpbmcKwqAgdG8gZWFj aCBjb2RlIGVsZW1lbnQgaW4gdGhlIGNvZGUgcGFnZSwgdGhlcmUgd291bGQgYmUgYSBkYXRhIGVs ZW1lbnQKwqAgaW4gdGhlIGRhdGEgcGFnZSB0aGF0IHdvdWxkIGNvbnRhaW4gZGF0YSB0aGF0IGlz IHNwZWNpZmljIHRvIGEKwqAgdHJhbXBvbGluZSBpbnN0YW5jZS4KCi0gQ29kZSB3aWxsIGFjY2Vz cyBkYXRhIHVzaW5nIFBDLXJlbGF0aXZlIGFkZHJlc3NpbmcuCgpUaGUgbWFuYWdlbWVudCBvZiB0 aGUgY29kZSBwYWdlcyBhbmQgYWxsb2NhdGlvbiBmb3IgZWFjaCB0cmFtcG9saW5lCmluc3RhbmNl IHdvdWxkIGFsbCBiZSBkb25lIGluIHVzZXIgc3BhY2UuCgpJcyB0aGlzIHRoZSBnZW5lcmFsIGlk ZWE/CgpDcmVhdGluZyBhIGNvZGUgcGFnZQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpX ZSBjYW4gZG8gdGhpcyBpbiBvbmUgb2YgdGhlIGZvbGxvd2luZyB3YXlzOgotIEFsbG9jYXRlIGEg d3JpdGFibGUgcGFnZSBhdCBydW4gdGltZSwgd3JpdGUgdGhlIHRlbXBsYXRlIGNvZGUgaW50bwrC oCB0aGUgcGFnZSBhbmQgaGF2ZSBleGVjdXRlIHBlcm1pc3Npb25zIG9uIHRoZSBwYWdlLgoKLSBB bGxvY2F0ZSBhIHdyaXRhYmxlIHBhZ2UgYXQgcnVuIHRpbWUsIHdyaXRlIHRoZSB0ZW1wbGF0ZSBj b2RlIGludG8KwqAgdGhlIHBhZ2UgYW5kIHJlbWFwIHRoZSBwYWdlIHdpdGgganVzdCBleGVjdXRl IHBlcm1pc3Npb25zLgoKLSBBbGxvY2F0ZSBhIHdyaXRhYmxlIHBhZ2UgYXQgcnVuIHRpbWUsIHdy aXRlIHRoZSB0ZW1wbGF0ZSBjb2RlIGludG8KwqAgdGhlIHBhZ2UsIHdyaXRlIHRoZSBwYWdlIGlu dG8gYSB0ZW1wb3JhcnkgZmlsZSBhbmQgbWFwIHRoZSBmaWxlIHdpdGgKwqAgZXhlY3V0ZSBwZXJt aXNzaW9ucy4KCi0gSW5jbHVkZSB0aGUgdGVtcGxhdGUgY29kZSBpbiBhIGNvZGUgcGFnZSBhdCBi dWlsZCB0aW1lIGl0c2VsZiBhbmQKwqAganVzdCByZW1hcCB0aGUgY29kZSBwYWdlIGVhY2ggdGlt ZSB5b3UgbmVlZCBhIGNvZGUgcGFnZS4KClByb3MgYW5kIENvbnMKLS0tLS0tLS0tLS0tLS0tLS0t LQoKQXMgbG9uZyBhcyB0aGUgT1MgcHJvdmlkZXMgdGhlIGZ1bmN0aW9uYWxpdHkgdG8gZG8gdGhp cyBhbmQgdGhlIHNlY3VyaXR5CnN1YnN5c3RlbSBpbiB0aGUgT1MgYWxsb3dzIHRoZSBhY3Rpb25z LCB0aGlzIGlzIHRvdGFsbHkgZmVhc2libGUuIElmIG5vdCwKd2UgbmVlZCBzb21ldGhpbmcgbGlr ZSB0cmFtcGZkLgoKQXMgRmxvcmVuIG1lbnRpb25lZCwgbGliZmZpIGRvZXMgaW1wbGVtZW50IHNv bWV0aGluZyBsaWtlIHRoaXMgZm9yIE1BQ0guCgpJbiBmYWN0LCBpbiBteSBsaWJmZmkgY2hhbmdl cywgSSB1c2UgdHJhbXBmZCBvbmx5IGFmdGVyIGFsbCB0aGUgb3RoZXIgbWV0aG9kcwpoYXZlIGZh aWxlZCBiZWNhdXNlIG9mIHNlY3VyaXR5IHNldHRpbmdzLgoKQnV0IHRoZSBhYm92ZSBhcHByb2Fj aCBvbmx5IHNvbHZlcyB0aGUgcHJvYmxlbSBmb3IgdGhpcyBzaW1wbGUgdHlwZSBvZgp0cmFtcG9s aW5lLiBJdCBkb2VzIG5vdCBwcm92aWRlIGEgZnJhbWV3b3JrIGZvciBhZGRyZXNzaW5nIG1vcmUg Y29tcGxleCB0eXBlcwpvciBldmVuIG90aGVyIGZvcm1zIG9mIGR5bmFtaWMgY29kZS4KCkFsc28s IGVhY2ggYXBwbGljYXRpb24gd291bGQgbmVlZCB0byBpbXBsZW1lbnQgdGhpcyBzb2x1dGlvbiBm b3IgaXRzZWxmCmFzIG9wcG9zZWQgdG8gcmVseWluZyBvbiBvbmUgaW1wbGVtZW50YXRpb24gcHJv dmlkZWQgYnkgdGhlIGtlcm5lbC4KClRyYW1wZmQtYmFzZWQgc29sdXRpb24KLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLQoKSSBvdXRsaW5lZCBhbiBlbmhhbmNlbWVudCB0byB0cmFtcGZk IGluIGEgcmVzcG9uc2UgdG8gRGF2aWQgTGFpZ2h0LiBJbiB0aGlzCmVuaGFuY2VtZW50LCB0aGUg a2VybmVsIGlzIHRoZSBvbmUgdGhhdCB3b3VsZCBzZXQgdXAgdGhlIGNvZGUgcGFnZS4KClRoZSBr ZXJuZWwgd291bGQgY2FsbCBhbiBhcmNoLXNwZWNpZmljIHN1cHBvcnQgZnVuY3Rpb24gdG8gZ2Vu ZXJhdGUgdGhlCmNvZGUgcmVxdWlyZWQgdG8gbG9hZCByZWdpc3RlcnMsIHB1c2ggdmFsdWVzIG9u IHRoZSBzdGFjayBhbmQganVtcCB0byBhIFBDCmZvciBhIHRyYW1wb2xpbmUgaW5zdGFuY2UgYmFz ZWQgb24gaXRzIGN1cnJlbnQgY29udGV4dC4gVGhlIHRyYW1wb2xpbmUKaW5zdGFuY2UgZGF0YSBj b3VsZCBiZSBiYWtlZCBpbnRvIHRoZSBjb2RlLgoKTXkgaW5pdGlhbCBpZGVhIHdhcyB0byBvbmx5 IGhhdmUgb25lIHRyYW1wb2xpbmUgaW5zdGFuY2UgcGVyIHBhZ2UuIEJ1dCBJCnRoaW5rIEkgY2Fu IGltcGxlbWVudCBtdWx0aXBsZSBpbnN0YW5jZXMgcGVyIHBhZ2UuIEkganVzdCBoYXZlIHRvIG1h bmFnZQp0aGUgdHJhbXBmZCBmaWxlIHByaXZhdGUgZGF0YSBhbmQgVk1BIHByaXZhdGUgZGF0YSBh Y2NvcmRpbmdseSB0byBtYXAgYW4KZWxlbWVudCBpbiBhIGNvZGUgcGFnZSB0byBpdHMgdHJhbXBv bGluZSBvYmplY3QuCgpUaGUgdHdvIGFwcHJvYWNoZXMgYXJlIHNpbWlsYXIgZXhjZXB0IGZvciB0 aGUgZGV0YWlsIGFib3V0IHdobyBzZXRzIHVwCmFuZCBtYW5hZ2VzIHRoZSB0cmFtcG9saW5lIHBh Z2VzLiBJbiBib3RoIGFwcHJvYWNoZXMsIHRoZSBwZXJmb3JtYW5jZSBwcm9ibGVtCmlzIGFkZHJl c3NlZC4gQnV0IHRyYW1wZmQgY2FuIGJlIHVzZWQgZXZlbiB3aGVuIHNlY3VyaXR5IHNldHRpbmdz IGFyZQpyZXN0cmljdGl2ZS4KCklzIG15IHNvbHV0aW9uIGFjY2VwdGFibGU/CgpBIGNvdXBsZSBv ZiB0aGluZ3MKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgotIEluIHRoZSBjdXJyZW50IHRyYW1w ZmQgaW1wbGVtZW50YXRpb24sIG5vIHBoeXNpY2FsIHBhZ2VzIGFyZSBhY3R1YWxseQrCoCBhbGxv Y2F0ZWQuIEl0IGlzIGp1c3QgYSB2aXJ0dWFsIG1hcHBpbmcuIEZyb20gYSBtZW1vcnkgZm9vdHBy aW50CsKgIHBlcnNwZWN0aXZlLCB0aGlzIGlzIGdvb2QuIE1heSBiZSwgd2UgY2FuIGxldCB0aGUg dXNlciBzcGVjaWZ5IGlmCsKgIGhlIHdhbnRzIGEgZmFzdCB0cmFtcG9saW5lIHRoYXQgY29uc3Vt ZXMgbWVtb3J5IG9yIGEgc2xvdyBvbmUgdGhhdCBkb2Vzbid0PwoKLSBJbiB0aGUgZnV0dXJlLCB3 ZSBtYXkgZGVmaW5lIGFkZGl0aW9uYWwgdHlwZXMgdGhhdCBuZWVkIHRoZSBrZXJuZWwgdG8gZG8K wqAgdGhlIGpvYi4gRXhhbXBsZXM6CgrCoMKgwqAgLSBUaGUga2VybmVsIG1heSBoYXZlIGEgdHJh bXBvbGluZSB0eXBlIGZvciB3aGljaCBpdCBpcyBub3Qgd2lsbGluZwrCoMKgwqDCoMKgwqAgb3Ig YWJsZSB0byBnZW5lcmF0ZSBjb2RlCgrCoMKgwqAgLSBUaGUga2VybmVsIGNvdWxkIGVtdWxhdGUg ZHluYW1pYyBjb2RlIGZvciB0aGUgdXNlcgoKwqDCoMKgwqAgLSBUaGUga2VybmVsIGNvdWxkIGlu dGVycHJldCBkeW5hbWljIGNvZGUgZm9yIHRoZSB1c2VyCgrCoMKgwqDCoCAtIFRoZSBrZXJuZWwg Y291bGQgYWxsb3cgdGhlIHVzZXIgdG8gYWNjZXNzIHNvbWUga2VybmVsIGZ1bmN0aW9uYWxpdHkK wqDCoMKgwqDCoMKgwqAgdXNpbmcgdGhlIGZyYW1ld29yawoKwqAgSW4gc3VjaCBjYXNlcywgdGhl cmUgaXNuJ3QgYW55IHBoeXNpY2FsIGNvZGUgcGFnZSB0aGF0IGdldHMgbWFwcGVkIGludG8KwqAg dGhlIHVzZXIgYWRkcmVzcyBzcGFjZS4gV2UgbmVlZCB0aGUga2VybmVsIHRvIGhhbmRsZSB0aGUg YWRkcmVzcyBmYXVsdArCoCBhbmQgcHJvdmlkZSB0aGUgZnVuY3Rpb25hbGl0eS4KCk9uZSBxdWVz dGlvbiBmb3IgdGhlIHJldmlld2VycwotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tCgpEbyB5b3UgdGhpbmsgdGhhdCB0aGUgZmlsZSBkZXNjcmlwdG9yIGJhc2VkIGFwcHJv YWNoIGlzIGZpbmU/IE9yLCBkb2VzIHRoaXMKbmVlZCBhIHJlZ3VsYXIgc3lzdGVtIGNhbGwgYmFz ZWQgaW1wbGVtZW50YXRpb24/IFRoZXJlIGFyZSBzb21lIGFkdmFudGFnZXMKd2l0aCBhIHJlZ3Vs YXIgc3lzdGVtIGNhbGw6CgotIFdlIGRvbid0IGNvbnN1bWUgZmlsZSBkZXNjcmlwdG9ycy4gRS5n LiwgaW4gbGliZmZpLCB3ZSBoYXZlIHRvCsKgIGtlZXAgdGhlIGZpbGUgZGVzY3JpcHRvciBvcGVu IGZvciBhIGNsb3N1cmUgdW50aWwgdGhlIGNsb3N1cmUKwqAgaXMgZnJlZWQuCgotIFRyYW1wb2xp bmUgb3BlcmF0aW9ucyBjYW4gYmUgcGVyZm9ybWVkIGJhc2VkIG9uIHRoZSB0cmFtcG9saW5lCsKg IGFkZHJlc3MgaW5zdGVhZCBvZiBhbiBmZC4KCi0gU2hhcmluZyBvZiBvYmplY3RzIGFjcm9zcyBw cm9jZXNzZXMgY2FuIGJlIGltcGxlbWVudGVkIHRocm91Z2gKwqAgYSByZWd1bGFyIElEIGJhc2Vk IG1ldGhvZCByYXRoZXIgdGhhbiBzZW5kaW5nIHRoZSBmaWxlIGRlc2NyaXB0b3IKwqAgb3ZlciBh IHVuaXggZG9tYWluIHNvY2tldC4KCi0gU2hhcmVkIG9iamVjdHMgY2FuIGJlIHBlcnNpc3RlbnQu CgotIEFuIGZkIGJhc2VkIEFQSSBkb2VzIHN0cnVjdHVyZSBwYXJzaW5nIGluIHJlYWQoKS93cml0 ZSgpIGNhbGxzCsKgIHRvIG9idGFpbiBhcmd1bWVudHMuIFdpdGggYSByZWd1bGFyIHN5c3RlbSBj YWxsLCB0aGF0IGlzIG5vdArCoCBuZWNlc3NhcnkuCgpQbGVhc2UgbGV0IG1lIGtub3cgeW91ciB0 aG91Z2h0cy4KCk1hZGhhdmFuCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVs QGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9s aXN0aW5mby9saW51eC1hcm0ta2VybmVsCg==