Commit 9a479f76 authored by Peter Zijlstra's avatar Peter Zijlstra
Browse files

objtool: Add --cfi to generate the .cfi_sites section



Add the location of all __cfi_##name symbols (as generated by kCFI) to
a section such that we might re-write things at kernel boot.

Notably; boot time re-hashing and FineIBT are the intended use of
this.

Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20221027092842.568039454@infradead.org
parent b341b20d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ const struct option check_options[] = {
	OPT_BOOLEAN('s', "stackval", &opts.stackval, "validate frame pointer rules"),
	OPT_BOOLEAN('t', "static-call", &opts.static_call, "annotate static calls"),
	OPT_BOOLEAN('u', "uaccess", &opts.uaccess, "validate uaccess rules for SMAP"),
	OPT_BOOLEAN(0  , "cfi", &opts.cfi, "annotate kernel control flow integrity (kCFI) function preambles"),
	OPT_CALLBACK_OPTARG(0, "dump", NULL, NULL, "orc", "dump metadata", parse_dump),

	OPT_GROUP("Options:"),
+69 −0
Original line number Diff line number Diff line
@@ -861,6 +861,68 @@ static int create_ibt_endbr_seal_sections(struct objtool_file *file)
	return 0;
}

static int create_cfi_sections(struct objtool_file *file)
{
	struct section *sec, *s;
	struct symbol *sym;
	unsigned int *loc;
	int idx;

	sec = find_section_by_name(file->elf, ".cfi_sites");
	if (sec) {
		INIT_LIST_HEAD(&file->call_list);
		WARN("file already has .cfi_sites section, skipping");
		return 0;
	}

	idx = 0;
	for_each_sec(file, s) {
		if (!s->text)
			continue;

		list_for_each_entry(sym, &s->symbol_list, list) {
			if (sym->type != STT_FUNC)
				continue;

			if (strncmp(sym->name, "__cfi_", 6))
				continue;

			idx++;
		}
	}

	sec = elf_create_section(file->elf, ".cfi_sites", 0, sizeof(unsigned int), idx);
	if (!sec)
		return -1;

	idx = 0;
	for_each_sec(file, s) {
		if (!s->text)
			continue;

		list_for_each_entry(sym, &s->symbol_list, list) {
			if (sym->type != STT_FUNC)
				continue;

			if (strncmp(sym->name, "__cfi_", 6))
				continue;

			loc = (unsigned int *)sec->data->d_buf + idx;
			memset(loc, 0, sizeof(unsigned int));

			if (elf_add_reloc_to_insn(file->elf, sec,
						  idx * sizeof(unsigned int),
						  R_X86_64_PC32,
						  s, sym->offset))
				return -1;

			idx++;
		}
	}

	return 0;
}

static int create_mcount_loc_sections(struct objtool_file *file)
{
	struct section *sec;
@@ -4430,6 +4492,13 @@ int check(struct objtool_file *file)
		warnings += ret;
	}

	if (opts.cfi) {
		ret = create_cfi_sections(file);
		if (ret < 0)
			goto out;
		warnings += ret;
	}

	if (opts.rethunk) {
		ret = create_return_sites_sections(file);
		if (ret < 0)
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ struct opts {
	bool static_call;
	bool uaccess;
	int prefix;
	bool cfi;

	/* options: */
	bool backtrace;