From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7810) id 3C48E3858C50; Tue, 1 Nov 2022 11:01:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3C48E3858C50 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1667300503; bh=tMhfl7tPRuVZ8czOwxOmVuJndix+6J9+Pn2RyoWJX3A=; h=From:To:Subject:Date:From; b=CmHNkSOFBMF/rkBh4CyQYwRa8CH0XkV6UtXmuzhoN4TBuzNIV6Gv4wNm005SUPb76 56cnn5GeF38Y9NUF5g5OFtQHWuyM1OsNAmlRPWh/5vRR8bXmCW3NyS725zaGCDzKfW VaMPckvX01+iUmckUy0oY9ee01Wzgbp3ezTws9YA= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Alex Coplan To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/vendors/ARM/heads/morello)] morello: Narrowing of outgoing varargs X-Act-Checkin: gcc X-Git-Author: Alex Coplan X-Git-Refname: refs/vendors/ARM/heads/morello X-Git-Oldrev: 70cb98d7a702272cae4174f21046ab785226d74c X-Git-Newrev: 683594a08c44941233b474c991cf5dec17788a66 Message-Id: <20221101110143.3C48E3858C50@sourceware.org> Date: Tue, 1 Nov 2022 11:01:35 +0000 (GMT) List-Id: https://gcc.gnu.org/g:683594a08c44941233b474c991cf5dec17788a66 commit 683594a08c44941233b474c991cf5dec17788a66 Author: Alex Coplan Date: Fri Oct 21 11:39:06 2022 +0100 morello: Narrowing of outgoing varargs This patch adds bounds narrowing and permission clearing on the outgoing varargs pointer (c9) for pure-capability Morello. The bounds narrowing is needed for conformance with AAPCS64-cap (and is of course desirable from a security perspective). The permission clearing follows what is done in Morello LLVM. Note we don't handle padding and alignment to ensure tight bounds in the case of > 4096 varargs, but this is not required for ABI conformance. It could be added in the future as an additional enhancement, if desired. To assist in implementing the permission clearing, we refactor the code that defines the __{ARM,CHERI}_CAP_PERMISSION_* macros. Even the CHERI permission macros should be defined by the backend, since the values are target specific (they differ between CHERI architectures). Defining them in the backend also allows us to use a shared enum across the backend which can then be used for codegen. We make use of that in this patch in order to clear the write and execute permissions on c9 for outgoing varargs. While refactoring the CHERI permsision macros, we stop defining __CHERI_CAP_PERMISSION_PERMIT_CCALL__, which the ACLE explicitly says should not be defined on Morello. Diff: --- gcc/c-family/c-cppbuiltin.c | 14 -------------- gcc/config/aarch64/aarch64-c.c | 35 +++++++++++++++++++++++++++++++---- gcc/config/aarch64/aarch64.c | 23 ++++++++++++++++++----- gcc/config/aarch64/aarch64.h | 18 ++++++++++++++++++ 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index a6c912dc352..5a0bb473b43 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -1460,21 +1460,7 @@ c_cpp_builtins (cpp_reader *pfile) if (targetm.capability_mode ().exists () && targetm.capabilities_in_hardware ()) { - /* N.b. I've not found these values defined in a document anywhere. - The values were found by looking at the assembly after using them in - the CUCL CHERI compiler explorer. */ cpp_define (pfile, "__CHERI__"); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_GLOBAL__", 1); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_PERMIT_CCALL__", 256); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_ACCESS_SYSTEM_REGISTERS__", 512); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_PERMIT_UNSEAL__", 1024); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_PERMIT_SEAL__", 2048); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_PERMIT_STORE_LOCAL__", 4096); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_PERMIT_STORE_CAPABILITY__", 8192); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_PERMIT_LOAD_CAPABILITY__", 16384); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_PERMIT_EXECUTE__", 32768); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_PERMIT_STORE__", 65536); - builtin_define_with_int_value ("__CHERI_CAP_PERMISSION_PERMIT_LOAD__", 131072); if (targetm.capability_mode ().require () == Pmode) cpp_define (pfile, "__CHERI_PURE_CAPABILITY__"); diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c index 4798d80407e..eb07ec78c84 100644 --- a/gcc/config/aarch64/aarch64-c.c +++ b/gcc/config/aarch64/aarch64-c.c @@ -144,11 +144,38 @@ aarch64_update_cpp_builtins (cpp_reader *pfile) if (TARGET_MORELLO) { +#define CAP_PERM(prefix, acle_name, arch_name)\ + builtin_define_with_int_value ("__" prefix "_CAP_PERMISSION_" \ + acle_name "__", \ + AARCH64_CAP_PERM_##arch_name) + /* These defines are Morello-specific, as per the Morello ACLE. */ - builtin_define_with_int_value ("__ARM_CAP_PERMISSION_EXECUTIVE__", 2); - builtin_define_with_int_value ("__ARM_CAP_PERMISSION_MUTABLE_LOAD__", 64); - builtin_define_with_int_value ("__ARM_CAP_PERMISSION_COMPARTMENT_ID__", 128); - builtin_define_with_int_value ("__ARM_CAP_PERMISSION_BRANCH_SEALED_PAIR__", 256); +#define ARM_PERM(x) CAP_PERM ("ARM", #x, x) + ARM_PERM (EXECUTIVE); + ARM_PERM (MUTABLE_LOAD); + ARM_PERM (COMPARTMENT_ID); + ARM_PERM (BRANCH_SEALED_PAIR); +#undef ARM_PERM + + /* These defines are common to all CHERI architectures, but have + Morello-specific values, hence defining them in the backend. */ +#define CHERI_PERM(acle, arch) CAP_PERM ("CHERI", acle, arch) +#define CHERI_PERMIT_1(acle, arch) CHERI_PERM ("PERMIT_" acle, arch) +#define CHERI_PERMIT(x) CHERI_PERMIT_1 (#x, x) + CHERI_PERM ("GLOBAL", GLOBAL); + CHERI_PERM ("ACCESS_SYSTEM_REGISTERS", SYSTEM); + CHERI_PERMIT (UNSEAL); + CHERI_PERMIT (SEAL); + CHERI_PERMIT (STORE_LOCAL); + CHERI_PERMIT_1 ("STORE_CAPABILITY", STORE_CAP); + CHERI_PERMIT_1 ("LOAD_CAPABILITY", LOAD_CAP); + CHERI_PERMIT (EXECUTE); + CHERI_PERMIT (STORE); + CHERI_PERMIT (LOAD); +#undef CHERI_PERMIT +#undef CHERI_PERMIT_1 +#undef CHERI_PERM +#undef CAP_PERM } aarch64_def_or_undef (TARGET_CRYPTO, "__ARM_FEATURE_CRYPTO", pfile); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 5179f310552..d4be34d1d35 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -17962,16 +17962,29 @@ aarch64_setup_incoming_varargs (cumulative_args_t cum_v, } static void -aarch64_handle_outgoing_varargs (rtx aama_addr, - int n_anon_args ATTRIBUTE_UNUSED, - rtx *fusage) +aarch64_handle_outgoing_varargs (rtx aama_addr, int n_anon_args, rtx *fusage) { if (!TARGET_CAPABILITY_PURE) return; - /* Morello TODO: emit scbnds with size of (n_anon_args * 16). */ rtx c9 = gen_rtx_REG (CADImode, R9_REGNUM); - emit_move_insn (c9, aama_addr); + + if (CONST_NULL_P (aama_addr)) + emit_move_insn (c9, aama_addr); + else + { + const auto aama_size = (unsigned HOST_WIDE_INT)n_anon_args * 16; + + rtx bounded = expand_binop (CADImode, cap_bounds_set_optab, + aama_addr, gen_int_mode (aama_size, DImode), + NULL_RTX, 1, OPTAB_DIRECT); + + rtx perms_to_clear + = gen_int_mode (AARCH64_CAP_PERM_EXECUTE | AARCH64_CAP_PERM_STORE, + DImode); + emit_insn (gen_aarch64_cap_clear_perm (c9, bounded, perms_to_clear)); + } + use_reg (fusage, c9); } diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index f9fcb173f60..76a4de5aadf 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -986,6 +986,24 @@ enum aarch64_abi_type #define TARGET_ILP32 (aarch64_abi == AARCH64_ABI_ILP32) +enum aarch64_cap_permissions { + AARCH64_CAP_PERM_GLOBAL = (1LU << 0), + AARCH64_CAP_PERM_EXECUTIVE = (1LU << 1), + /* 4 bits of User permissions. */ + AARCH64_CAP_PERM_MUTABLE_LOAD = (1LU << 6), + AARCH64_CAP_PERM_COMPARTMENT_ID = (1LU << 7), + AARCH64_CAP_PERM_BRANCH_SEALED_PAIR = (1LU << 8), + AARCH64_CAP_PERM_SYSTEM = (1LU << 9), + AARCH64_CAP_PERM_UNSEAL = (1LU << 10), + AARCH64_CAP_PERM_SEAL = (1LU << 11), + AARCH64_CAP_PERM_STORE_LOCAL = (1LU << 12), + AARCH64_CAP_PERM_STORE_CAP = (1LU << 13), + AARCH64_CAP_PERM_LOAD_CAP = (1LU << 14), + AARCH64_CAP_PERM_EXECUTE = (1LU << 15), + AARCH64_CAP_PERM_STORE = (1LU << 16), + AARCH64_CAP_PERM_LOAD = (1LU << 17), +}; + enum aarch64_capability { AARCH64_CAPABILITY_NONE, AARCH64_CAPABILITY_FAKE,