Skip to content

Commit 8ce1ac7

Browse files
chenyuan0001Kernel Patches Daemon
authored andcommitted
bpftool: Add CET-aware symbol matching for x86_64 architectures
Adjust symbol matching logic to account for Control-flow Enforcement Technology (CET) on x86_64 systems. CET prefixes functions with a 4-byte 'endbr' instruction, shifting the actual hook entry point to symbol + 4. Signed-off-by: Yuan Chen <[email protected]>
1 parent b0d72a4 commit 8ce1ac7

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

tools/bpf/bpftool/link.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,52 @@ get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
282282
return data;
283283
}
284284

285+
static bool is_x86_ibt_enabled(void)
286+
{
287+
#if defined(__x86_64__)
288+
struct kernel_config_option options[] = {
289+
{ "CONFIG_X86_KERNEL_IBT", },
290+
};
291+
char *values[ARRAY_SIZE(options)] = { };
292+
bool ret;
293+
294+
if (read_kernel_config(options, ARRAY_SIZE(options), values, NULL))
295+
return false;
296+
297+
ret = !!values[0];
298+
free(values[0]);
299+
return ret;
300+
#else
301+
return false;
302+
#endif
303+
}
304+
305+
static bool
306+
symbol_matches_target(__u64 sym_addr, __u64 target_addr, bool is_ibt_enabled)
307+
{
308+
if (sym_addr == target_addr)
309+
return true;
310+
311+
/*
312+
* On x86_64 architectures with CET (Control-flow Enforcement Technology),
313+
* function entry points have a 4-byte 'endbr' instruction prefix.
314+
* This causes kprobe hooks to target the address *after* 'endbr'
315+
* (symbol address + 4), preserving the CET instruction.
316+
* Here we check if the symbol address matches the hook target address
317+
* minus 4, indicating a CET-enabled function entry point.
318+
*/
319+
if (is_ibt_enabled && sym_addr == target_addr - 4)
320+
return true;
321+
322+
return false;
323+
}
324+
285325
static void
286326
show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
287327
{
288328
struct addr_cookie *data;
289329
__u32 i, j = 0;
330+
bool is_ibt_enabled;
290331

291332
jsonw_bool_field(json_wtr, "retprobe",
292333
info->kprobe_multi.flags & BPF_F_KPROBE_MULTI_RETURN);
@@ -306,8 +347,10 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
306347
if (!dd.sym_count)
307348
goto error;
308349

350+
is_ibt_enabled = is_x86_ibt_enabled();
309351
for (i = 0; i < dd.sym_count; i++) {
310-
if (dd.sym_mapping[i].address != data[j].addr)
352+
if (!symbol_matches_target(dd.sym_mapping[i].address,
353+
data[j].addr, is_ibt_enabled))
311354
continue;
312355
jsonw_start_object(json_wtr);
313356
jsonw_uint_field(json_wtr, "addr", dd.sym_mapping[i].address);
@@ -719,6 +762,7 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
719762
{
720763
struct addr_cookie *data;
721764
__u32 i, j = 0;
765+
bool is_ibt_enabled;
722766

723767
if (!info->kprobe_multi.count)
724768
return;
@@ -742,9 +786,11 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
742786
if (!dd.sym_count)
743787
goto error;
744788

789+
is_ibt_enabled = is_x86_ibt_enabled();
745790
printf("\n\t%-16s %-16s %s", "addr", "cookie", "func [module]");
746791
for (i = 0; i < dd.sym_count; i++) {
747-
if (dd.sym_mapping[i].address != data[j].addr)
792+
if (!symbol_matches_target(dd.sym_mapping[i].address,
793+
data[j].addr, is_ibt_enabled))
748794
continue;
749795
printf("\n\t%016lx %-16llx %s",
750796
dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name);

0 commit comments

Comments
 (0)