Skip to content

Commit d9e9d23

Browse files
Peter Zijlstrasuryasaimadhu
authored andcommitted
x86,objtool: Create .return_sites
Find all the return-thunk sites and record them in a .return_sites section such that the kernel can undo this. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org> Signed-off-by: Borislav Petkov <bp@suse.de>
1 parent 15e6722 commit d9e9d23

File tree

6 files changed

+83
-0
lines changed

6 files changed

+83
-0
lines changed

tools/objtool/arch/x86/decode.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,3 +787,8 @@ bool arch_is_retpoline(struct symbol *sym)
787787
{
788788
return !strncmp(sym->name, "__x86_indirect_", 15);
789789
}
790+
791+
bool arch_is_rethunk(struct symbol *sym)
792+
{
793+
return !strcmp(sym->name, "__x86_return_thunk");
794+
}

tools/objtool/check.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,52 @@ static int create_retpoline_sites_sections(struct objtool_file *file)
749749
return 0;
750750
}
751751

752+
static int create_return_sites_sections(struct objtool_file *file)
753+
{
754+
struct instruction *insn;
755+
struct section *sec;
756+
int idx;
757+
758+
sec = find_section_by_name(file->elf, ".return_sites");
759+
if (sec) {
760+
WARN("file already has .return_sites, skipping");
761+
return 0;
762+
}
763+
764+
idx = 0;
765+
list_for_each_entry(insn, &file->return_thunk_list, call_node)
766+
idx++;
767+
768+
if (!idx)
769+
return 0;
770+
771+
sec = elf_create_section(file->elf, ".return_sites", 0,
772+
sizeof(int), idx);
773+
if (!sec) {
774+
WARN("elf_create_section: .return_sites");
775+
return -1;
776+
}
777+
778+
idx = 0;
779+
list_for_each_entry(insn, &file->return_thunk_list, call_node) {
780+
781+
int *site = (int *)sec->data->d_buf + idx;
782+
*site = 0;
783+
784+
if (elf_add_reloc_to_insn(file->elf, sec,
785+
idx * sizeof(int),
786+
R_X86_64_PC32,
787+
insn->sec, insn->offset)) {
788+
WARN("elf_add_reloc_to_insn: .return_sites");
789+
return -1;
790+
}
791+
792+
idx++;
793+
}
794+
795+
return 0;
796+
}
797+
752798
static int create_ibt_endbr_seal_sections(struct objtool_file *file)
753799
{
754800
struct instruction *insn;
@@ -1083,6 +1129,11 @@ __weak bool arch_is_retpoline(struct symbol *sym)
10831129
return false;
10841130
}
10851131

1132+
__weak bool arch_is_rethunk(struct symbol *sym)
1133+
{
1134+
return false;
1135+
}
1136+
10861137
#define NEGATIVE_RELOC ((void *)-1L)
10871138

10881139
static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn)
@@ -1250,6 +1301,18 @@ static void add_retpoline_call(struct objtool_file *file, struct instruction *in
12501301
annotate_call_site(file, insn, false);
12511302
}
12521303

1304+
static void add_return_call(struct objtool_file *file, struct instruction *insn)
1305+
{
1306+
/*
1307+
* Return thunk tail calls are really just returns in disguise,
1308+
* so convert them accordingly.
1309+
*/
1310+
insn->type = INSN_RETURN;
1311+
insn->retpoline_safe = true;
1312+
1313+
list_add_tail(&insn->call_node, &file->return_thunk_list);
1314+
}
1315+
12531316
static bool same_function(struct instruction *insn1, struct instruction *insn2)
12541317
{
12551318
return insn1->func->pfunc == insn2->func->pfunc;
@@ -1302,6 +1365,9 @@ static int add_jump_destinations(struct objtool_file *file)
13021365
} else if (reloc->sym->retpoline_thunk) {
13031366
add_retpoline_call(file, insn);
13041367
continue;
1368+
} else if (reloc->sym->return_thunk) {
1369+
add_return_call(file, insn);
1370+
continue;
13051371
} else if (insn->func) {
13061372
/*
13071373
* External sibling call or internal sibling call with
@@ -2184,6 +2250,9 @@ static int classify_symbols(struct objtool_file *file)
21842250
if (arch_is_retpoline(func))
21852251
func->retpoline_thunk = true;
21862252

2253+
if (arch_is_rethunk(func))
2254+
func->return_thunk = true;
2255+
21872256
if (!strcmp(func->name, "__fentry__"))
21882257
func->fentry = true;
21892258

@@ -3972,6 +4041,11 @@ int check(struct objtool_file *file)
39724041
if (ret < 0)
39734042
goto out;
39744043
warnings += ret;
4044+
4045+
ret = create_return_sites_sections(file);
4046+
if (ret < 0)
4047+
goto out;
4048+
warnings += ret;
39754049
}
39764050

39774051
if (opts.mcount) {

tools/objtool/include/objtool/arch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ const char *arch_ret_insn(int len);
8989
int arch_decode_hint_reg(u8 sp_reg, int *base);
9090

9191
bool arch_is_retpoline(struct symbol *sym);
92+
bool arch_is_rethunk(struct symbol *sym);
9293

9394
int arch_rewrite_retpolines(struct objtool_file *file);
9495

tools/objtool/include/objtool/elf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct symbol {
5757
u8 uaccess_safe : 1;
5858
u8 static_call_tramp : 1;
5959
u8 retpoline_thunk : 1;
60+
u8 return_thunk : 1;
6061
u8 fentry : 1;
6162
u8 profiling_func : 1;
6263
struct list_head pv_target;

tools/objtool/include/objtool/objtool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct objtool_file {
2424
struct list_head insn_list;
2525
DECLARE_HASHTABLE(insn_hash, 20);
2626
struct list_head retpoline_call_list;
27+
struct list_head return_thunk_list;
2728
struct list_head static_call_list;
2829
struct list_head mcount_loc_list;
2930
struct list_head endbr_list;

tools/objtool/objtool.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ struct objtool_file *objtool_open_read(const char *_objname)
102102
INIT_LIST_HEAD(&file.insn_list);
103103
hash_init(file.insn_hash);
104104
INIT_LIST_HEAD(&file.retpoline_call_list);
105+
INIT_LIST_HEAD(&file.return_thunk_list);
105106
INIT_LIST_HEAD(&file.static_call_list);
106107
INIT_LIST_HEAD(&file.mcount_loc_list);
107108
INIT_LIST_HEAD(&file.endbr_list);

0 commit comments

Comments
 (0)