From patchwork Tue Aug 8 16:54:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 799355 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-460044-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="FCQcTdjw"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xRgVB4Wdrz9s4s for ; Wed, 9 Aug 2017 02:54:25 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=DOlFNesaS4cOgISQaG/miu594NFiB5Gq4wOVmSdHHofcEC tAb3V0Kmx5ffZiAM+Gw2l+cOBEwTYfbxieAdBOhCHgt2/cpyH/+NDKRHC88l/gKR cIvALR21JyY+Qyp82/ZlHbiFDz8WHtMihFlqcJ2wubLPCGbspoPWK0g/fXuco= 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 :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=xA3ywaokVZl/lvSD5PG7l1yU6os=; b=FCQcTdjwtbVZbiIRFY// jbGDh9i7st2vpxvwXJXduK5KCo8aBaDe0SoG67Lfu2C7ASI6v3FTkuWekn7vpJg8 sguXt2ORrl2ffH1s7BZuAizKh9atGIeMH84cf03G3fYfFwHPqi9Jgjaq/7PykBRg n4qMcUDKhDHNXY/6U4CU5FQ= Received: (qmail 105957 invoked by alias); 8 Aug 2017 16:54:12 -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 105909 invoked by uid 89); 8 Aug 2017 16:54:11 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-15.0 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=6000 X-HELO: mail-ua0-f173.google.com Received: from mail-ua0-f173.google.com (HELO mail-ua0-f173.google.com) (209.85.217.173) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 08 Aug 2017 16:54:09 +0000 Received: by mail-ua0-f173.google.com with SMTP id d29so17692011uai.2 for ; Tue, 08 Aug 2017 09:54:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=K37uuENG1yNDfIdgI1rO3R0dFl+x1+tOK7YCv83r8no=; b=ilLMxlHW8Ha/jP9b6xB+OQIJHCNzVV3qzOfE6H58+wjXI5p/xzE5aka1dhADJBASQ/ N5MZQ1zsBPjW84H4tdONqfLuvgEoF9kDt3TKYBveZGwY9EyrwNxc47PzQviqg/aOGCf+ 4JTU0v6DKYWmu5eDxmbPbziJB3XGsrV4tDoCts5DD3nOHJZ7wDrDLjkJhPJRxh0cN0TA xHdTQqdwqdOu6Vx99ML70v3bL+roW+89YRlFjspu9jslZZGningZzDvw9cigmyWCLL+p ve823Hq8RDXw1MFx/2sLy0513oMRA6mgGxEEAwFfsTsnYC5hZScvsB49Und/gwgICcs6 31Cg== X-Gm-Message-State: AHYfb5i1O/xp7k5/0T+iPp8kDidNvdvv62oNavimgPxd7zHlPPIgyG4C fLEVVUCmO+29cxp96snLCijG11I6u7d3 X-Received: by 10.176.24.97 with SMTP id j33mr3029546uag.125.1502211247433; Tue, 08 Aug 2017 09:54:07 -0700 (PDT) MIME-Version: 1.0 Received: by 10.103.68.218 with HTTP; Tue, 8 Aug 2017 09:54:06 -0700 (PDT) From: Uros Bizjak Date: Tue, 8 Aug 2017 18:54:06 +0200 Message-ID: Subject: [PATCH, i386]: Make stack canary location customizable (PR target/81708) To: "gcc-patches@gcc.gnu.org" Hello! Attached patch introduces -mstack-protector-guard-reg= and -mstack-protector-guard-offset= options to make stack canary location customizable. These are the same options powerpc has. 2017-08-08 Uros Bizjak PR target/81708 * config/i386/i386.opt (mstack-protector-guard-reg=): New option (mstack-protector-guard-offset=): Ditto. * config/i386/i386.c (ix86_option_override): Handle -mstack-protector-guard-reg= and -mstack-protector-guard-offset= options. (ix86_stack_protect_guard): Use ix86_stack_protect_guard_reg and ix86_stack_protect_guard_offset variables. (TARGET_STACK_PROTECT_GUARD): Always define. * doc/invoke.texi (x86 Options): Document -mstack-protector-guard-reg= and -mstack-protector-guard-offset= options. testsuite/ChangeLog: 2017-08-08 Uros Bizjak PR target/81708 * gcc.target/i386/stack-prot-guard.c: New test. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. I will mention new options in gcc-8 changes webpage later. Uros. Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 250960) +++ config/i386/i386.c (working copy) @@ -6662,6 +6662,69 @@ ix86_option_override_internal (bool main_args_p, opts->x_ix86_stack_protector_guard = TARGET_HAS_BIONIC ? SSP_GLOBAL : SSP_TLS; +#ifdef TARGET_THREAD_SSP_OFFSET + ix86_stack_protector_guard_offset = TARGET_THREAD_SSP_OFFSET; +#endif + + if (global_options_set.x_ix86_stack_protector_guard_offset_str) + { + char *endp; + const char *str = ix86_stack_protector_guard_offset_str; + + errno = 0; + int64_t offset; + +#if defined(INT64_T_IS_LONG) + offset = strtol (str, &endp, 0); +#else + offset = strtoll (str, &endp, 0); +#endif + + if (!*str || *endp || errno) + error ("%qs is not a valid number " + "in -mstack-protector-guard-offset=", str); + + if (!IN_RANGE (offset, HOST_WIDE_INT_C (-0x80000000), + HOST_WIDE_INT_C (0x7fffffff))) + error ("%qs is not a valid offset " + "in -mstack-protector-guard-offset=", str); + + ix86_stack_protector_guard_offset = offset; + } + + ix86_stack_protector_guard_reg = DEFAULT_TLS_SEG_REG; + + /* The kernel uses a different segment register for performance + reasons; a system call would not have to trash the userspace + segment register, which would be expensive. */ + if (ix86_cmodel == CM_KERNEL) + ix86_stack_protector_guard_reg = ADDR_SPACE_SEG_GS; + + if (global_options_set.x_ix86_stack_protector_guard_reg_str) + { + const char *str = ix86_stack_protector_guard_reg_str; + addr_space_t seg = ADDR_SPACE_GENERIC; + + /* Discard optional register prefix. */ + if (str[0] == '%') + str++; + + if (strlen (str) == 2 && str[1] == 's') + { + if (str[0] == 'f') + seg = ADDR_SPACE_SEG_FS; + else if (str[0] == 'g') + seg = ADDR_SPACE_SEG_GS; + } + + if (seg == ADDR_SPACE_GENERIC) + error ("%qs is not a valid base register " + "in -mstack-protector-guard-reg=", + ix86_stack_protector_guard_reg_str); + + ix86_stack_protector_guard_reg = seg; + } + /* Handle -mmemcpy-strategy= and -mmemset-strategy= */ if (opts->x_ix86_tune_memcpy_strategy) { @@ -45795,7 +45858,6 @@ ix86_mangle_type (const_tree type) } } -#ifdef TARGET_THREAD_SSP_OFFSET static tree ix86_stack_protect_guard (void) { @@ -45802,20 +45864,13 @@ ix86_stack_protect_guard (void) if (TARGET_SSP_TLS_GUARD) { tree type_node = lang_hooks.types.type_for_mode (ptr_mode, 1); - addr_space_t as = DEFAULT_TLS_SEG_REG; - /* The kernel uses a different segment register for performance - reasons; a system call would not have to trash the userspace - segment register, which would be expensive. */ - if (ix86_cmodel == CM_KERNEL) - as = ADDR_SPACE_SEG_GS; + int qual = ENCODE_QUAL_ADDR_SPACE (ix86_stack_protector_guard_reg); - int qual = ENCODE_QUAL_ADDR_SPACE (as); - tree type = build_qualified_type (type_node, qual); tree asptrtype = build_pointer_type (type); - tree sspoff = build_int_cst (asptrtype, TARGET_THREAD_SSP_OFFSET); - + tree sspoff = build_int_cst (asptrtype, + ix86_stack_protector_guard_offset); tree t = build2 (MEM_REF, asptrtype, sspoff, build_int_cst (asptrtype, 0)); return t; @@ -45823,7 +45878,6 @@ ix86_stack_protect_guard (void) return default_stack_protect_guard (); } -#endif /* For 32-bit code we can save PIC register setup by using __stack_chk_fail_local hidden function instead of calling @@ -52831,10 +52885,8 @@ ix86_run_selftests (void) #undef TARGET_MANGLE_TYPE #define TARGET_MANGLE_TYPE ix86_mangle_type -#ifdef TARGET_THREAD_SSP_OFFSET #undef TARGET_STACK_PROTECT_GUARD #define TARGET_STACK_PROTECT_GUARD ix86_stack_protect_guard -#endif #if !TARGET_MACHO #undef TARGET_STACK_PROTECT_FAIL Index: config/i386/i386.opt =================================================================== --- config/i386/i386.opt (revision 250960) +++ config/i386/i386.opt (working copy) @@ -924,6 +924,20 @@ Enum(stack_protector_guard) String(tls) Value(SSP_ EnumValue Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL) +mstack-protector-guard-reg= +Target RejectNegative Joined Var(ix86_stack_protector_guard_reg_str) +Use the given base register for addressing the stack-protector guard. + +TargetVariable +addr_space_t ix86_stack_protector_guard_reg = ADDR_SPACE_GENERIC + +mstack-protector-guard-offset= +Target RejectNegative Joined Integer Var(ix86_stack_protector_guard_offset_str) +Use the given offset for addressing the stack-protector guard. + +TargetVariable +HOST_WIDE_INT ix86_stack_protector_guard_offset = 0 + mmitigate-rop Target Var(flag_mitigate_rop) Init(0) Attempt to avoid generating instruction sequences containing ret bytes. Index: doc/invoke.texi =================================================================== --- doc/invoke.texi (revision 250960) +++ doc/invoke.texi (working copy) @@ -1215,7 +1215,9 @@ See RS/6000 and PowerPC Options. -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol -malign-data=@var{type} -mstack-protector-guard=@var{guard} @gol --mmitigate-rop -mgeneral-regs-only -mcall-ms2sysv-xlogues} +-mstack-protector-guard-reg=@var{reg} @gol +-mstack-protector-guard-offset=@var{offset} -mmitigate-rop @gol +-mgeneral-regs-only -mcall-ms2sysv-xlogues} @emph{x86 Windows Options} @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol @@ -26147,12 +26149,23 @@ to 255, 8-bit unsigned integer divide is used inst Split 32-byte AVX unaligned load and store. @item -mstack-protector-guard=@var{guard} -@opindex 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 global canary or @samp{tls} for per-thread canary in the TLS block (the default). This option has effect only when @option{-fstack-protector} or @option{-fstack-protector-all} is specified. +With the latter choice the options +@option{-mstack-protector-guard-reg=@var{reg}} and +@option{-mstack-protector-guard-offset=@var{offset}} furthermore specify +which segment register (@code{%fs} or @code{%gs}) to use as base register +for reading the canary, and from what offset from that base register. +The default for those is as specified in the relevant ABI. + @item -mmitigate-rop @opindex mmitigate-rop Try to avoid generating code sequences that contain unintended return Index: testsuite/gcc.target/i386/stack-prot-guard.c =================================================================== --- testsuite/gcc.target/i386/stack-prot-guard.c (nonexistent) +++ testsuite/gcc.target/i386/stack-prot-guard.c (working copy) @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=tls -mstack-protector-guard-reg=gs -mstack-protector-guard-offset=0x3038" } */ + +void f(void) { } + +/* { dg-final { scan-assembler "gs:12344" } } */