cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

arm_ssp_per_task_plugin.c (2506B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3#include "gcc-common.h"
      4
      5__visible int plugin_is_GPL_compatible;
      6
      7static unsigned int canary_offset;
      8
      9static unsigned int arm_pertask_ssp_rtl_execute(void)
     10{
     11	rtx_insn *insn;
     12
     13	for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) {
     14		const char *sym;
     15		rtx body;
     16		rtx current;
     17
     18		/*
     19		 * Find a SET insn involving a SYMBOL_REF to __stack_chk_guard
     20		 */
     21		if (!INSN_P(insn))
     22			continue;
     23		body = PATTERN(insn);
     24		if (GET_CODE(body) != SET ||
     25		    GET_CODE(SET_SRC(body)) != SYMBOL_REF)
     26			continue;
     27		sym = XSTR(SET_SRC(body), 0);
     28		if (strcmp(sym, "__stack_chk_guard"))
     29			continue;
     30
     31		/*
     32		 * Replace the source of the SET insn with an expression that
     33		 * produces the address of the current task's stack canary value
     34		 */
     35		current = gen_reg_rtx(Pmode);
     36
     37		emit_insn_before(gen_load_tp_hard(current), insn);
     38
     39		SET_SRC(body) = gen_rtx_PLUS(Pmode, current,
     40					     GEN_INT(canary_offset));
     41	}
     42	return 0;
     43}
     44
     45#define PASS_NAME arm_pertask_ssp_rtl
     46
     47#define NO_GATE
     48#include "gcc-generate-rtl-pass.h"
     49
     50#if BUILDING_GCC_VERSION >= 9000
     51static bool no(void)
     52{
     53	return false;
     54}
     55
     56static void arm_pertask_ssp_start_unit(void *gcc_data, void *user_data)
     57{
     58	targetm.have_stack_protect_combined_set = no;
     59	targetm.have_stack_protect_combined_test = no;
     60}
     61#endif
     62
     63__visible int plugin_init(struct plugin_name_args *plugin_info,
     64			  struct plugin_gcc_version *version)
     65{
     66	const char * const plugin_name = plugin_info->base_name;
     67	const int argc = plugin_info->argc;
     68	const struct plugin_argument *argv = plugin_info->argv;
     69	int i;
     70
     71	if (!plugin_default_version_check(version, &gcc_version)) {
     72		error(G_("incompatible gcc/plugin versions"));
     73		return 1;
     74	}
     75
     76	for (i = 0; i < argc; ++i) {
     77		if (!strcmp(argv[i].key, "disable"))
     78			return 0;
     79
     80		/* all remaining options require a value */
     81		if (!argv[i].value) {
     82			error(G_("no value supplied for option '-fplugin-arg-%s-%s'"),
     83			      plugin_name, argv[i].key);
     84			return 1;
     85		}
     86
     87		if (!strcmp(argv[i].key, "offset")) {
     88			canary_offset = atoi(argv[i].value);
     89			continue;
     90		}
     91		error(G_("unknown option '-fplugin-arg-%s-%s'"),
     92		      plugin_name, argv[i].key);
     93		return 1;
     94	}
     95
     96	PASS_INFO(arm_pertask_ssp_rtl, "expand", 1, PASS_POS_INSERT_AFTER);
     97
     98	register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
     99			  NULL, &arm_pertask_ssp_rtl_pass_info);
    100
    101#if BUILDING_GCC_VERSION >= 9000
    102	register_callback(plugin_info->base_name, PLUGIN_START_UNIT,
    103			  arm_pertask_ssp_start_unit, NULL);
    104#endif
    105
    106	return 0;
    107}