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 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8CAFFC43217 for ; Wed, 6 Oct 2021 17:41:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 786AD60FC3 for ; Wed, 6 Oct 2021 17:41:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239712AbhJFRni (ORCPT ); Wed, 6 Oct 2021 13:43:38 -0400 Received: from mx01.bbu.dsd.mx.bitdefender.com ([91.199.104.161]:53560 "EHLO mx01.bbu.dsd.mx.bitdefender.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239393AbhJFRmn (ORCPT ); Wed, 6 Oct 2021 13:42:43 -0400 Received: from smtp.bitdefender.com (smtp01.buh.bitdefender.com [10.17.80.75]) by mx01.bbu.dsd.mx.bitdefender.com (Postfix) with ESMTPS id D3664307CAFA; Wed, 6 Oct 2021 20:31:09 +0300 (EEST) Received: from localhost (unknown [91.199.104.28]) by smtp.bitdefender.com (Postfix) with ESMTPSA id B66F5305FFA0; Wed, 6 Oct 2021 20:31:09 +0300 (EEST) X-Is-Junk-Enabled: fGZTSsP0qEJE2AIKtlSuFiRRwg9xyHmJ From: =?UTF-8?q?Adalbert=20Laz=C4=83r?= To: kvm@vger.kernel.org Cc: virtualization@lists.linux-foundation.org, Paolo Bonzini , Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , Mathieu Tarral , Tamas K Lengyel , =?UTF-8?q?Mihai=20Don=C8=9Bu?= , =?UTF-8?q?Adalbert=20Laz=C4=83r?= Subject: [PATCH v12 39/77] KVM: introspection: add KVMI_VM_READ_PHYSICAL/KVMI_VM_WRITE_PHYSICAL Date: Wed, 6 Oct 2021 20:30:35 +0300 Message-Id: <20211006173113.26445-40-alazar@bitdefender.com> In-Reply-To: <20211006173113.26445-1-alazar@bitdefender.com> References: <20211006173113.26445-1-alazar@bitdefender.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Mihai Donțu These commands allow the introspection tool to read/write from/to the guest memory. Signed-off-by: Mihai Donțu Co-developed-by: Adalbert Lazăr Signed-off-by: Adalbert Lazăr --- Documentation/virt/kvm/kvmi.rst | 68 ++++++++++ include/uapi/linux/kvmi.h | 17 +++ .../testing/selftests/kvm/x86_64/kvmi_test.c | 124 ++++++++++++++++++ virt/kvm/introspection/kvmi.c | 98 ++++++++++++++ virt/kvm/introspection/kvmi_int.h | 7 + virt/kvm/introspection/kvmi_msg.c | 44 +++++++ 6 files changed, 358 insertions(+) diff --git a/Documentation/virt/kvm/kvmi.rst b/Documentation/virt/kvm/kvmi.rst index ecf809f40771..c424acf01784 100644 --- a/Documentation/virt/kvm/kvmi.rst +++ b/Documentation/virt/kvm/kvmi.rst @@ -365,6 +365,74 @@ the following events:: * -KVM_EINVAL - the event ID is unknown (use *KVMI_VM_CHECK_EVENT* first) * -KVM_EPERM - the access is disallowed (use *KVMI_VM_CHECK_EVENT* first) +6. KVMI_VM_READ_PHYSICAL +------------------------ + +:Architectures: all +:Versions: >= 1 +:Parameters: + +:: + + struct kvmi_vm_read_physical { + __u64 gpa; + __u16 size; + __u16 padding1; + __u32 padding2; + }; + +:Returns: + +:: + + struct kvmi_error_code; + __u8 data[0]; + +Reads from the guest memory. + +Currently, the size must be non-zero and the read must be restricted to +one page (offset + size <= PAGE_SIZE). + +:Errors: + +* -KVM_ENOENT - the guest page doesn't exists +* -KVM_EINVAL - the specified gpa/size pair is invalid +* -KVM_EINVAL - the padding is not zero + +7. KVMI_VM_WRITE_PHYSICAL +------------------------- + +:Architectures: all +:Versions: >= 1 +:Parameters: + +:: + + struct kvmi_vm_write_physical { + __u64 gpa; + __u16 size; + __u16 padding1; + __u32 padding2; + __u8 data[0]; + }; + +:Returns: + +:: + + struct kvmi_error_code + +Writes into the guest memory. + +Currently, the size must be non-zero and the write must be restricted to +one page (offset + size <= PAGE_SIZE). + +:Errors: + +* -KVM_ENOENT - the guest page doesn't exists +* -KVM_EINVAL - the specified gpa/size pair is invalid +* -KVM_EINVAL - the padding is not zero + Events ====== diff --git a/include/uapi/linux/kvmi.h b/include/uapi/linux/kvmi.h index 9a10ef2cd890..048afad01be6 100644 --- a/include/uapi/linux/kvmi.h +++ b/include/uapi/linux/kvmi.h @@ -24,6 +24,8 @@ enum { KVMI_VM_CHECK_EVENT = KVMI_VM_MESSAGE_ID(3), KVMI_VM_GET_INFO = KVMI_VM_MESSAGE_ID(4), KVMI_VM_CONTROL_EVENTS = KVMI_VM_MESSAGE_ID(5), + KVMI_VM_READ_PHYSICAL = KVMI_VM_MESSAGE_ID(6), + KVMI_VM_WRITE_PHYSICAL = KVMI_VM_MESSAGE_ID(7), KVMI_NEXT_VM_MESSAGE }; @@ -90,4 +92,19 @@ struct kvmi_vm_control_events { __u32 padding2; }; +struct kvmi_vm_read_physical { + __u64 gpa; + __u16 size; + __u16 padding1; + __u32 padding2; +}; + +struct kvmi_vm_write_physical { + __u64 gpa; + __u16 size; + __u16 padding1; + __u32 padding2; + __u8 data[0]; +}; + #endif /* _UAPI__LINUX_KVMI_H */ diff --git a/tools/testing/selftests/kvm/x86_64/kvmi_test.c b/tools/testing/selftests/kvm/x86_64/kvmi_test.c index f5fdb09b9be6..28dd6414a7e8 100644 --- a/tools/testing/selftests/kvm/x86_64/kvmi_test.c +++ b/tools/testing/selftests/kvm/x86_64/kvmi_test.c @@ -8,6 +8,7 @@ #define _GNU_SOURCE /* for program_invocation_short_name */ #include #include +#include #include "test_util.h" @@ -24,6 +25,12 @@ static int socket_pair[2]; #define Kvm_socket socket_pair[0] #define Userspace_socket socket_pair[1] +static vm_vaddr_t test_gva; +static void *test_hva; +static vm_paddr_t test_gpa; + +static int page_size; + void setup_socket(void) { int r; @@ -427,8 +434,112 @@ static void test_cmd_vm_control_events(struct kvm_vm *vm) allow_event(vm, id); } +static void cmd_vm_write_page(__u64 gpa, __u64 size, void *p, + int expected_err) +{ + struct kvmi_vm_write_physical *cmd; + struct kvmi_msg_hdr *req; + size_t req_size; + + req_size = sizeof(*req) + sizeof(*cmd) + size; + req = calloc(1, req_size); + + cmd = (struct kvmi_vm_write_physical *)(req + 1); + cmd->gpa = gpa; + cmd->size = size; + + memcpy(cmd + 1, p, size); + + test_vm_command(KVMI_VM_WRITE_PHYSICAL, req, req_size, NULL, 0, + expected_err); + + free(req); +} + +static void write_guest_page(__u64 gpa, void *p) +{ + cmd_vm_write_page(gpa, page_size, p, 0); +} + +static void write_with_invalid_arguments(__u64 gpa, __u64 size, void *p) +{ + cmd_vm_write_page(gpa, size, p, -KVM_EINVAL); +} + +static void write_invalid_guest_page(struct kvm_vm *vm, void *p) +{ + __u64 gpa = vm->max_gfn << vm->page_shift; + __u64 size = 1; + + cmd_vm_write_page(gpa, size, p, -KVM_ENOENT); +} + +static void cmd_vm_read_page(__u64 gpa, __u64 size, void *p, + int expected_err) +{ + struct { + struct kvmi_msg_hdr hdr; + struct kvmi_vm_read_physical cmd; + } req = { }; + + req.cmd.gpa = gpa; + req.cmd.size = size; + + test_vm_command(KVMI_VM_READ_PHYSICAL, &req.hdr, sizeof(req), p, size, + expected_err); +} + +static void read_guest_page(__u64 gpa, void *p) +{ + cmd_vm_read_page(gpa, page_size, p, 0); +} + +static void read_with_invalid_arguments(__u64 gpa, __u64 size, void *p) +{ + cmd_vm_read_page(gpa, size, p, -KVM_EINVAL); +} + +static void read_invalid_guest_page(struct kvm_vm *vm) +{ + __u64 gpa = vm->max_gfn << vm->page_shift; + __u64 size = 1; + + cmd_vm_read_page(gpa, size, NULL, -KVM_ENOENT); +} + +static void test_memory_access(struct kvm_vm *vm) +{ + void *pw, *pr; + + pw = malloc(page_size); + TEST_ASSERT(pw, "Insufficient Memory\n"); + + memset(pw, 1, page_size); + + write_guest_page(test_gpa, pw); + TEST_ASSERT(memcmp(pw, test_hva, page_size) == 0, + "Write page test failed"); + + pr = malloc(page_size); + TEST_ASSERT(pr, "Insufficient Memory\n"); + + read_guest_page(test_gpa, pr); + TEST_ASSERT(memcmp(pw, pr, page_size) == 0, + "Read page test failed"); + + read_with_invalid_arguments(test_gpa, 0, pr); + write_with_invalid_arguments(test_gpa, 0, pw); + write_invalid_guest_page(vm, pw); + + free(pw); + free(pr); + + read_invalid_guest_page(vm); +} + static void test_introspection(struct kvm_vm *vm) { + srandom(time(0)); setup_socket(); hook_introspection(vm); @@ -439,10 +550,20 @@ static void test_introspection(struct kvm_vm *vm) test_cmd_vm_get_info(); test_event_unhook(vm); test_cmd_vm_control_events(vm); + test_memory_access(vm); unhook_introspection(vm); } +static void setup_test_pages(struct kvm_vm *vm) +{ + test_gva = vm_vaddr_alloc_page(vm); + sync_global_to_guest(vm, test_gva); + + test_hva = addr_gva2hva(vm, test_gva); + test_gpa = addr_gva2gpa(vm, test_gva); +} + int main(int argc, char *argv[]) { struct kvm_vm *vm; @@ -455,6 +576,9 @@ int main(int argc, char *argv[]) vm = vm_create_default(VCPU_ID, 0, NULL); vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); + page_size = getpagesize(); + setup_test_pages(vm); + test_introspection(vm); kvm_vm_free(vm); diff --git a/virt/kvm/introspection/kvmi.c b/virt/kvm/introspection/kvmi.c index 6a57d45b66ec..207dabb8b040 100644 --- a/virt/kvm/introspection/kvmi.c +++ b/virt/kvm/introspection/kvmi.c @@ -5,7 +5,9 @@ * Copyright (C) 2017-2021 Bitdefender S.R.L. * */ +#include #include +#include #include "kvmi_int.h" #define KVMI_NUM_COMMANDS __cmp((int)KVMI_NEXT_VM_MESSAGE, \ @@ -453,3 +455,99 @@ int kvmi_cmd_vm_control_events(struct kvm_introspection *kvmi, return 0; } + +static long +get_user_pages_remote_unlocked(struct mm_struct *mm, unsigned long start, + unsigned long nr_pages, unsigned int gup_flags, + struct page **pages) +{ + struct vm_area_struct **vmas = NULL; + int locked = 1; + long r; + + mmap_read_lock(mm); + r = get_user_pages_remote(mm, start, nr_pages, gup_flags, + pages, vmas, &locked); + if (locked) + mmap_read_unlock(mm); + + return r; +} + +static void *get_page_ptr(struct kvm *kvm, gpa_t gpa, struct page **page, + bool write, int *srcu_idx) +{ + unsigned int flags = write ? FOLL_WRITE : 0; + unsigned long hva; + + *page = NULL; + + *srcu_idx = srcu_read_lock(&kvm->srcu); + hva = gfn_to_hva(kvm, gpa_to_gfn(gpa)); + + if (kvm_is_error_hva(hva)) + goto out_err; + + if (get_user_pages_remote_unlocked(kvm->mm, hva, 1, flags, page) != 1) + goto out_err; + + return write ? kmap_atomic(*page) : kmap(*page); +out_err: + srcu_read_unlock(&kvm->srcu, *srcu_idx); + return NULL; +} + +static void put_page_ptr(struct kvm *kvm, void *ptr, struct page *page, + bool write, int srcu_idx) +{ + if (write) + kunmap_atomic(ptr); + else + kunmap(ptr); + + put_page(page); + + srcu_read_unlock(&kvm->srcu, srcu_idx); +} + +int kvmi_cmd_read_physical(struct kvm *kvm, u64 gpa, size_t size, + int (*send)(struct kvm_introspection *, + const struct kvmi_msg_hdr *, + int err, const void *buf, size_t), + const struct kvmi_msg_hdr *ctx) +{ + struct page *page; + void *ptr_page; + int srcu_idx; + int err; + + ptr_page = get_page_ptr(kvm, gpa, &page, false, &srcu_idx); + if (!ptr_page) { + err = send(KVMI(kvm), ctx, -KVM_ENOENT, NULL, 0); + } else { + err = send(KVMI(kvm), ctx, 0, + ptr_page + (gpa & ~PAGE_MASK), size); + + put_page_ptr(kvm, ptr_page, page, false, srcu_idx); + } + + return err; +} + +int kvmi_cmd_write_physical(struct kvm *kvm, u64 gpa, size_t size, + const void *buf) +{ + int ec = -KVM_ENOENT; + struct page *page; + int srcu_idx; + void *ptr; + + ptr = get_page_ptr(kvm, gpa, &page, true, &srcu_idx); + if (ptr) { + memcpy(ptr + (gpa & ~PAGE_MASK), buf, size); + put_page_ptr(kvm, ptr, page, true, srcu_idx); + ec = 0; + } + + return ec; +} diff --git a/virt/kvm/introspection/kvmi_int.h b/virt/kvm/introspection/kvmi_int.h index 987513d6c1a7..b7c8730e7e6d 100644 --- a/virt/kvm/introspection/kvmi_int.h +++ b/virt/kvm/introspection/kvmi_int.h @@ -29,6 +29,13 @@ bool kvmi_is_known_event(u16 id); bool kvmi_is_known_vm_event(u16 id); int kvmi_cmd_vm_control_events(struct kvm_introspection *kvmi, u16 event_id, bool enable); +int kvmi_cmd_read_physical(struct kvm *kvm, u64 gpa, size_t size, + int (*send)(struct kvm_introspection *, + const struct kvmi_msg_hdr*, + int err, const void *buf, size_t), + const struct kvmi_msg_hdr *ctx); +int kvmi_cmd_write_physical(struct kvm *kvm, u64 gpa, size_t size, + const void *buf); /* arch */ void kvmi_arch_init_vcpu_events_mask(unsigned long *supported); diff --git a/virt/kvm/introspection/kvmi_msg.c b/virt/kvm/introspection/kvmi_msg.c index b2a5dd3d219a..697c307ea745 100644 --- a/virt/kvm/introspection/kvmi_msg.c +++ b/virt/kvm/introspection/kvmi_msg.c @@ -182,6 +182,48 @@ static int handle_vm_control_events(struct kvm_introspection *kvmi, return kvmi_msg_vm_reply(kvmi, msg, ec, NULL, 0); } +static bool invalid_page_access(u64 gpa, u64 size) +{ + u64 off = gpa & ~PAGE_MASK; + + return (size == 0 || size > PAGE_SIZE || off + size > PAGE_SIZE); +} + +static int handle_vm_read_physical(struct kvm_introspection *kvmi, + const struct kvmi_msg_hdr *msg, + const void *_req) +{ + const struct kvmi_vm_read_physical *req = _req; + + if (invalid_page_access(req->gpa, req->size) || + req->padding1 || req->padding2) + return kvmi_msg_vm_reply(kvmi, msg, -KVM_EINVAL, NULL, 0); + + return kvmi_cmd_read_physical(kvmi->kvm, req->gpa, req->size, + kvmi_msg_vm_reply, msg); +} + +static int handle_vm_write_physical(struct kvm_introspection *kvmi, + const struct kvmi_msg_hdr *msg, + const void *_req) +{ + const struct kvmi_vm_write_physical *req = _req; + int ec; + + if (struct_size(req, data, req->size) > msg->size) + return -EINVAL; + + if (invalid_page_access(req->gpa, req->size)) + ec = -KVM_EINVAL; + else if (req->padding1 || req->padding2) + ec = -KVM_EINVAL; + else + ec = kvmi_cmd_write_physical(kvmi->kvm, req->gpa, + req->size, req->data); + + return kvmi_msg_vm_reply(kvmi, msg, ec, NULL, 0); +} + /* * These commands are executed by the receiving thread. */ @@ -191,6 +233,8 @@ static const kvmi_vm_msg_fct msg_vm[] = { [KVMI_VM_CHECK_EVENT] = handle_vm_check_event, [KVMI_VM_CONTROL_EVENTS] = handle_vm_control_events, [KVMI_VM_GET_INFO] = handle_vm_get_info, + [KVMI_VM_READ_PHYSICAL] = handle_vm_read_physical, + [KVMI_VM_WRITE_PHYSICAL] = handle_vm_write_physical, }; static kvmi_vm_msg_fct get_vm_msg_handler(u16 id) 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 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 74A3DC433FE for ; Wed, 6 Oct 2021 17:55:51 +0000 (UTC) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (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 3DE4761186 for ; Wed, 6 Oct 2021 17:55:51 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 3DE4761186 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=bitdefender.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=lists.linux-foundation.org Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id E739484085; Wed, 6 Oct 2021 17:55:50 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1su2nR1EERhe; Wed, 6 Oct 2021 17:55:49 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 3EE4F83EE7; Wed, 6 Oct 2021 17:55:49 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 84F46C0023; Wed, 6 Oct 2021 17:55:48 +0000 (UTC) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3AC41C0011 for ; Wed, 6 Oct 2021 17:55:44 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id B824383BE4 for ; Wed, 6 Oct 2021 17:55:43 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Q8L8eLsnHJTQ for ; Wed, 6 Oct 2021 17:55:42 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.8.0 Received: from mx01.bbu.dsd.mx.bitdefender.com (mx01.bbu.dsd.mx.bitdefender.com [91.199.104.161]) by smtp1.osuosl.org (Postfix) with ESMTPS id 688E983AB8 for ; Wed, 6 Oct 2021 17:55:42 +0000 (UTC) Received: from smtp.bitdefender.com (smtp01.buh.bitdefender.com [10.17.80.75]) by mx01.bbu.dsd.mx.bitdefender.com (Postfix) with ESMTPS id D3664307CAFA; Wed, 6 Oct 2021 20:31:09 +0300 (EEST) Received: from localhost (unknown [91.199.104.28]) by smtp.bitdefender.com (Postfix) with ESMTPSA id B66F5305FFA0; Wed, 6 Oct 2021 20:31:09 +0300 (EEST) X-Is-Junk-Enabled: fGZTSsP0qEJE2AIKtlSuFiRRwg9xyHmJ From: =?UTF-8?q?Adalbert=20Laz=C4=83r?= To: kvm@vger.kernel.org Subject: [PATCH v12 39/77] KVM: introspection: add KVMI_VM_READ_PHYSICAL/KVMI_VM_WRITE_PHYSICAL Date: Wed, 6 Oct 2021 20:30:35 +0300 Message-Id: <20211006173113.26445-40-alazar@bitdefender.com> In-Reply-To: <20211006173113.26445-1-alazar@bitdefender.com> References: <20211006173113.26445-1-alazar@bitdefender.com> MIME-Version: 1.0 Cc: Tamas K Lengyel , Wanpeng Li , Sean Christopherson , Joerg Roedel , virtualization@lists.linux-foundation.org, =?UTF-8?q?Adalbert=20Laz=C4=83r?= , Mathieu Tarral , Paolo Bonzini , =?UTF-8?q?Mihai=20Don=C8=9Bu?= , Jim Mattson X-BeenThere: virtualization@lists.linux-foundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux virtualization List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: virtualization-bounces@lists.linux-foundation.org Sender: "Virtualization" RnJvbTogTWloYWkgRG9uyJt1IDxtZG9udHVAYml0ZGVmZW5kZXIuY29tPgoKVGhlc2UgY29tbWFu ZHMgYWxsb3cgdGhlIGludHJvc3BlY3Rpb24gdG9vbCB0byByZWFkL3dyaXRlIGZyb20vdG8KdGhl IGd1ZXN0IG1lbW9yeS4KClNpZ25lZC1vZmYtYnk6IE1paGFpIERvbsibdSA8bWRvbnR1QGJpdGRl ZmVuZGVyLmNvbT4KQ28tZGV2ZWxvcGVkLWJ5OiBBZGFsYmVydCBMYXrEg3IgPGFsYXphckBiaXRk ZWZlbmRlci5jb20+ClNpZ25lZC1vZmYtYnk6IEFkYWxiZXJ0IExhesSDciA8YWxhemFyQGJpdGRl ZmVuZGVyLmNvbT4KLS0tCiBEb2N1bWVudGF0aW9uL3ZpcnQva3ZtL2t2bWkucnN0ICAgICAgICAg ICAgICAgfCAgNjggKysrKysrKysrKwogaW5jbHVkZS91YXBpL2xpbnV4L2t2bWkuaCAgICAgICAg ICAgICAgICAgICAgIHwgIDE3ICsrKwogLi4uL3Rlc3Rpbmcvc2VsZnRlc3RzL2t2bS94ODZfNjQv a3ZtaV90ZXN0LmMgIHwgMTI0ICsrKysrKysrKysrKysrKysrKwogdmlydC9rdm0vaW50cm9zcGVj dGlvbi9rdm1pLmMgICAgICAgICAgICAgICAgIHwgIDk4ICsrKysrKysrKysrKysrCiB2aXJ0L2t2 bS9pbnRyb3NwZWN0aW9uL2t2bWlfaW50LmggICAgICAgICAgICAgfCAgIDcgKwogdmlydC9rdm0v aW50cm9zcGVjdGlvbi9rdm1pX21zZy5jICAgICAgICAgICAgIHwgIDQ0ICsrKysrKysKIDYgZmls ZXMgY2hhbmdlZCwgMzU4IGluc2VydGlvbnMoKykKCmRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9u L3ZpcnQva3ZtL2t2bWkucnN0IGIvRG9jdW1lbnRhdGlvbi92aXJ0L2t2bS9rdm1pLnJzdAppbmRl eCBlY2Y4MDlmNDA3NzEuLmM0MjRhY2YwMTc4NCAxMDA2NDQKLS0tIGEvRG9jdW1lbnRhdGlvbi92 aXJ0L2t2bS9rdm1pLnJzdAorKysgYi9Eb2N1bWVudGF0aW9uL3ZpcnQva3ZtL2t2bWkucnN0CkBA IC0zNjUsNiArMzY1LDc0IEBAIHRoZSBmb2xsb3dpbmcgZXZlbnRzOjoKICogLUtWTV9FSU5WQUwg LSB0aGUgZXZlbnQgSUQgaXMgdW5rbm93biAodXNlICpLVk1JX1ZNX0NIRUNLX0VWRU5UKiBmaXJz dCkKICogLUtWTV9FUEVSTSAtIHRoZSBhY2Nlc3MgaXMgZGlzYWxsb3dlZCAodXNlICpLVk1JX1ZN X0NIRUNLX0VWRU5UKiBmaXJzdCkKIAorNi4gS1ZNSV9WTV9SRUFEX1BIWVNJQ0FMCistLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0KKworOkFyY2hpdGVjdHVyZXM6IGFsbAorOlZlcnNpb25zOiA+PSAx Cis6UGFyYW1ldGVyczoKKworOjoKKworCXN0cnVjdCBrdm1pX3ZtX3JlYWRfcGh5c2ljYWwgewor CQlfX3U2NCBncGE7CisJCV9fdTE2IHNpemU7CisJCV9fdTE2IHBhZGRpbmcxOworCQlfX3UzMiBw YWRkaW5nMjsKKwl9OworCis6UmV0dXJuczoKKworOjoKKworCXN0cnVjdCBrdm1pX2Vycm9yX2Nv ZGU7CisJX191OCBkYXRhWzBdOworCitSZWFkcyBmcm9tIHRoZSBndWVzdCBtZW1vcnkuCisKK0N1 cnJlbnRseSwgdGhlIHNpemUgbXVzdCBiZSBub24temVybyBhbmQgdGhlIHJlYWQgbXVzdCBiZSBy ZXN0cmljdGVkIHRvCitvbmUgcGFnZSAob2Zmc2V0ICsgc2l6ZSA8PSBQQUdFX1NJWkUpLgorCis6 RXJyb3JzOgorCisqIC1LVk1fRU5PRU5UIC0gdGhlIGd1ZXN0IHBhZ2UgZG9lc24ndCBleGlzdHMK KyogLUtWTV9FSU5WQUwgLSB0aGUgc3BlY2lmaWVkIGdwYS9zaXplIHBhaXIgaXMgaW52YWxpZAor KiAtS1ZNX0VJTlZBTCAtIHRoZSBwYWRkaW5nIGlzIG5vdCB6ZXJvCisKKzcuIEtWTUlfVk1fV1JJ VEVfUEhZU0lDQUwKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKworOkFyY2hpdGVjdHVyZXM6 IGFsbAorOlZlcnNpb25zOiA+PSAxCis6UGFyYW1ldGVyczoKKworOjoKKworCXN0cnVjdCBrdm1p X3ZtX3dyaXRlX3BoeXNpY2FsIHsKKwkJX191NjQgZ3BhOworCQlfX3UxNiBzaXplOworCQlfX3Ux NiBwYWRkaW5nMTsKKwkJX191MzIgcGFkZGluZzI7CisJCV9fdTggIGRhdGFbMF07CisJfTsKKwor OlJldHVybnM6CisKKzo6CisKKwlzdHJ1Y3Qga3ZtaV9lcnJvcl9jb2RlCisKK1dyaXRlcyBpbnRv IHRoZSBndWVzdCBtZW1vcnkuCisKK0N1cnJlbnRseSwgdGhlIHNpemUgbXVzdCBiZSBub24temVy byBhbmQgdGhlIHdyaXRlIG11c3QgYmUgcmVzdHJpY3RlZCB0bworb25lIHBhZ2UgKG9mZnNldCAr IHNpemUgPD0gUEFHRV9TSVpFKS4KKworOkVycm9yczoKKworKiAtS1ZNX0VOT0VOVCAtIHRoZSBn dWVzdCBwYWdlIGRvZXNuJ3QgZXhpc3RzCisqIC1LVk1fRUlOVkFMIC0gdGhlIHNwZWNpZmllZCBn cGEvc2l6ZSBwYWlyIGlzIGludmFsaWQKKyogLUtWTV9FSU5WQUwgLSB0aGUgcGFkZGluZyBpcyBu b3QgemVybworCiBFdmVudHMKID09PT09PQogCmRpZmYgLS1naXQgYS9pbmNsdWRlL3VhcGkvbGlu dXgva3ZtaS5oIGIvaW5jbHVkZS91YXBpL2xpbnV4L2t2bWkuaAppbmRleCA5YTEwZWYyY2Q4OTAu LjA0OGFmYWQwMWJlNiAxMDA2NDQKLS0tIGEvaW5jbHVkZS91YXBpL2xpbnV4L2t2bWkuaAorKysg Yi9pbmNsdWRlL3VhcGkvbGludXgva3ZtaS5oCkBAIC0yNCw2ICsyNCw4IEBAIGVudW0gewogCUtW TUlfVk1fQ0hFQ0tfRVZFTlQgICAgPSBLVk1JX1ZNX01FU1NBR0VfSUQoMyksCiAJS1ZNSV9WTV9H RVRfSU5GTyAgICAgICA9IEtWTUlfVk1fTUVTU0FHRV9JRCg0KSwKIAlLVk1JX1ZNX0NPTlRST0xf RVZFTlRTID0gS1ZNSV9WTV9NRVNTQUdFX0lEKDUpLAorCUtWTUlfVk1fUkVBRF9QSFlTSUNBTCAg PSBLVk1JX1ZNX01FU1NBR0VfSUQoNiksCisJS1ZNSV9WTV9XUklURV9QSFlTSUNBTCA9IEtWTUlf Vk1fTUVTU0FHRV9JRCg3KSwKIAogCUtWTUlfTkVYVF9WTV9NRVNTQUdFCiB9OwpAQCAtOTAsNCAr OTIsMTkgQEAgc3RydWN0IGt2bWlfdm1fY29udHJvbF9ldmVudHMgewogCV9fdTMyIHBhZGRpbmcy OwogfTsKIAorc3RydWN0IGt2bWlfdm1fcmVhZF9waHlzaWNhbCB7CisJX191NjQgZ3BhOworCV9f dTE2IHNpemU7CisJX191MTYgcGFkZGluZzE7CisJX191MzIgcGFkZGluZzI7Cit9OworCitzdHJ1 Y3Qga3ZtaV92bV93cml0ZV9waHlzaWNhbCB7CisJX191NjQgZ3BhOworCV9fdTE2IHNpemU7CisJ X191MTYgcGFkZGluZzE7CisJX191MzIgcGFkZGluZzI7CisJX191OCAgZGF0YVswXTsKK307CisK ICNlbmRpZiAvKiBfVUFQSV9fTElOVVhfS1ZNSV9IICovCmRpZmYgLS1naXQgYS90b29scy90ZXN0 aW5nL3NlbGZ0ZXN0cy9rdm0veDg2XzY0L2t2bWlfdGVzdC5jIGIvdG9vbHMvdGVzdGluZy9zZWxm dGVzdHMva3ZtL3g4Nl82NC9rdm1pX3Rlc3QuYwppbmRleCBmNWZkYjA5YjliZTYuLjI4ZGQ2NDE0 YTdlOCAxMDA2NDQKLS0tIGEvdG9vbHMvdGVzdGluZy9zZWxmdGVzdHMva3ZtL3g4Nl82NC9rdm1p X3Rlc3QuYworKysgYi90b29scy90ZXN0aW5nL3NlbGZ0ZXN0cy9rdm0veDg2XzY0L2t2bWlfdGVz dC5jCkBAIC04LDYgKzgsNyBAQAogI2RlZmluZSBfR05VX1NPVVJDRSAvKiBmb3IgcHJvZ3JhbV9p bnZvY2F0aW9uX3Nob3J0X25hbWUgKi8KICNpbmNsdWRlIDxzeXMvdHlwZXMuaD4KICNpbmNsdWRl IDxzeXMvc29ja2V0Lmg+CisjaW5jbHVkZSA8dGltZS5oPgogCiAjaW5jbHVkZSAidGVzdF91dGls LmgiCiAKQEAgLTI0LDYgKzI1LDEyIEBAIHN0YXRpYyBpbnQgc29ja2V0X3BhaXJbMl07CiAjZGVm aW5lIEt2bV9zb2NrZXQgICAgICAgc29ja2V0X3BhaXJbMF0KICNkZWZpbmUgVXNlcnNwYWNlX3Nv Y2tldCBzb2NrZXRfcGFpclsxXQogCitzdGF0aWMgdm1fdmFkZHJfdCB0ZXN0X2d2YTsKK3N0YXRp YyB2b2lkICp0ZXN0X2h2YTsKK3N0YXRpYyB2bV9wYWRkcl90IHRlc3RfZ3BhOworCitzdGF0aWMg aW50IHBhZ2Vfc2l6ZTsKKwogdm9pZCBzZXR1cF9zb2NrZXQodm9pZCkKIHsKIAlpbnQgcjsKQEAg LTQyNyw4ICs0MzQsMTEyIEBAIHN0YXRpYyB2b2lkIHRlc3RfY21kX3ZtX2NvbnRyb2xfZXZlbnRz KHN0cnVjdCBrdm1fdm0gKnZtKQogCWFsbG93X2V2ZW50KHZtLCBpZCk7CiB9CiAKK3N0YXRpYyB2 b2lkIGNtZF92bV93cml0ZV9wYWdlKF9fdTY0IGdwYSwgX191NjQgc2l6ZSwgdm9pZCAqcCwKKwkJ CSAgICAgIGludCBleHBlY3RlZF9lcnIpCit7CisJc3RydWN0IGt2bWlfdm1fd3JpdGVfcGh5c2lj YWwgKmNtZDsKKwlzdHJ1Y3Qga3ZtaV9tc2dfaGRyICpyZXE7CisJc2l6ZV90IHJlcV9zaXplOwor CisJcmVxX3NpemUgPSBzaXplb2YoKnJlcSkgKyBzaXplb2YoKmNtZCkgKyBzaXplOworCXJlcSA9 IGNhbGxvYygxLCByZXFfc2l6ZSk7CisKKwljbWQgPSAoc3RydWN0IGt2bWlfdm1fd3JpdGVfcGh5 c2ljYWwgKikocmVxICsgMSk7CisJY21kLT5ncGEgPSBncGE7CisJY21kLT5zaXplID0gc2l6ZTsK KworCW1lbWNweShjbWQgKyAxLCBwLCBzaXplKTsKKworCXRlc3Rfdm1fY29tbWFuZChLVk1JX1ZN X1dSSVRFX1BIWVNJQ0FMLCByZXEsIHJlcV9zaXplLCBOVUxMLCAwLAorCQkJZXhwZWN0ZWRfZXJy KTsKKworCWZyZWUocmVxKTsKK30KKworc3RhdGljIHZvaWQgd3JpdGVfZ3Vlc3RfcGFnZShfX3U2 NCBncGEsIHZvaWQgKnApCit7CisJY21kX3ZtX3dyaXRlX3BhZ2UoZ3BhLCBwYWdlX3NpemUsIHAs IDApOworfQorCitzdGF0aWMgdm9pZCB3cml0ZV93aXRoX2ludmFsaWRfYXJndW1lbnRzKF9fdTY0 IGdwYSwgX191NjQgc2l6ZSwgdm9pZCAqcCkKK3sKKwljbWRfdm1fd3JpdGVfcGFnZShncGEsIHNp emUsIHAsIC1LVk1fRUlOVkFMKTsKK30KKworc3RhdGljIHZvaWQgd3JpdGVfaW52YWxpZF9ndWVz dF9wYWdlKHN0cnVjdCBrdm1fdm0gKnZtLCB2b2lkICpwKQoreworCV9fdTY0IGdwYSA9IHZtLT5t YXhfZ2ZuIDw8IHZtLT5wYWdlX3NoaWZ0OworCV9fdTY0IHNpemUgPSAxOworCisJY21kX3ZtX3dy aXRlX3BhZ2UoZ3BhLCBzaXplLCBwLCAtS1ZNX0VOT0VOVCk7Cit9CisKK3N0YXRpYyB2b2lkIGNt ZF92bV9yZWFkX3BhZ2UoX191NjQgZ3BhLCBfX3U2NCBzaXplLCB2b2lkICpwLAorCQkJICAgICBp bnQgZXhwZWN0ZWRfZXJyKQoreworCXN0cnVjdCB7CisJCXN0cnVjdCBrdm1pX21zZ19oZHIgaGRy OworCQlzdHJ1Y3Qga3ZtaV92bV9yZWFkX3BoeXNpY2FsIGNtZDsKKwl9IHJlcSA9IHsgfTsKKwor CXJlcS5jbWQuZ3BhID0gZ3BhOworCXJlcS5jbWQuc2l6ZSA9IHNpemU7CisKKwl0ZXN0X3ZtX2Nv bW1hbmQoS1ZNSV9WTV9SRUFEX1BIWVNJQ0FMLCAmcmVxLmhkciwgc2l6ZW9mKHJlcSksIHAsIHNp emUsCisJCQlleHBlY3RlZF9lcnIpOworfQorCitzdGF0aWMgdm9pZCByZWFkX2d1ZXN0X3BhZ2Uo X191NjQgZ3BhLCB2b2lkICpwKQoreworCWNtZF92bV9yZWFkX3BhZ2UoZ3BhLCBwYWdlX3NpemUs IHAsIDApOworfQorCitzdGF0aWMgdm9pZCByZWFkX3dpdGhfaW52YWxpZF9hcmd1bWVudHMoX191 NjQgZ3BhLCBfX3U2NCBzaXplLCB2b2lkICpwKQoreworCWNtZF92bV9yZWFkX3BhZ2UoZ3BhLCBz aXplLCBwLCAtS1ZNX0VJTlZBTCk7Cit9CisKK3N0YXRpYyB2b2lkIHJlYWRfaW52YWxpZF9ndWVz dF9wYWdlKHN0cnVjdCBrdm1fdm0gKnZtKQoreworCV9fdTY0IGdwYSA9IHZtLT5tYXhfZ2ZuIDw8 IHZtLT5wYWdlX3NoaWZ0OworCV9fdTY0IHNpemUgPSAxOworCisJY21kX3ZtX3JlYWRfcGFnZShn cGEsIHNpemUsIE5VTEwsIC1LVk1fRU5PRU5UKTsKK30KKworc3RhdGljIHZvaWQgdGVzdF9tZW1v cnlfYWNjZXNzKHN0cnVjdCBrdm1fdm0gKnZtKQoreworCXZvaWQgKnB3LCAqcHI7CisKKwlwdyA9 IG1hbGxvYyhwYWdlX3NpemUpOworCVRFU1RfQVNTRVJUKHB3LCAiSW5zdWZmaWNpZW50IE1lbW9y eVxuIik7CisKKwltZW1zZXQocHcsIDEsIHBhZ2Vfc2l6ZSk7CisKKwl3cml0ZV9ndWVzdF9wYWdl KHRlc3RfZ3BhLCBwdyk7CisJVEVTVF9BU1NFUlQobWVtY21wKHB3LCB0ZXN0X2h2YSwgcGFnZV9z aXplKSA9PSAwLAorCQkiV3JpdGUgcGFnZSB0ZXN0IGZhaWxlZCIpOworCisJcHIgPSBtYWxsb2Mo cGFnZV9zaXplKTsKKwlURVNUX0FTU0VSVChwciwgIkluc3VmZmljaWVudCBNZW1vcnlcbiIpOwor CisJcmVhZF9ndWVzdF9wYWdlKHRlc3RfZ3BhLCBwcik7CisJVEVTVF9BU1NFUlQobWVtY21wKHB3 LCBwciwgcGFnZV9zaXplKSA9PSAwLAorCQkiUmVhZCBwYWdlIHRlc3QgZmFpbGVkIik7CisKKwly ZWFkX3dpdGhfaW52YWxpZF9hcmd1bWVudHModGVzdF9ncGEsIDAsIHByKTsKKwl3cml0ZV93aXRo X2ludmFsaWRfYXJndW1lbnRzKHRlc3RfZ3BhLCAwLCBwdyk7CisJd3JpdGVfaW52YWxpZF9ndWVz dF9wYWdlKHZtLCBwdyk7CisKKwlmcmVlKHB3KTsKKwlmcmVlKHByKTsKKworCXJlYWRfaW52YWxp ZF9ndWVzdF9wYWdlKHZtKTsKK30KKwogc3RhdGljIHZvaWQgdGVzdF9pbnRyb3NwZWN0aW9uKHN0 cnVjdCBrdm1fdm0gKnZtKQogeworCXNyYW5kb20odGltZSgwKSk7CiAJc2V0dXBfc29ja2V0KCk7 CiAJaG9va19pbnRyb3NwZWN0aW9uKHZtKTsKIApAQCAtNDM5LDEwICs1NTAsMjAgQEAgc3RhdGlj IHZvaWQgdGVzdF9pbnRyb3NwZWN0aW9uKHN0cnVjdCBrdm1fdm0gKnZtKQogCXRlc3RfY21kX3Zt X2dldF9pbmZvKCk7CiAJdGVzdF9ldmVudF91bmhvb2sodm0pOwogCXRlc3RfY21kX3ZtX2NvbnRy b2xfZXZlbnRzKHZtKTsKKwl0ZXN0X21lbW9yeV9hY2Nlc3Modm0pOwogCiAJdW5ob29rX2ludHJv c3BlY3Rpb24odm0pOwogfQogCitzdGF0aWMgdm9pZCBzZXR1cF90ZXN0X3BhZ2VzKHN0cnVjdCBr dm1fdm0gKnZtKQoreworCXRlc3RfZ3ZhID0gdm1fdmFkZHJfYWxsb2NfcGFnZSh2bSk7CisJc3lu Y19nbG9iYWxfdG9fZ3Vlc3Qodm0sIHRlc3RfZ3ZhKTsKKworCXRlc3RfaHZhID0gYWRkcl9ndmEy aHZhKHZtLCB0ZXN0X2d2YSk7CisJdGVzdF9ncGEgPSBhZGRyX2d2YTJncGEodm0sIHRlc3RfZ3Zh KTsKK30KKwogaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKmFyZ3ZbXSkKIHsKIAlzdHJ1Y3Qga3Zt X3ZtICp2bTsKQEAgLTQ1NSw2ICs1NzYsOSBAQCBpbnQgbWFpbihpbnQgYXJnYywgY2hhciAqYXJn dltdKQogCXZtID0gdm1fY3JlYXRlX2RlZmF1bHQoVkNQVV9JRCwgMCwgTlVMTCk7CiAJdmNwdV9z ZXRfY3B1aWQodm0sIFZDUFVfSUQsIGt2bV9nZXRfc3VwcG9ydGVkX2NwdWlkKCkpOwogCisJcGFn ZV9zaXplID0gZ2V0cGFnZXNpemUoKTsKKwlzZXR1cF90ZXN0X3BhZ2VzKHZtKTsKKwogCXRlc3Rf aW50cm9zcGVjdGlvbih2bSk7CiAKIAlrdm1fdm1fZnJlZSh2bSk7CmRpZmYgLS1naXQgYS92aXJ0 L2t2bS9pbnRyb3NwZWN0aW9uL2t2bWkuYyBiL3ZpcnQva3ZtL2ludHJvc3BlY3Rpb24va3ZtaS5j CmluZGV4IDZhNTdkNDViNjZlYy4uMjA3ZGFiYjhiMDQwIDEwMDY0NAotLS0gYS92aXJ0L2t2bS9p bnRyb3NwZWN0aW9uL2t2bWkuYworKysgYi92aXJ0L2t2bS9pbnRyb3NwZWN0aW9uL2t2bWkuYwpA QCAtNSw3ICs1LDkgQEAKICAqIENvcHlyaWdodCAoQykgMjAxNy0yMDIxIEJpdGRlZmVuZGVyIFMu Ui5MLgogICoKICAqLworI2luY2x1ZGUgPGxpbnV4L21tdV9jb250ZXh0Lmg+CiAjaW5jbHVkZSA8 bGludXgva3RocmVhZC5oPgorI2luY2x1ZGUgPGxpbnV4L2hpZ2htZW0uaD4KICNpbmNsdWRlICJr dm1pX2ludC5oIgogCiAjZGVmaW5lIEtWTUlfTlVNX0NPTU1BTkRTIF9fY21wKChpbnQpS1ZNSV9O RVhUX1ZNX01FU1NBR0UsIFwKQEAgLTQ1MywzICs0NTUsOTkgQEAgaW50IGt2bWlfY21kX3ZtX2Nv bnRyb2xfZXZlbnRzKHN0cnVjdCBrdm1faW50cm9zcGVjdGlvbiAqa3ZtaSwKIAogCXJldHVybiAw OwogfQorCitzdGF0aWMgbG9uZworZ2V0X3VzZXJfcGFnZXNfcmVtb3RlX3VubG9ja2VkKHN0cnVj dCBtbV9zdHJ1Y3QgKm1tLCB1bnNpZ25lZCBsb25nIHN0YXJ0LAorCQkJCXVuc2lnbmVkIGxvbmcg bnJfcGFnZXMsIHVuc2lnbmVkIGludCBndXBfZmxhZ3MsCisJCQkJc3RydWN0IHBhZ2UgKipwYWdl cykKK3sKKwlzdHJ1Y3Qgdm1fYXJlYV9zdHJ1Y3QgKip2bWFzID0gTlVMTDsKKwlpbnQgbG9ja2Vk ID0gMTsKKwlsb25nIHI7CisKKwltbWFwX3JlYWRfbG9jayhtbSk7CisJciA9IGdldF91c2VyX3Bh Z2VzX3JlbW90ZShtbSwgc3RhcnQsIG5yX3BhZ2VzLCBndXBfZmxhZ3MsCisJCQkJICBwYWdlcywg dm1hcywgJmxvY2tlZCk7CisJaWYgKGxvY2tlZCkKKwkJbW1hcF9yZWFkX3VubG9jayhtbSk7CisK KwlyZXR1cm4gcjsKK30KKworc3RhdGljIHZvaWQgKmdldF9wYWdlX3B0cihzdHJ1Y3Qga3ZtICpr dm0sIGdwYV90IGdwYSwgc3RydWN0IHBhZ2UgKipwYWdlLAorCQkJICBib29sIHdyaXRlLCBpbnQg KnNyY3VfaWR4KQoreworCXVuc2lnbmVkIGludCBmbGFncyA9IHdyaXRlID8gRk9MTF9XUklURSA6 IDA7CisJdW5zaWduZWQgbG9uZyBodmE7CisKKwkqcGFnZSA9IE5VTEw7CisKKwkqc3JjdV9pZHgg PSBzcmN1X3JlYWRfbG9jaygma3ZtLT5zcmN1KTsKKwlodmEgPSBnZm5fdG9faHZhKGt2bSwgZ3Bh X3RvX2dmbihncGEpKTsKKworCWlmIChrdm1faXNfZXJyb3JfaHZhKGh2YSkpCisJCWdvdG8gb3V0 X2VycjsKKworCWlmIChnZXRfdXNlcl9wYWdlc19yZW1vdGVfdW5sb2NrZWQoa3ZtLT5tbSwgaHZh LCAxLCBmbGFncywgcGFnZSkgIT0gMSkKKwkJZ290byBvdXRfZXJyOworCisJcmV0dXJuIHdyaXRl ID8ga21hcF9hdG9taWMoKnBhZ2UpIDoga21hcCgqcGFnZSk7CitvdXRfZXJyOgorCXNyY3VfcmVh ZF91bmxvY2soJmt2bS0+c3JjdSwgKnNyY3VfaWR4KTsKKwlyZXR1cm4gTlVMTDsKK30KKworc3Rh dGljIHZvaWQgcHV0X3BhZ2VfcHRyKHN0cnVjdCBrdm0gKmt2bSwgdm9pZCAqcHRyLCBzdHJ1Y3Qg cGFnZSAqcGFnZSwKKwkJCSBib29sIHdyaXRlLCBpbnQgc3JjdV9pZHgpCit7CisJaWYgKHdyaXRl KQorCQlrdW5tYXBfYXRvbWljKHB0cik7CisJZWxzZQorCQlrdW5tYXAocHRyKTsKKworCXB1dF9w YWdlKHBhZ2UpOworCisJc3JjdV9yZWFkX3VubG9jaygma3ZtLT5zcmN1LCBzcmN1X2lkeCk7Cit9 CisKK2ludCBrdm1pX2NtZF9yZWFkX3BoeXNpY2FsKHN0cnVjdCBrdm0gKmt2bSwgdTY0IGdwYSwg c2l6ZV90IHNpemUsCisJCQkgICBpbnQgKCpzZW5kKShzdHJ1Y3Qga3ZtX2ludHJvc3BlY3Rpb24g KiwKKwkJCQkJY29uc3Qgc3RydWN0IGt2bWlfbXNnX2hkciAqLAorCQkJCQlpbnQgZXJyLCBjb25z dCB2b2lkICpidWYsIHNpemVfdCksCisJCQkgICBjb25zdCBzdHJ1Y3Qga3ZtaV9tc2dfaGRyICpj dHgpCit7CisJc3RydWN0IHBhZ2UgKnBhZ2U7CisJdm9pZCAqcHRyX3BhZ2U7CisJaW50IHNyY3Vf aWR4OworCWludCBlcnI7CisKKwlwdHJfcGFnZSA9IGdldF9wYWdlX3B0cihrdm0sIGdwYSwgJnBh Z2UsIGZhbHNlLCAmc3JjdV9pZHgpOworCWlmICghcHRyX3BhZ2UpIHsKKwkJZXJyID0gc2VuZChL Vk1JKGt2bSksIGN0eCwgLUtWTV9FTk9FTlQsIE5VTEwsIDApOworCX0gZWxzZSB7CisJCWVyciA9 IHNlbmQoS1ZNSShrdm0pLCBjdHgsIDAsCisJCQkgICBwdHJfcGFnZSArIChncGEgJiB+UEFHRV9N QVNLKSwgc2l6ZSk7CisKKwkJcHV0X3BhZ2VfcHRyKGt2bSwgcHRyX3BhZ2UsIHBhZ2UsIGZhbHNl LCBzcmN1X2lkeCk7CisJfQorCisJcmV0dXJuIGVycjsKK30KKworaW50IGt2bWlfY21kX3dyaXRl X3BoeXNpY2FsKHN0cnVjdCBrdm0gKmt2bSwgdTY0IGdwYSwgc2l6ZV90IHNpemUsCisJCQkgICAg Y29uc3Qgdm9pZCAqYnVmKQoreworCWludCBlYyA9IC1LVk1fRU5PRU5UOworCXN0cnVjdCBwYWdl ICpwYWdlOworCWludCBzcmN1X2lkeDsKKwl2b2lkICpwdHI7CisKKwlwdHIgPSBnZXRfcGFnZV9w dHIoa3ZtLCBncGEsICZwYWdlLCB0cnVlLCAmc3JjdV9pZHgpOworCWlmIChwdHIpIHsKKwkJbWVt Y3B5KHB0ciArIChncGEgJiB+UEFHRV9NQVNLKSwgYnVmLCBzaXplKTsKKwkJcHV0X3BhZ2VfcHRy KGt2bSwgcHRyLCBwYWdlLCB0cnVlLCBzcmN1X2lkeCk7CisJCWVjID0gMDsKKwl9CisKKwlyZXR1 cm4gZWM7Cit9CmRpZmYgLS1naXQgYS92aXJ0L2t2bS9pbnRyb3NwZWN0aW9uL2t2bWlfaW50Lmgg Yi92aXJ0L2t2bS9pbnRyb3NwZWN0aW9uL2t2bWlfaW50LmgKaW5kZXggOTg3NTEzZDZjMWE3Li5i N2M4NzMwZTdlNmQgMTAwNjQ0Ci0tLSBhL3ZpcnQva3ZtL2ludHJvc3BlY3Rpb24va3ZtaV9pbnQu aAorKysgYi92aXJ0L2t2bS9pbnRyb3NwZWN0aW9uL2t2bWlfaW50LmgKQEAgLTI5LDYgKzI5LDEz IEBAIGJvb2wga3ZtaV9pc19rbm93bl9ldmVudCh1MTYgaWQpOwogYm9vbCBrdm1pX2lzX2tub3du X3ZtX2V2ZW50KHUxNiBpZCk7CiBpbnQga3ZtaV9jbWRfdm1fY29udHJvbF9ldmVudHMoc3RydWN0 IGt2bV9pbnRyb3NwZWN0aW9uICprdm1pLAogCQkJICAgICAgIHUxNiBldmVudF9pZCwgYm9vbCBl bmFibGUpOworaW50IGt2bWlfY21kX3JlYWRfcGh5c2ljYWwoc3RydWN0IGt2bSAqa3ZtLCB1NjQg Z3BhLCBzaXplX3Qgc2l6ZSwKKwkJCSAgIGludCAoKnNlbmQpKHN0cnVjdCBrdm1faW50cm9zcGVj dGlvbiAqLAorCQkJCQljb25zdCBzdHJ1Y3Qga3ZtaV9tc2dfaGRyKiwKKwkJCQkJaW50IGVyciwg Y29uc3Qgdm9pZCAqYnVmLCBzaXplX3QpLAorCQkJICAgY29uc3Qgc3RydWN0IGt2bWlfbXNnX2hk ciAqY3R4KTsKK2ludCBrdm1pX2NtZF93cml0ZV9waHlzaWNhbChzdHJ1Y3Qga3ZtICprdm0sIHU2 NCBncGEsIHNpemVfdCBzaXplLAorCQkJICAgIGNvbnN0IHZvaWQgKmJ1Zik7CiAKIC8qIGFyY2gg Ki8KIHZvaWQga3ZtaV9hcmNoX2luaXRfdmNwdV9ldmVudHNfbWFzayh1bnNpZ25lZCBsb25nICpz dXBwb3J0ZWQpOwpkaWZmIC0tZ2l0IGEvdmlydC9rdm0vaW50cm9zcGVjdGlvbi9rdm1pX21zZy5j IGIvdmlydC9rdm0vaW50cm9zcGVjdGlvbi9rdm1pX21zZy5jCmluZGV4IGIyYTVkZDNkMjE5YS4u Njk3YzMwN2VhNzQ1IDEwMDY0NAotLS0gYS92aXJ0L2t2bS9pbnRyb3NwZWN0aW9uL2t2bWlfbXNn LmMKKysrIGIvdmlydC9rdm0vaW50cm9zcGVjdGlvbi9rdm1pX21zZy5jCkBAIC0xODIsNiArMTgy LDQ4IEBAIHN0YXRpYyBpbnQgaGFuZGxlX3ZtX2NvbnRyb2xfZXZlbnRzKHN0cnVjdCBrdm1faW50 cm9zcGVjdGlvbiAqa3ZtaSwKIAlyZXR1cm4ga3ZtaV9tc2dfdm1fcmVwbHkoa3ZtaSwgbXNnLCBl YywgTlVMTCwgMCk7CiB9CiAKK3N0YXRpYyBib29sIGludmFsaWRfcGFnZV9hY2Nlc3ModTY0IGdw YSwgdTY0IHNpemUpCit7CisJdTY0IG9mZiA9IGdwYSAmIH5QQUdFX01BU0s7CisKKwlyZXR1cm4g KHNpemUgPT0gMCB8fCBzaXplID4gUEFHRV9TSVpFIHx8IG9mZiArIHNpemUgPiBQQUdFX1NJWkUp OworfQorCitzdGF0aWMgaW50IGhhbmRsZV92bV9yZWFkX3BoeXNpY2FsKHN0cnVjdCBrdm1faW50 cm9zcGVjdGlvbiAqa3ZtaSwKKwkJCQkgICBjb25zdCBzdHJ1Y3Qga3ZtaV9tc2dfaGRyICptc2cs CisJCQkJICAgY29uc3Qgdm9pZCAqX3JlcSkKK3sKKwljb25zdCBzdHJ1Y3Qga3ZtaV92bV9yZWFk X3BoeXNpY2FsICpyZXEgPSBfcmVxOworCisJaWYgKGludmFsaWRfcGFnZV9hY2Nlc3MocmVxLT5n cGEsIHJlcS0+c2l6ZSkgfHwKKwkgICAgcmVxLT5wYWRkaW5nMSB8fCByZXEtPnBhZGRpbmcyKQor CQlyZXR1cm4ga3ZtaV9tc2dfdm1fcmVwbHkoa3ZtaSwgbXNnLCAtS1ZNX0VJTlZBTCwgTlVMTCwg MCk7CisKKwlyZXR1cm4ga3ZtaV9jbWRfcmVhZF9waHlzaWNhbChrdm1pLT5rdm0sIHJlcS0+Z3Bh LCByZXEtPnNpemUsCisJCQkJICAgICAga3ZtaV9tc2dfdm1fcmVwbHksIG1zZyk7Cit9CisKK3N0 YXRpYyBpbnQgaGFuZGxlX3ZtX3dyaXRlX3BoeXNpY2FsKHN0cnVjdCBrdm1faW50cm9zcGVjdGlv biAqa3ZtaSwKKwkJCQkgICAgY29uc3Qgc3RydWN0IGt2bWlfbXNnX2hkciAqbXNnLAorCQkJCSAg ICBjb25zdCB2b2lkICpfcmVxKQoreworCWNvbnN0IHN0cnVjdCBrdm1pX3ZtX3dyaXRlX3BoeXNp Y2FsICpyZXEgPSBfcmVxOworCWludCBlYzsKKworCWlmIChzdHJ1Y3Rfc2l6ZShyZXEsIGRhdGEs IHJlcS0+c2l6ZSkgPiBtc2ctPnNpemUpCisJCXJldHVybiAtRUlOVkFMOworCisJaWYgKGludmFs aWRfcGFnZV9hY2Nlc3MocmVxLT5ncGEsIHJlcS0+c2l6ZSkpCisJCWVjID0gLUtWTV9FSU5WQUw7 CisJZWxzZSBpZiAocmVxLT5wYWRkaW5nMSB8fCByZXEtPnBhZGRpbmcyKQorCQllYyA9IC1LVk1f RUlOVkFMOworCWVsc2UKKwkJZWMgPSBrdm1pX2NtZF93cml0ZV9waHlzaWNhbChrdm1pLT5rdm0s IHJlcS0+Z3BhLAorCQkJCQkgICAgIHJlcS0+c2l6ZSwgcmVxLT5kYXRhKTsKKworCXJldHVybiBr dm1pX21zZ192bV9yZXBseShrdm1pLCBtc2csIGVjLCBOVUxMLCAwKTsKK30KKwogLyoKICAqIFRo ZXNlIGNvbW1hbmRzIGFyZSBleGVjdXRlZCBieSB0aGUgcmVjZWl2aW5nIHRocmVhZC4KICAqLwpA QCAtMTkxLDYgKzIzMyw4IEBAIHN0YXRpYyBjb25zdCBrdm1pX3ZtX21zZ19mY3QgbXNnX3ZtW10g PSB7CiAJW0tWTUlfVk1fQ0hFQ0tfRVZFTlRdICAgID0gaGFuZGxlX3ZtX2NoZWNrX2V2ZW50LAog CVtLVk1JX1ZNX0NPTlRST0xfRVZFTlRTXSA9IGhhbmRsZV92bV9jb250cm9sX2V2ZW50cywKIAlb S1ZNSV9WTV9HRVRfSU5GT10gICAgICAgPSBoYW5kbGVfdm1fZ2V0X2luZm8sCisJW0tWTUlfVk1f UkVBRF9QSFlTSUNBTF0gID0gaGFuZGxlX3ZtX3JlYWRfcGh5c2ljYWwsCisJW0tWTUlfVk1fV1JJ VEVfUEhZU0lDQUxdID0gaGFuZGxlX3ZtX3dyaXRlX3BoeXNpY2FsLAogfTsKIAogc3RhdGljIGt2 bWlfdm1fbXNnX2ZjdCBnZXRfdm1fbXNnX2hhbmRsZXIodTE2IGlkKQpfX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpWaXJ0dWFsaXphdGlvbiBtYWlsaW5nIGxp c3QKVmlydHVhbGl6YXRpb25AbGlzdHMubGludXgtZm91bmRhdGlvbi5vcmcKaHR0cHM6Ly9saXN0 cy5saW51eGZvdW5kYXRpb24ub3JnL21haWxtYW4vbGlzdGluZm8vdmlydHVhbGl6YXRpb24=