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: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20221027092842.568039454@infradead.org
This commit is contained in:
Peter Zijlstra 2022-10-27 11:28:13 +02:00
parent b341b20d64
commit 9a479f766b
3 changed files with 71 additions and 0 deletions

View File

@ -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:"),

View File

@ -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)

View File

@ -27,6 +27,7 @@ struct opts {
bool static_call;
bool uaccess;
int prefix;
bool cfi;
/* options: */
bool backtrace;