From patchwork Mon Sep 30 16:50:17 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Will Newton X-Patchwork-Id: 20710 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ye0-f200.google.com (mail-ye0-f200.google.com [209.85.213.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id A40D325A2B for ; Mon, 30 Sep 2013 16:50:22 +0000 (UTC) Received: by mail-ye0-f200.google.com with SMTP id r5sf5215715yen.3 for ; Mon, 30 Sep 2013 09:50:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:message-id:date:from:user-agent :mime-version:to:cc:subject:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe:content-type :content-transfer-encoding; bh=HTqH6ybP11nA42HESH8A5kpI1ZbhoC3bhKA34GUhnJI=; b=eEO9/hEwcPRJzZv2pKX7aniCD0d/ZoMvXh/mo/TPf/qZPC1fLDMHxbBADjFFNgYeXg sIo31vAuULGRa8NEH2VKSFrZ+iFRabPu9sylErJVuIp8OZPNIgL2xUluFrbM91RQFay0 4/YOqtgzk99D1uW3jYhJbZTt9ZMxSVQYqPk4XuxLN2Y2qfQOam1ncvt3Sf3SLbIk9Qg6 ZFjUjOPRxHi0OBrZwkLaX7tZpIk4fnhjMEgEBkyCrDShmTNOKdY8PLzuHFHh2tdACQ72 UEgWZ1IMgd++wWxNpvMJIO0wEgwKaRweJBUOCc1Ov3GOQrVDK+IXFxHkdjoe1D4Lv2Ys PPFg== X-Received: by 10.236.4.69 with SMTP id 45mr4303995yhi.20.1380559822037; Mon, 30 Sep 2013 09:50:22 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.35.10 with SMTP id d10ls2106304qej.19.gmail; Mon, 30 Sep 2013 09:50:21 -0700 (PDT) X-Received: by 10.220.164.202 with SMTP id f10mr2686809vcy.25.1380559821923; Mon, 30 Sep 2013 09:50:21 -0700 (PDT) Received: from mail-vb0-f43.google.com (mail-vb0-f43.google.com [209.85.212.43]) by mx.google.com with ESMTPS id ee8si261848vdc.15.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 30 Sep 2013 09:50:21 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.43 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.43; Received: by mail-vb0-f43.google.com with SMTP id h11so3907854vbh.2 for ; Mon, 30 Sep 2013 09:50:21 -0700 (PDT) X-Gm-Message-State: ALoCoQnz817A3AbWDkFGKyiTAVEo2NbPsLGZS82VIFyRLiBdiyet9tl5oB59jU62pR3c07hjTsn8 X-Received: by 10.220.43.19 with SMTP id u19mr23126218vce.3.1380559821759; Mon, 30 Sep 2013 09:50:21 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp117229vcz; Mon, 30 Sep 2013 09:50:21 -0700 (PDT) X-Received: by 10.180.39.212 with SMTP id r20mr14676699wik.13.1380559820428; Mon, 30 Sep 2013 09:50:20 -0700 (PDT) Received: from mail-wg0-f53.google.com (mail-wg0-f53.google.com [74.125.82.53]) by mx.google.com with ESMTPS id gj11si4897811wic.66.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 30 Sep 2013 09:50:20 -0700 (PDT) Received-SPF: neutral (google.com: 74.125.82.53 is neither permitted nor denied by best guess record for domain of will.newton@linaro.org) client-ip=74.125.82.53; Received: by mail-wg0-f53.google.com with SMTP id x12so5423414wgg.8 for ; Mon, 30 Sep 2013 09:50:19 -0700 (PDT) X-Received: by 10.180.20.13 with SMTP id j13mr14584339wie.6.1380559819716; Mon, 30 Sep 2013 09:50:19 -0700 (PDT) Received: from localhost.localdomain (cpc6-seac21-2-0-cust453.7-2.cable.virginmedia.com. [82.1.113.198]) by mx.google.com with ESMTPSA id b13sm27622477wic.9.1969.12.31.16.00.00 (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 30 Sep 2013 09:50:19 -0700 (PDT) Message-ID: <5249ABC9.4090903@linaro.org> Date: Mon, 30 Sep 2013 17:50:17 +0100 From: Will Newton User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130805 Thunderbird/17.0.8 MIME-Version: 1.0 To: libc-ports@sourceware.org CC: patches@linaro.org Subject: [PATCH v3] ARM: Add pointer encryption support. X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: will.newton@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.43 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Add support for pointer encryption in glibc internal structures in C and assembler code. Pointer encryption is a glibc security feature described here: https://sourceware.org/glibc/wiki/PointerEncryption The ARM implementation uses global variables instead of thread pointer relative accesses to get the value of the pointer encryption guard because accessing the thread pointer can be very expensive on older ARM cores. ports/ChangeLog.arm: 2013-09-27 Will Newton * sysdeps/arm/__longjmp.S (__longjmp): Demangle fp, sp and lr when restoring register values. * sysdeps/arm/include/bits/setjmp.h (JMP_BUF_REGLIST): Remove sp and lr from list and replace fp with a4. * sysdeps/arm/jmpbuf-unwind.h (_jmpbuf_sp): New function. (_JMPBUF_UNWINDS_ADJ): Call _jmpbuf_sp. * sysdeps/arm/setjmp.S (__sigsetjmp): Mangle fp, sp and lr before storing register values. * sysdeps/arm/sysdep.h (LDST_GLOBAL): New macro. * sysdeps/unix/sysv/linux/arm/sysdep.h (PTR_MANGLE): New macro. (PTR_DEMANGLE): Likewise. (PTR_MANGLE2): Likewise. (PTR_DEMANGLE2): Likewise. --- ports/sysdeps/arm/__longjmp.S | 14 ++++++++++ ports/sysdeps/arm/include/bits/setjmp.h | 5 ++-- ports/sysdeps/arm/jmpbuf-unwind.h | 13 +++++++++- ports/sysdeps/arm/setjmp.S | 14 ++++++++++ ports/sysdeps/arm/sysdep.h | 12 +++++++++ ports/sysdeps/unix/sysv/linux/arm/sysdep.h | 41 +++++++++++++++++++++++++++--- 6 files changed, 93 insertions(+), 6 deletions(-) Changes in v3: - Added comments - Described internals on the wiki and added a link in commit message - Improved commit message - Replaced conditional !IS_IN_nscd with !NOT_IN_libc || IS_IN_libpthread diff --git a/ports/sysdeps/arm/__longjmp.S b/ports/sysdeps/arm/__longjmp.S index a5edede..2b1f7f4 100644 --- a/ports/sysdeps/arm/__longjmp.S +++ b/ports/sysdeps/arm/__longjmp.S @@ -34,10 +34,24 @@ ENTRY (__longjmp) sfi_breg ip, \ ldr r4, [\B, #32] /* jmpbuf's sp */ cfi_undefined (r4) +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (r4, r4, a3, a4) +#endif CHECK_SP (r4) #endif sfi_sp sfi_breg ip, \ ldmia \B!, JMP_BUF_REGLIST +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (fp, a4, a3, a2) + ldr a4, [ip], #4 + PTR_DEMANGLE2 (sp, a4, a3) + ldr a4, [ip], #4 + PTR_DEMANGLE2 (lr, a4, a3) +#else + mov fp, a4 + ldr sp, [ip], #4 + ldr lr, [ip], #4 +#endif cfi_restore (v1) cfi_restore (v2) cfi_restore (v3) diff --git a/ports/sysdeps/arm/include/bits/setjmp.h b/ports/sysdeps/arm/include/bits/setjmp.h index 1559d7b..64505dc 100644 --- a/ports/sysdeps/arm/include/bits/setjmp.h +++ b/ports/sysdeps/arm/include/bits/setjmp.h @@ -26,8 +26,9 @@ #ifndef _ISOMAC /* Register list for a ldm/stm instruction to load/store - the general registers from a __jmp_buf. */ -# define JMP_BUF_REGLIST {v1-v6, sl, fp, sp, lr} + the general registers from a __jmp_buf. The a4 register + contains fp at this point. */ +# define JMP_BUF_REGLIST {a4, v1-v6, sl} /* Index of __jmp_buf where the sp register resides. */ # define __JMP_BUF_SP 8 diff --git a/ports/sysdeps/arm/jmpbuf-unwind.h b/ports/sysdeps/arm/jmpbuf-unwind.h index 0863540..1b0d020 100644 --- a/ports/sysdeps/arm/jmpbuf-unwind.h +++ b/ports/sysdeps/arm/jmpbuf-unwind.h @@ -17,6 +17,7 @@ #include #include +#include #include /* Test if longjmp to JMPBUF would unwind the frame @@ -27,8 +28,18 @@ #define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) +static inline uintptr_t __attribute__ ((unused)) +_jmpbuf_sp (__jmp_buf regs) +{ + uintptr_t sp = regs[__JMP_BUF_SP]; +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (sp); +#endif + return sp; +} + #define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ - ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[__JMP_BUF_SP] - (_adj)) + ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj)) /* We use the normal longjmp for unwinding. */ #define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/ports/sysdeps/arm/setjmp.S b/ports/sysdeps/arm/setjmp.S index a6c161d..b38b919 100644 --- a/ports/sysdeps/arm/setjmp.S +++ b/ports/sysdeps/arm/setjmp.S @@ -24,11 +24,25 @@ #include ENTRY (__sigsetjmp) +#ifdef PTR_MANGLE + PTR_MANGLE (a4, fp, a3, ip) +#else + mov a4, fp +#endif mov ip, r0 /* Save registers */ sfi_breg ip, \ stmia \B!, JMP_BUF_REGLIST +#ifdef PTR_MANGLE + PTR_MANGLE2 (a4, sp, a3) + str a4, [ip], #4 + PTR_MANGLE2 (a4, lr, a3) + str a4, [ip], #4 +#else + str sp, [ip], #4 + str lr, [ip], #4 +#endif #if !defined ARM_ASSUME_NO_IWMMXT || defined __SOFTFP__ # define NEED_HWCAP 1 diff --git a/ports/sysdeps/arm/sysdep.h b/ports/sysdeps/arm/sysdep.h index 5501597..3823617 100644 --- a/ports/sysdeps/arm/sysdep.h +++ b/ports/sysdeps/arm/sysdep.h @@ -171,6 +171,18 @@ 99: OP R, [pc, T] # endif +/* Load or store to/from a global EXPR into/from R, using T. */ +# define LDST_GLOBAL(OP, R, T, EXPR) \ + ldr T, 99f; \ + ldr R, 100f; \ +98: add T, T, pc; \ + ldr T, [T, R]; \ + .subsection 2; \ +99: .word _GLOBAL_OFFSET_TABLE_ - 98b - PC_OFS; \ +100: .word EXPR##(GOT); \ + .previous; \ + OP R, [T] + /* Cope with negative memory offsets, which thumb can't encode. Use NEGOFF_ADJ_BASE to (conditionally) alter the base register, and then NEGOFF_OFF1 to use 0 for thumb and the offset for arm, diff --git a/ports/sysdeps/unix/sysv/linux/arm/sysdep.h b/ports/sysdeps/unix/sysv/linux/arm/sysdep.h index b195d8e..2bd187e 100644 --- a/ports/sysdeps/unix/sysv/linux/arm/sysdep.h +++ b/ports/sysdeps/unix/sysv/linux/arm/sysdep.h @@ -435,8 +435,43 @@ __local_syscall_error: \ #endif /* __ASSEMBLER__ */ -/* Pointer mangling is not yet supported for ARM. */ -#define PTR_MANGLE(var) (void) (var) -#define PTR_DEMANGLE(var) (void) (var) +/* Pointer mangling support. */ +#if (defined NOT_IN_libc && defined IS_IN_rtld) || (!defined SHARED && (!defined NOT_IN_libc || defined IS_IN_libpthread)) +# ifdef __ASSEMBLER__ +# define PTR_MANGLE(dst, src, guard, tmp) \ + LDST_PCREL(ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local)); \ + PTR_MANGLE2(dst, src, guard) +/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */ +# define PTR_MANGLE2(dst, src, guard) \ + eor dst, src, guard +# define PTR_DEMANGLE(dst, src, guard, tmp) \ + PTR_MANGLE (dst, src, guard, tmp) +# define PTR_DEMANGLE2(dst, src, guard) \ + PTR_MANGLE2 (dst, src, guard) +# else +extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden; +# define PTR_MANGLE(var) \ + (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local) +# define PTR_DEMANGLE(var) PTR_MANGLE (var) +# endif +#else +# ifdef __ASSEMBLER__ +# define PTR_MANGLE(dst, src, guard, tmp) \ + LDST_GLOBAL(ldr, guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard)); \ + PTR_MANGLE2(dst, src, guard) +/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */ +# define PTR_MANGLE2(dst, src, guard) \ + eor dst, src, guard +# define PTR_DEMANGLE(dst, src, guard, tmp) \ + PTR_MANGLE (dst, src, guard, tmp) +# define PTR_DEMANGLE2(dst, src, guard) \ + PTR_MANGLE2 (dst, src, guard) +# else +extern uintptr_t __pointer_chk_guard attribute_relro; +# define PTR_MANGLE(var) \ + (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard) +# define PTR_DEMANGLE(var) PTR_MANGLE (var) +# endif +#endif #endif /* linux/arm/sysdep.h */