From patchwork Mon Dec 3 09:55:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ramana Radhakrishnan X-Patchwork-Id: 152684 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp6612813ljp; Mon, 3 Dec 2018 01:56:01 -0800 (PST) X-Google-Smtp-Source: AFSGD/XEvCdEqDHQ3UGTXGtYu9FDP8LnqUAf/cAYAhQYpAoOmzaEOc2lbCW9tkn38hg2m9u+kb6D X-Received: by 2002:a17:902:8f83:: with SMTP id z3mr14939156plo.328.1543830960947; Mon, 03 Dec 2018 01:56:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543830960; cv=none; d=google.com; s=arc-20160816; b=X/MqqwlNrD96K3oVaHFkQsaOQbpcRinMd6vKqn+Smqz2cIQHchiz7PjTIENkT44q49 vGbXjbD0u+NDez+QvdZs39R5NxoJjg/bAljBQAAbgYQJR4wwfNTDtzb+c2FwSgle6HJh pUit5HkpJnvWaUZZunxqcc8wq3CXqSEhLF0e67zYfUQwkBLSiZt8nkopfhAwVM0yu/CZ st8yOYKodk6z0CJ5QFn1as1+5P9aTzMstm3wh3vS1j2FQ4ZZ9afZELtmybbTkzaXhInv jFMVGMpcpQVbrQa9NnIzkLf0ObNtORDHe27FdpG44OhbN7cWNv6mo3i4pSB96P9Dssv2 3TsA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:user-agent:message-id:date:subject:cc:to:from :dkim-signature:delivered-to:sender:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:mailing-list:dkim-signature :domainkey-signature; bh=ZaZpWgD+vsCTo7QragMatVKEqMfur2mmfOjMGnCIZsM=; b=y5P1AirxZ4Wr/b0/pJGzvVbm0gkhA+6+M7FO3DSqPqaDGNYJdWXBkTvpPD5GthR3Kv 2O2uVMduW4tfm0IayAALrTlP/Sb4ciDeVZ4p1oEEUX68jcPCld4mtf2d2mnKLiev8ijW Y1AaUUKenKUdM/BFJYV2Vu3f1nlaFq7lC1VUWuPCm0uI+s610twc01Jc2DymTJkFE4uA MOrm+I15tJHNuy7codCYrTfzqdYWv2FYbyTVTJooRsdkgyacwNPkE+TWMNk4dJsd0HCA vv2H/xa8t9T0ZdXTn6m3VD3XDqyadRwKjEUz8JdYZvUCGmlAYZ92tuJvh2ASD5TpKuxC 1b9g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=HhBfsE5c; dkim=neutral (body hash did not verify) header.i=@armh.onmicrosoft.com header.s=selector1-arm-com header.b=KN9pbRVj; spf=pass (google.com: domain of gcc-patches-return-491488-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="gcc-patches-return-491488-patch=linaro.org@gcc.gnu.org" Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id r28si12157385pgm.317.2018.12.03.01.56.00 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 03 Dec 2018 01:56:00 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-return-491488-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=HhBfsE5c; dkim=neutral (body hash did not verify) header.i=@armh.onmicrosoft.com header.s=selector1-arm-com header.b=KN9pbRVj; spf=pass (google.com: domain of gcc-patches-return-491488-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="gcc-patches-return-491488-patch=linaro.org@gcc.gnu.org" DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:content-type:mime-version; q=dns; s=default; b=Uy/nSfhA3lM0lAX1nLia7flE+tASV+16hpmrf1GD8fd7aSsZSA 1YafRYj2b84rhUmedMgT7Dvd4JzDjcE0DACxIOQ1Q1JPnCg/HmvW3zWGf4xRXUJb 5b1yl9M0Q/6SL2PorNacv0sWrhSdOQTjWCvvCaIsJIpcBCKqmq/pWcDWk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:content-type:mime-version; s= default; bh=ygmxFiqMIUMhSBd5AWNiNwfkgRc=; b=HhBfsE5c86eyoNSm12/O YrRGaHhIi5sIJWyNAApJF0b4qrKMq9PtA+maxjIAPdCF/YIfuNNMNaJVQSbSuVmt u+bdpvpaA3IwAjV/sr064PbaPmlbe8rLP+w9UfqOTJv698+xNyuep3LbbPJEY5SR m5M+KEUD7XDTBkkDBoT3OZo= Received: (qmail 10802 invoked by alias); 3 Dec 2018 09:55:49 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 10789 invoked by uid 89); 3 Dec 2018 09:55:47 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=intend, storage, sk:x_flag_, Options X-HELO: EUR03-AM5-obe.outbound.protection.outlook.com Received: from mail-eopbgr30089.outbound.protection.outlook.com (HELO EUR03-AM5-obe.outbound.protection.outlook.com) (40.107.3.89) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 03 Dec 2018 09:55:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector1-arm-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=IVo8ABGm4uRcMGozVo/PUfCluhUF78y6MRuiVNXmAbA=; b=KN9pbRVjjnKxu07lnlfgAerBiktuODXFBYvSka4aZ3Bw4AWi9yU+LMetayh85OqaRLakgwFpf21+NyjePtAePkMaj4bbwXFFEbj0LmNQvJtXmRwJ+Y9e4ZZ2xFihJu5Jb+KL/YLEJs1bpsQh//d1wQcnhjC7KZHYQsVCFs4C7IY= Received: from AM4PR08MB2788.eurprd08.prod.outlook.com (10.171.191.18) by AM4PR08MB0756.eurprd08.prod.outlook.com (10.164.82.146) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1382.22; Mon, 3 Dec 2018 09:55:36 +0000 Received: from AM4PR08MB2788.eurprd08.prod.outlook.com ([fe80::8584:2893:f8fe:d054]) by AM4PR08MB2788.eurprd08.prod.outlook.com ([fe80::8584:2893:f8fe:d054%2]) with mapi id 15.20.1382.020; Mon, 3 Dec 2018 09:55:36 +0000 From: Ramana Radhakrishnan To: James Greenhalgh , Richard Earnshaw CC: Marcus Shawcroft , "gcc-patches@gcc.gnu.org" , Ard Biesheuvel , Will Deacon , Mark Rutland , nd Subject: [RFC][AArch64] Add support for system register based stack protector canary access Date: Mon, 3 Dec 2018 09:55:36 +0000 Message-ID: <7a5a57fa-629d-d2ff-6292-e0893647ec8a@arm.com> user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0 authentication-results: spf=none (sender IP is ) smtp.mailfrom=Ramana.Radhakrishnan@arm.com; received-spf: None (protection.outlook.com: arm.com does not designate permitted sender hosts) MIME-Version: 1.0 For quite sometime the kernel guys, (more specifically Ard) have been talking about using a system register (sp_el0) and an offset from that for a canary based access. This patchset adds support for a new set of command line options similar to how powerpc has done this. I don't intend to change the defaults in userland, we've discussed this for user-land in the past and as far as glibc and userland is concerned we stick to the options as currently existing. The system register option is really for the kernel to use along with an offset as they control their ABI and this is a decision for them to make. I did consider sticking this all under a mcmodel=kernel-small option but thought that would be a bit too aggressive. There is very little error checking I can do in terms of the system register being used and really the assembler would barf quite quickly in case things go wrong. I've managed to rebuild Ard's kernel tree with an additional patch that I will send to him. I haven't managed to boot this kernel. There was an additional question asked about the performance characteristics of this but it's a security feature and the kernel doesn't have the luxury of a hidden symbol. Further since the kernel uses sp_el0 for access everywhere and if they choose to use the same register I don't think the performance characteristics would be too bad, but that's a decision for the kernel folks to make when taking in the feature into the kernel. I still need to add some tests and documentation in invoke.texi but this is at the stage where it would be nice for some other folks to look at this. The difference in code generated is as below. extern void bar (char *); int foo (void) { char a[100]; bar (&a); } $GCC -O2 -fstack-protector-strong vs -mstack-protector-guard-reg=sp_el0 -mstack-protector-guard=sysreg -mstack-protector-guard-offset=1024 -fstack-protector-strong I will be afk tomorrow and day after but this is to elicit some comments and for Ard to try this out with his kernel patches. Thoughts ? regards Ramana gcc/ChangeLog: 2018-11-23 Ramana Radhakrishnan * config/aarch64/aarch64-opts.h (enum stack_protector_guard): New * config/aarch64/aarch64.c (aarch64_override_options_internal): Handle and put in error checks for stack protector guard options. (aarch64_stack_protect_guard): New. (TARGET_STACK_PROTECT_GUARD): Define. * config/aarch64/aarch64.md (UNSPEC_SSP_SYSREG): New. (reg_stack_protect_address): New. (stack_protect_set): Adjust for SSP_GLOBAL. (stack_protect_test): Likewise. * config/aarch64/aarch64.opt (-mstack-protector-guard-reg): New. (-mstack-protector-guard): Likewise. (-mstack-protector-guard-offset): Likewise. * doc/invoke.texi: Document new AArch64 options. commit 9febaa23c114e598ddc9a2406ad96d8fa3ebe0c6 Author: Ramana Radhakrishnan Date: Mon Nov 19 10:12:12 2018 +0000 diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h index 7a5c6d7664f..2f06f3e0e5a 100644 --- a/gcc/config/aarch64/aarch64-opts.h +++ b/gcc/config/aarch64/aarch64-opts.h @@ -91,4 +91,10 @@ enum aarch64_sve_vector_bits_enum { SVE_2048 = 2048 }; +/* Where to get the canary for the stack protector. */ +enum stack_protector_guard { + SSP_SYSREG, /* per-thread canary in special system register */ + SSP_GLOBAL /* global canary */ +}; + #endif diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 0d89ba27e4a..a56b2166542 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -10955,6 +10955,41 @@ aarch64_override_options_internal (struct gcc_options *opts) if (opts->x_flag_strict_volatile_bitfields < 0 && abi_version_at_least (2)) opts->x_flag_strict_volatile_bitfields = 1; + if (aarch64_stack_protector_guard == SSP_GLOBAL + && opts->x_aarch64_stack_protector_guard_offset_str) + { + error ("Incompatible options -mstack-protector-guard=global and" + "-mstack-protector-guard-offset=%qs", + aarch64_stack_protector_guard_offset_str); + } + + if (aarch64_stack_protector_guard == SSP_SYSREG + && !(opts->x_aarch64_stack_protector_guard_offset_str + && opts->x_aarch64_stack_protector_guard_reg_str)) + { + error ("Both -mstack-protector-guard-offset and " + "-mstack-protector-guard-reg must be used " + "with -mstack-protector-guard=sysreg"); + } + + if (opts->x_aarch64_stack_protector_guard_reg_str) + { + if (strlen (opts->x_aarch64_stack_protector_guard_reg_str) > 100) + error ("Specify a system register with a small string length."); + } + + if (opts->x_aarch64_stack_protector_guard_offset_str) + { + char *end; + const char *str = aarch64_stack_protector_guard_offset_str; + errno = 0; + long offs = strtol (aarch64_stack_protector_guard_offset_str, &end, 0); + if (!*str || *end || errno) + error ("%qs is not a valid offset in %qs", str, + "-mstack-protector-guard-offset="); + aarch64_stack_protector_guard_offset = offs; + } + initialize_aarch64_code_model (opts); initialize_aarch64_tls_size (opts); @@ -17872,8 +17907,24 @@ aarch64_run_selftests (void) } // namespace selftest +/* Implement TARGET_STACK_PROTECT_GUARD. In case of a + global variable based guard use the default else + return a null tree. */ +static tree +aarch64_stack_protect_guard (void) +{ + if (aarch64_stack_protector_guard == SSP_GLOBAL) + return default_stack_protect_guard (); + + return NULL_TREE; +} + + #endif /* #if CHECKING_P */ +#undef TARGET_STACK_PROTECT_GUARD +#define TARGET_STACK_PROTECT_GUARD aarch64_stack_protect_guard + #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST aarch64_address_cost diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 82af4d47f78..8b0eb9e4382 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -194,6 +194,7 @@ UNSPEC_UCVTF UNSPEC_USHL_2S UNSPEC_VSTRUCTDUMMY + UNSPEC_SSP_SYSREG UNSPEC_SP_SET UNSPEC_SP_TEST UNSPEC_RSQRT @@ -6561,13 +6562,46 @@ "" { machine_mode mode = GET_MODE (operands[0]); + if (aarch64_stack_protector_guard != SSP_GLOBAL) + { + /* Generate access through the system register. */ + rtx tmp_reg = gen_reg_rtx (mode); + if (mode == DImode) + { + emit_insn (gen_reg_stack_protect_address_di (tmp_reg)); + emit_insn (gen_adddi3 (tmp_reg, tmp_reg, + GEN_INT (aarch64_stack_protector_guard_offset))); + } + else + { + emit_insn (gen_reg_stack_protect_address_si (tmp_reg)); + emit_insn (gen_addsi3 (tmp_reg, tmp_reg, + GEN_INT (aarch64_stack_protector_guard_offset))); + } + operands[1] = gen_rtx_MEM (mode, tmp_reg); + } + emit_insn ((mode == DImode ? gen_stack_protect_set_di : gen_stack_protect_set_si) (operands[0], operands[1])); DONE; }) +(define_insn "reg_stack_protect_address_" + [(set (match_operand:PTR 0 "register_operand" "=r") + (unspec:PTR [(const_int 0)] + UNSPEC_SSP_SYSREG))] + "aarch64_stack_protector_guard != SSP_GLOBAL" + { + char buf[150]; + snprintf (buf, 150, "mrs\\t%%0, %s", + aarch64_stack_protector_guard_reg_str); + output_asm_insn (buf, operands); + return ""; + } + [(set_attr "type" "mrs")]) + (define_insn "stack_protect_set_" [(set (match_operand:PTR 0 "memory_operand" "=m") (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")] @@ -6588,12 +6622,34 @@ machine_mode mode = GET_MODE (operands[0]); result = gen_reg_rtx(mode); + if (aarch64_stack_protector_guard != SSP_GLOBAL) + { + /* Generate access through the system register. The + sequence we want here is the access + of the stack offset to come with + mrs scratch_reg, + add scratch_reg, scratch_reg, :lo12:offset. */ + rtx tmp_reg = gen_reg_rtx (mode); + if (mode == DImode) + { + emit_insn (gen_reg_stack_protect_address_di (tmp_reg)); + emit_insn (gen_adddi3 (tmp_reg, tmp_reg, + GEN_INT (aarch64_stack_protector_guard_offset))); + } + else + { + emit_insn (gen_reg_stack_protect_address_si (tmp_reg)); + emit_insn (gen_addsi3 (tmp_reg, tmp_reg, + GEN_INT (aarch64_stack_protector_guard_offset))); + } + operands[1] = gen_rtx_MEM (mode, tmp_reg); + } emit_insn ((mode == DImode - ? gen_stack_protect_test_di - : gen_stack_protect_test_si) (result, - operands[0], - operands[1])); + ? gen_stack_protect_test_di + : gen_stack_protect_test_si) (result, + operands[0], + operands[1])); if (mode == DImode) emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx), diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index b2e80cbf6f1..1aaf4beb329 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -218,3 +218,33 @@ Enables verbose cost model dumping in the debug dump files. mtrack-speculation Target Var(aarch64_track_speculation) Generate code to track when the CPU might be speculating incorrectly. + +mstack-protector-guard= +Target RejectNegative Joined Enum(stack_protector_guard) Var(aarch64_stack_protector_guard) Init(SSP_GLOBAL) +Use given stack-protector guard. + +Enum +Name(stack_protector_guard) Type(enum stack_protector_guard) +Valid arguments to -mstack-protector-guard=: + +EnumValue +Enum(stack_protector_guard) String(sysreg) Value(SSP_SYSREG) + +EnumValue +Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL) + +mstack-protector-guard-reg= +Target Joined RejectNegative String Var(aarch64_stack_protector_guard_reg_str) +Use the system register specified on the command line as the stack protector +guard register. This option is for use with fstack-protector-strong and +not for use in user-land code. + +mstack-protector-guard-offset= +Target Joined RejectNegative String Var(aarch64_stack_protector_guard_offset_str) +Use an immediate to offset from the stack protector guard register, sp_el0. +This option is for use with fstack-protector-strong and not for use in +user-land code. + +TargetVariable +long aarch64_stack_protector_guard_offset = 0 + diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index d46ebd02c4e..dbe1ca42be4 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -629,7 +629,9 @@ Objective-C and Objective-C++ Dialects}. -mpc-relative-literal-loads @gol -msign-return-address=@var{scope} @gol -march=@var{name} -mcpu=@var{name} -mtune=@var{name} @gol --moverride=@var{string} -mverbose-cost-dump -mtrack-speculation} +-moverride=@var{string} -mverbose-cost-dump @gol +-mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{sysreg} @gol +-mstack-protector-guard-offset=@var{offset} -mtrack-speculation } @emph{Adapteva Epiphany Options} @gccoptlist{-mhalf-reg-file -mprefer-short-insn-regs @gol @@ -15450,6 +15452,24 @@ object boundary as described in the architecture specification. Omit or keep the frame pointer in leaf functions. The former behavior is the default. +@item -mstack-protector-guard=@var{guard} +@itemx -mstack-protector-guard-reg=@var{reg} +@itemx -mstack-protector-guard-offset=@var{offset} +@opindex mstack-protector-guard +@opindex mstack-protector-guard-reg +@opindex mstack-protector-guard-offset +Generate stack protection code using canary at @var{guard}. Supported +locations are @samp{global} for a global canary or @samp{sysreg} for a +canary in an appropriate system register. + +With the latter choice the options +@option{-mstack-protector-guard-reg=@var{reg}} and +@option{-mstack-protector-guard-offset=@var{offset}} furthermore specify +which system register to use as base register for reading the canary, +and from what offset from that base register. There is no default +register or offset as this is entirely for use within the Linux +kernel. + @item -mtls-dialect=desc @opindex mtls-dialect=desc Use TLS descriptors as the thread-local storage mechanism for dynamic accesses --- tst.s 2018-12-03 09:46:21.174167443 +0000 +++ tst.s.1 2018-12-03 09:46:03.546257203 +0000 @@ -15,15 +15,14 @@ mov x29, sp str x19, [sp, 16] .cfi_offset 19, -128 - adrp x19, __stack_chk_guard - add x19, x19, :lo12:__stack_chk_guard - ldr x0, [x19] - str x0, [sp, 136] - mov x0,0 + mrs x19, sp_el0 add x0, sp, 32 + ldr x1, [x19, 1024] + str x1, [sp, 136] + mov x1,0 bl bar ldr x0, [sp, 136] - ldr x1, [x19] + ldr x1, [x19, 1024] eor x1, x0, x1 cbnz x1, .L5