@@ -282,11 +282,52 @@ get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
282
282
return data ;
283
283
}
284
284
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
+
285
325
static void
286
326
show_kprobe_multi_json (struct bpf_link_info * info , json_writer_t * wtr )
287
327
{
288
328
struct addr_cookie * data ;
289
329
__u32 i , j = 0 ;
330
+ bool is_ibt_enabled ;
290
331
291
332
jsonw_bool_field (json_wtr , "retprobe" ,
292
333
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)
306
347
if (!dd .sym_count )
307
348
goto error ;
308
349
350
+ is_ibt_enabled = is_x86_ibt_enabled ();
309
351
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 ))
311
354
continue ;
312
355
jsonw_start_object (json_wtr );
313
356
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)
719
762
{
720
763
struct addr_cookie * data ;
721
764
__u32 i , j = 0 ;
765
+ bool is_ibt_enabled ;
722
766
723
767
if (!info -> kprobe_multi .count )
724
768
return ;
@@ -742,9 +786,11 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
742
786
if (!dd .sym_count )
743
787
goto error ;
744
788
789
+ is_ibt_enabled = is_x86_ibt_enabled ();
745
790
printf ("\n\t%-16s %-16s %s" , "addr" , "cookie" , "func [module]" );
746
791
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 ))
748
794
continue ;
749
795
printf ("\n\t%016lx %-16llx %s" ,
750
796
dd .sym_mapping [i ].address , data [j ].cookie , dd .sym_mapping [i ].name );
0 commit comments