Skip to content

Commit 262941a

Browse files
Peter Zijlstragregkh
authored andcommitted
x86,objtool: Create .return_sites
commit d9e9d23 upstream. 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> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent e0c27dc commit 262941a

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
@@ -747,6 +747,52 @@ static int create_retpoline_sites_sections(struct objtool_file *file)
747747
return 0;
748748
}
749749

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

1130+
__weak bool arch_is_rethunk(struct symbol *sym)
1131+
{
1132+
return false;
1133+
}
1134+
10841135
#define NEGATIVE_RELOC ((void *)-1L)
10851136

10861137
static struct reloc *insn_reloc(struct objtool_file *file, struct instruction *insn)
@@ -1248,6 +1299,18 @@ static void add_retpoline_call(struct objtool_file *file, struct instruction *in
12481299
annotate_call_site(file, insn, false);
12491300
}
12501301

1302+
static void add_return_call(struct objtool_file *file, struct instruction *insn)
1303+
{
1304+
/*
1305+
* Return thunk tail calls are really just returns in disguise,
1306+
* so convert them accordingly.
1307+
*/
1308+
insn->type = INSN_RETURN;
1309+
insn->retpoline_safe = true;
1310+
1311+
list_add_tail(&insn->call_node, &file->return_thunk_list);
1312+
}
1313+
12511314
static bool same_function(struct instruction *insn1, struct instruction *insn2)
12521315
{
12531316
return insn1->func->pfunc == insn2->func->pfunc;
@@ -1300,6 +1363,9 @@ static int add_jump_destinations(struct objtool_file *file)
13001363
} else if (reloc->sym->retpoline_thunk) {
13011364
add_retpoline_call(file, insn);
13021365
continue;
1366+
} else if (reloc->sym->return_thunk) {
1367+
add_return_call(file, insn);
1368+
continue;
13031369
} else if (insn->func) {
13041370
/*
13051371
* External sibling call or internal sibling call with
@@ -2182,6 +2248,9 @@ static int classify_symbols(struct objtool_file *file)
21822248
if (arch_is_retpoline(func))
21832249
func->retpoline_thunk = true;
21842250

2251+
if (arch_is_rethunk(func))
2252+
func->return_thunk = true;
2253+
21852254
if (!strcmp(func->name, "__fentry__"))
21862255
func->fentry = true;
21872256

@@ -3935,6 +4004,11 @@ int check(struct objtool_file *file)
39354004
if (ret < 0)
39364005
goto out;
39374006
warnings += ret;
4007+
4008+
ret = create_return_sites_sections(file);
4009+
if (ret < 0)
4010+
goto out;
4011+
warnings += ret;
39384012
}
39394013

39404014
if (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
@@ -126,6 +126,7 @@ struct objtool_file *objtool_open_read(const char *_objname)
126126
INIT_LIST_HEAD(&file.insn_list);
127127
hash_init(file.insn_hash);
128128
INIT_LIST_HEAD(&file.retpoline_call_list);
129+
INIT_LIST_HEAD(&file.return_thunk_list);
129130
INIT_LIST_HEAD(&file.static_call_list);
130131
INIT_LIST_HEAD(&file.mcount_loc_list);
131132
INIT_LIST_HEAD(&file.endbr_list);

0 commit comments

Comments
 (0)