From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=unavailable 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 827F6C433E0 for ; Thu, 9 Jul 2020 14:43: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 43FAE2073A for ; Thu, 9 Jul 2020 14:43:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="1rt2GZCz"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="Xgaznaap" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 43FAE2073A Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org 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-Type: Content-Transfer-Encoding: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=B0+SzyD+Fu9OWr1TVjuAcSHM9hFGHdQl6ieEaF4n80U=; b=1rt2GZCz7Mzh+QGWYlwwpDg3u tr1jzkgchAbwb5rSFuecWc1mc4ptzuPbdlNB7D4tKZQSEMSWCmEdrgALn6s7sZQBJceUuitvLry7R JSnpKZe4UG3tCaq8azgFwUVgpXCtMlhVNpu6ikFdeiVffoYf8gf1C6PDKxBh6QbvNjyeg7KQDh4lG Uv9Wvkw9B5EtBeyq5u0BwZjnlt57xcBFQDEDi128J9cOjtKkGa76HNt7pOkCW2+p+W6z6Nu2bNML9 4ruJLSe5S/+/TuqFlhTycAgKkBY2N3UeaQ3PX4qyFA8pKKZ28ZA/SMWJF/8R/0c6AqgGYTRjETM9B 9STOxFd0A==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jtXkR-0002rX-96; Thu, 09 Jul 2020 14:42:03 +0000 Received: from mail-qk1-x741.google.com ([2607:f8b0:4864:20::741]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jtXkM-0002pv-RT for linux-arm-kernel@lists.infradead.org; Thu, 09 Jul 2020 14:42:00 +0000 Received: by mail-qk1-x741.google.com with SMTP id r22so1947526qke.13 for ; Thu, 09 Jul 2020 07:41:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-language:content-transfer-encoding; bh=nafGpM13Vsm/N8B3umcbDh7pBbAU3raV0eC8u9Prpas=; b=XgaznaapjDXnafbbVHJvudC65ei40sYkYSenyl9AvnpQLAhQYxvgBbxsoumTXRm0tG E0ZPkK2Diw6SsIA2WWq8oAiu/D83o//9SFEdbOdfxkymYK621eWqNXDte7UChbAAwZXV fWdZIWQa+N2EhczHj5OkEXgts4Gc/eaEQS2hkxnVJIs7ZPRohRmqbJEtHgj7m2MXT0TC J+uivzO8QtKMHEaF3cgKXizYovh55mFWTabfoKWWdMf9EKxIyfTRj/c6xZj9Ol7TnAyG NEvZ7o+Abz6XOVcovErK1lx9akQeUvQyBrNBidqVSTMenVkA5fFjvDIL7CQAKM+z90GD 4Yfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=nafGpM13Vsm/N8B3umcbDh7pBbAU3raV0eC8u9Prpas=; b=Usp+g7hi/iOfjGZn+rXXQFhEO7rEFUQlP+Ozuj1dMdimWO9nh/QmSuGhPHdnciA4z5 /VduzFw5xtcvF9aXK7SFxXeTRz2EqtoZ/a1jgZbMUF1WS25qem3Nt2ucEGpD3cn8NQTC upTa42LxWWWPIveactkRPzignNcOlNLJRIQjyx/mn8no4WOpGYdxA3CAhsyGr4wymt2U dASqCfUZNPZlhByBns/48lzYc7vaoHIM1gHGi6vDSwuVuZ0fJT7WMqVSsBxNCrEKvi42 XPqnGl4lyL00v/1bWz0S26n5Gmay5fZGYXz1I+CflaxWYZXEd+UJ7Zk4oFaJ+kGkrRn/ 5tYg== X-Gm-Message-State: AOAM531zkYXLt+RFf6b9PTablOdvFNPAeRZ8iDBNE/6eDx8LpndkV23t r+dipm/HY4lzlpt2xJrcOvMHEg== X-Google-Smtp-Source: ABdhPJzDoFc4ToiOoK74IhMK3u/RMrIp0fqH14hExbgTTNSE7bTvyjJrOV7uPrsEHTj+2+9lg951jg== X-Received: by 2002:a37:8384:: with SMTP id f126mr63661522qkd.471.1594305715369; Thu, 09 Jul 2020 07:41:55 -0700 (PDT) Received: from ?IPv6:2804:7f0:8283:20c3:e9c8:8185:17e5:d78b? ([2804:7f0:8283:20c3:e9c8:8185:17e5:d78b]) by smtp.gmail.com with ESMTPSA id 16sm3703903qkn.106.2020.07.09.07.41.49 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 09 Jul 2020 07:41:54 -0700 (PDT) Subject: Re: [PATCH v6 20/26] arm64: mte: Add PTRACE_{PEEK,POKE}MTETAGS support To: Catalin Marinas , linux-arm-kernel@lists.infradead.org References: <20200703153718.16973-1-catalin.marinas@arm.com> <20200703153718.16973-21-catalin.marinas@arm.com> From: Luis Machado Message-ID: Date: Thu, 9 Jul 2020 11:41:47 -0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.8.0 MIME-Version: 1.0 In-Reply-To: <20200703153718.16973-21-catalin.marinas@arm.com> Content-Language: en-US X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200709_104158_944310_F637771A X-CRM114-Status: GOOD ( 44.41 ) 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: linux-arch@vger.kernel.org, Omair Javaid , Szabolcs Nagy , Andrey Konovalov , Kevin Brodsky , Peter Collingbourne , linux-mm@kvack.org, Alan Hayward , Andrew Morton , Vincenzo Frascino , Will Deacon , Dave P Martin Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="us-ascii"; Format="flowed" Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Hi, FYI, I've exercised this in GDB (with the MTE support patches applied) within system QEMU and things seem to be working as expected. The ptrace requests are being recognized, the tags are being fetched/stored as commanded and the SIGINFO data contains the fault address when a tag violation occurs. I plan to remove the initial core file support code since this is still undefined, and will wait for inclusion of the tagged address control changes so GDB can expose that additional register. On 7/3/20 12:37 PM, Catalin Marinas wrote: > Add support for bulk setting/getting of the MTE tags in a tracee's > address space at 'addr' in the ptrace() syscall prototype. 'data' points > to a struct iovec in the tracer's address space with iov_base > representing the address of a tracer's buffer of length iov_len. The > tags to be copied to/from the tracer's buffer are stored as one tag per > byte. > > On successfully copying at least one tag, ptrace() returns 0 and updates > the tracer's iov_len with the number of tags copied. In case of error, > either -EIO or -EFAULT is returned, trying to follow the ptrace() man > page. > > Note that the tag copying functions are not performance critical, > therefore they lack optimisations found in typical memory copy routines. > > Signed-off-by: Catalin Marinas > Cc: Will Deacon > Cc: Alan Hayward > Cc: Luis Machado > Cc: Omair Javaid > --- > > Notes: > v4: > - Following the change to only clear the tags in a page if it is mapped > to user with PROT_MTE, ptrace() now will refuse to access tags in > pages not previously mapped with PROT_MTE (PG_mte_tagged set). This is > primarily to avoid leaking uninitialised tags to user via ptrace(). > - Fix SYM_FUNC_END argument typo. > - Rename MTE_ALLOC_* to MTE_GRANULE_*. > - Use uao_user_alternative for the user access in case we ever want to > call mte_copy_tags_* with a kernel buffer. It also matches the other > uaccess routines in the kernel. > - Simplify arch_ptrace() slightly. > - Reorder down_write_killable() with access_ok() in > __access_remote_tags(). > - Handle copy length 0 in mte_copy_tags_{to,from}_user(). > - Use put_user() instead of __put_user(). > > New in v3. > > arch/arm64/include/asm/mte.h | 17 ++++ > arch/arm64/include/uapi/asm/ptrace.h | 3 + > arch/arm64/kernel/mte.c | 139 +++++++++++++++++++++++++++ > arch/arm64/kernel/ptrace.c | 7 ++ > arch/arm64/lib/mte.S | 53 ++++++++++ > 5 files changed, 219 insertions(+) > > diff --git a/arch/arm64/include/asm/mte.h b/arch/arm64/include/asm/mte.h > index c93047eff9fe..5fe9678d2e14 100644 > --- a/arch/arm64/include/asm/mte.h > +++ b/arch/arm64/include/asm/mte.h > @@ -5,6 +5,11 @@ > #ifndef __ASM_MTE_H > #define __ASM_MTE_H > > +#define MTE_GRANULE_SIZE UL(16) > +#define MTE_GRANULE_MASK (~(MTE_GRANULE_SIZE - 1)) > +#define MTE_TAG_SHIFT 56 > +#define MTE_TAG_SIZE 4 > + > #ifndef __ASSEMBLY__ > > #include > @@ -12,6 +17,10 @@ > #include > > void mte_clear_page_tags(void *addr); > +unsigned long mte_copy_tags_from_user(void *to, const void __user *from, > + unsigned long n); > +unsigned long mte_copy_tags_to_user(void __user *to, void *from, > + unsigned long n); > > #ifdef CONFIG_ARM64_MTE > > @@ -25,6 +34,8 @@ void mte_thread_switch(struct task_struct *next); > void mte_suspend_exit(void); > long set_mte_ctrl(unsigned long arg); > long get_mte_ctrl(void); > +int mte_ptrace_copy_tags(struct task_struct *child, long request, > + unsigned long addr, unsigned long data); > > #else > > @@ -54,6 +65,12 @@ static inline long get_mte_ctrl(void) > { > return 0; > } > +static inline int mte_ptrace_copy_tags(struct task_struct *child, > + long request, unsigned long addr, > + unsigned long data) > +{ > + return -EIO; > +} > > #endif > > diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h > index 06413d9f2341..758ae984ff97 100644 > --- a/arch/arm64/include/uapi/asm/ptrace.h > +++ b/arch/arm64/include/uapi/asm/ptrace.h > @@ -76,6 +76,9 @@ > /* syscall emulation path in ptrace */ > #define PTRACE_SYSEMU 31 > #define PTRACE_SYSEMU_SINGLESTEP 32 > +/* MTE allocation tag access */ > +#define PTRACE_PEEKMTETAGS 33 > +#define PTRACE_POKEMTETAGS 34 > > #ifndef __ASSEMBLY__ > > diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c > index 09cf76fc1090..3e08aea56e7a 100644 > --- a/arch/arm64/kernel/mte.c > +++ b/arch/arm64/kernel/mte.c > @@ -4,14 +4,18 @@ > */ > > #include > +#include > #include > #include > #include > +#include > #include > #include > +#include > > #include > #include > +#include > #include > > void mte_sync_tags(pte_t *ptep, pte_t pte) > @@ -173,3 +177,138 @@ long get_mte_ctrl(void) > > return ret; > } > + > +/* > + * Access MTE tags in another process' address space as given in mm. Update > + * the number of tags copied. Return 0 if any tags copied, error otherwise. > + * Inspired by __access_remote_vm(). > + */ > +static int __access_remote_tags(struct task_struct *tsk, struct mm_struct *mm, > + unsigned long addr, struct iovec *kiov, > + unsigned int gup_flags) > +{ > + struct vm_area_struct *vma; > + void __user *buf = kiov->iov_base; > + size_t len = kiov->iov_len; > + int ret; > + int write = gup_flags & FOLL_WRITE; > + > + if (!access_ok(buf, len)) > + return -EFAULT; > + > + if (mmap_read_lock_killable(mm)) > + return -EIO; > + > + while (len) { > + unsigned long tags, offset; > + void *maddr; > + struct page *page = NULL; > + > + ret = get_user_pages_remote(tsk, mm, addr, 1, gup_flags, > + &page, &vma, NULL); > + if (ret <= 0) > + break; > + > + /* > + * Only copy tags if the page has been mapped as PROT_MTE > + * (PG_mte_tagged set). Otherwise the tags are not valid and > + * not accessible to user. Moreover, an mprotect(PROT_MTE) > + * would cause the existing tags to be cleared if the page > + * was never mapped with PROT_MTE. > + */ > + if (!test_bit(PG_mte_tagged, &page->flags)) { > + ret = -EOPNOTSUPP; > + put_page(page); > + break; > + } > + > + /* limit access to the end of the page */ > + offset = offset_in_page(addr); > + tags = min(len, (PAGE_SIZE - offset) / MTE_GRANULE_SIZE); > + > + maddr = page_address(page); > + if (write) { > + tags = mte_copy_tags_from_user(maddr + offset, buf, tags); > + set_page_dirty_lock(page); > + } else { > + tags = mte_copy_tags_to_user(buf, maddr + offset, tags); > + } > + put_page(page); > + > + /* error accessing the tracer's buffer */ > + if (!tags) > + break; > + > + len -= tags; > + buf += tags; > + addr += tags * MTE_GRANULE_SIZE; > + } > + mmap_read_unlock(mm); > + > + /* return an error if no tags copied */ > + kiov->iov_len = buf - kiov->iov_base; > + if (!kiov->iov_len) { > + /* check for error accessing the tracee's address space */ > + if (ret <= 0) > + return -EIO; > + else > + return -EFAULT; > + } > + > + return 0; > +} > + > +/* > + * Copy MTE tags in another process' address space at 'addr' to/from tracer's > + * iovec buffer. Return 0 on success. Inspired by ptrace_access_vm(). > + */ > +static int access_remote_tags(struct task_struct *tsk, unsigned long addr, > + struct iovec *kiov, unsigned int gup_flags) > +{ > + struct mm_struct *mm; > + int ret; > + > + mm = get_task_mm(tsk); > + if (!mm) > + return -EPERM; > + > + if (!tsk->ptrace || (current != tsk->parent) || > + ((get_dumpable(mm) != SUID_DUMP_USER) && > + !ptracer_capable(tsk, mm->user_ns))) { > + mmput(mm); > + return -EPERM; > + } > + > + ret = __access_remote_tags(tsk, mm, addr, kiov, gup_flags); > + mmput(mm); > + > + return ret; > +} > + > +int mte_ptrace_copy_tags(struct task_struct *child, long request, > + unsigned long addr, unsigned long data) > +{ > + int ret; > + struct iovec kiov; > + struct iovec __user *uiov = (void __user *)data; > + unsigned int gup_flags = FOLL_FORCE; > + > + if (!system_supports_mte()) > + return -EIO; > + > + if (get_user(kiov.iov_base, &uiov->iov_base) || > + get_user(kiov.iov_len, &uiov->iov_len)) > + return -EFAULT; > + > + if (request == PTRACE_POKEMTETAGS) > + gup_flags |= FOLL_WRITE; > + > + /* align addr to the MTE tag granule */ > + addr &= MTE_GRANULE_MASK; > + > + ret = access_remote_tags(child, addr, &kiov, gup_flags); > + if (!ret) > + ret = put_user(kiov.iov_len, &uiov->iov_len); > + > + return ret; > +} > diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c > index 4582014dda25..653a03598c75 100644 > --- a/arch/arm64/kernel/ptrace.c > +++ b/arch/arm64/kernel/ptrace.c > @@ -34,6 +34,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -1796,6 +1797,12 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) > long arch_ptrace(struct task_struct *child, long request, > unsigned long addr, unsigned long data) > { > + switch (request) { > + case PTRACE_PEEKMTETAGS: > + case PTRACE_POKEMTETAGS: > + return mte_ptrace_copy_tags(child, request, addr, data); > + } > + > return ptrace_request(child, request, addr, data); > } > > diff --git a/arch/arm64/lib/mte.S b/arch/arm64/lib/mte.S > index 3c3d0edbbca3..434f81d9a180 100644 > --- a/arch/arm64/lib/mte.S > +++ b/arch/arm64/lib/mte.S > @@ -4,7 +4,9 @@ > */ > #include > > +#include > #include > +#include > #include > #include > > @@ -51,3 +53,54 @@ SYM_FUNC_START(mte_copy_page_tags) > b.ne 1b > ret > SYM_FUNC_END(mte_copy_page_tags) > + > +/* > + * Read tags from a user buffer (one tag per byte) and set the corresponding > + * tags at the given kernel address. Used by PTRACE_POKEMTETAGS. > + * x0 - kernel address (to) > + * x1 - user buffer (from) > + * x2 - number of tags/bytes (n) > + * Returns: > + * x0 - number of tags read/set > + */ > +SYM_FUNC_START(mte_copy_tags_from_user) > + mov x3, x1 > + cbz x2, 2f > +1: > + uao_user_alternative 2f, ldrb, ldtrb, w4, x1, 0 > + lsl x4, x4, #MTE_TAG_SHIFT > + stg x4, [x0], #MTE_GRANULE_SIZE > + add x1, x1, #1 > + subs x2, x2, #1 > + b.ne 1b > + > + // exception handling and function return > +2: sub x0, x1, x3 // update the number of tags set > + ret > +SYM_FUNC_END(mte_copy_tags_from_user) > + > +/* > + * Get the tags from a kernel address range and write the tag values to the > + * given user buffer (one tag per byte). Used by PTRACE_PEEKMTETAGS. > + * x0 - user buffer (to) > + * x1 - kernel address (from) > + * x2 - number of tags/bytes (n) > + * Returns: > + * x0 - number of tags read/set > + */ > +SYM_FUNC_START(mte_copy_tags_to_user) > + mov x3, x0 > + cbz x2, 2f > +1: > + ldg x4, [x1] > + ubfx x4, x4, #MTE_TAG_SHIFT, #MTE_TAG_SIZE > + uao_user_alternative 2f, strb, sttrb, w4, x0, 0 > + add x0, x0, #1 > + add x1, x1, #MTE_GRANULE_SIZE > + subs x2, x2, #1 > + b.ne 1b > + > + // exception handling and function return > +2: sub x0, x0, x3 // update the number of tags copied > + ret > +SYM_FUNC_END(mte_copy_tags_to_user) > _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel