Re: [PATCH] x86/ibt: Implement FineIBT

From: Josh Poimboeuf
Date: Fri Oct 21 2022 - 19:09:08 EST


On Tue, Oct 18, 2022 at 03:35:50PM +0200, Peter Zijlstra wrote:
> +#ifdef CONFIG_FINEIBT
> +/*
> + * kCFI FineIBT
> + *
> + * __cfi_\func: __cfi_\func:
> + * movl $0x12345678,%eax endbr64 // 4
> + * nop subl $0x12345678,%r10d // 7
> + * nop jz 1f // 2
> + * nop ud2 // 2
> + * nop 1: nop // 1
> + * nop
> + * nop
> + * nop
> + * nop
> + * nop
> + * nop
> + * nop

All the "CFI" naming everywhere is very unfortunate. We already have
"call frame information" in both the toolchain and objtool.

The feature is called "kCFI" anyway, can Clang call the symbols
'__kcfi_*'?

> +++ b/tools/objtool/builtin-check.c
> @@ -79,6 +79,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, "generate cfi_sites"),

"annotate kernel control flow integrity (kCFI) function preambles" ?

> +++ b/tools/objtool/check.c
> @@ -861,6 +861,62 @@ static int create_ibt_endbr_seal_section
> 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 (strncmp(sym->name, "__cfi_", 6))
> + continue;

Also make sure it's STT_FUNC.

> +
> + 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 (strncmp(sym->name, "__cfi_", 6))
> + continue;

Ditto.

--
Josh