@@ -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+ 
285325static  void 
286326show_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,11 +347,13 @@ 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 );
313- 		jsonw_uint_field (json_wtr , "addr" , dd . sym_mapping [ i ]. address );
356+ 		jsonw_uint_field (json_wtr , "addr" , ( unsigned long ) data [ j ]. addr );
314357		jsonw_string_field (json_wtr , "func" , dd .sym_mapping [i ].name );
315358		/* Print null if it is vmlinux */ 
316359		if  (dd .sym_mapping [i ].module [0 ] ==  '\0' ) {
@@ -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,12 +786,14 @@ 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" ,
750- 		       dd . sym_mapping [ i ]. address , data [j ].cookie , dd .sym_mapping [i ].name );
796+ 		       ( unsigned long ) data [ j ]. addr , data [j ].cookie , dd .sym_mapping [i ].name );
751797		if  (dd .sym_mapping [i ].module [0 ] !=  '\0' )
752798			printf (" [%s]  " , dd .sym_mapping [i ].module );
753799		else 
0 commit comments