@@ -516,6 +516,122 @@ static void test_attach_api_fails(void)
516
516
uprobe_multi__destroy (skel );
517
517
}
518
518
519
+ #ifdef __x86_64__
520
+ noinline void uprobe_multi_error_func (void )
521
+ {
522
+ /*
523
+ * If --fcf-protection=branch is enabled the gcc generates endbr as
524
+ * first instruction, so marking the exact address of int3 with the
525
+ * symbol to be used in the attach_uprobe_fail_trap test below.
526
+ */
527
+ asm volatile (
528
+ ".globl uprobe_multi_error_func_int3; \n"
529
+ "uprobe_multi_error_func_int3: \n"
530
+ "int3 \n"
531
+ );
532
+ }
533
+
534
+ /*
535
+ * Attaching uprobe on uprobe_multi_error_func results in error
536
+ * because it already starts with int3 instruction.
537
+ */
538
+ static void attach_uprobe_fail_trap (struct uprobe_multi * skel )
539
+ {
540
+ LIBBPF_OPTS (bpf_uprobe_multi_opts , opts );
541
+ const char * syms [4 ] = {
542
+ "uprobe_multi_func_1" ,
543
+ "uprobe_multi_func_2" ,
544
+ "uprobe_multi_func_3" ,
545
+ "uprobe_multi_error_func_int3" ,
546
+ };
547
+
548
+ opts .syms = syms ;
549
+ opts .cnt = ARRAY_SIZE (syms );
550
+
551
+ skel -> links .uprobe = bpf_program__attach_uprobe_multi (skel -> progs .uprobe , -1 ,
552
+ "/proc/self/exe" , NULL , & opts );
553
+ if (!ASSERT_ERR_PTR (skel -> links .uprobe , "bpf_program__attach_uprobe_multi" )) {
554
+ bpf_link__destroy (skel -> links .uprobe );
555
+ skel -> links .uprobe = NULL ;
556
+ }
557
+ }
558
+ #else
559
+ static void attach_uprobe_fail_trap (struct uprobe_multi * skel ) { }
560
+ #endif
561
+
562
+ short sema_1 __used , sema_2 __used ;
563
+
564
+ static void attach_uprobe_fail_refctr (struct uprobe_multi * skel )
565
+ {
566
+ unsigned long * tmp_offsets = NULL , * tmp_ref_ctr_offsets = NULL ;
567
+ unsigned long offsets [3 ], ref_ctr_offsets [3 ];
568
+ LIBBPF_OPTS (bpf_link_create_opts , opts );
569
+ const char * path = "/proc/self/exe" ;
570
+ const char * syms [3 ] = {
571
+ "uprobe_multi_func_1" ,
572
+ "uprobe_multi_func_2" ,
573
+ };
574
+ const char * sema [3 ] = {
575
+ "sema_1" ,
576
+ "sema_2" ,
577
+ };
578
+ int prog_fd , link_fd , err ;
579
+
580
+ prog_fd = bpf_program__fd (skel -> progs .uprobe_extra );
581
+
582
+ err = elf_resolve_syms_offsets ("/proc/self/exe" , 2 , (const char * * ) & syms ,
583
+ & tmp_offsets , STT_FUNC );
584
+ if (!ASSERT_OK (err , "elf_resolve_syms_offsets_func" ))
585
+ return ;
586
+
587
+ err = elf_resolve_syms_offsets ("/proc/self/exe" , 2 , (const char * * ) & sema ,
588
+ & tmp_ref_ctr_offsets , STT_OBJECT );
589
+ if (!ASSERT_OK (err , "elf_resolve_syms_offsets_sema" ))
590
+ goto cleanup ;
591
+
592
+ /*
593
+ * We attach to 3 uprobes on 2 functions, so 2 uprobes share single function,
594
+ * but with different ref_ctr_offset which is not allowed and results in fail.
595
+ */
596
+ offsets [0 ] = tmp_offsets [0 ]; /* uprobe_multi_func_1 */
597
+ offsets [1 ] = tmp_offsets [1 ]; /* uprobe_multi_func_2 */
598
+ offsets [2 ] = tmp_offsets [1 ]; /* uprobe_multi_func_2 */
599
+
600
+ ref_ctr_offsets [0 ] = tmp_ref_ctr_offsets [0 ]; /* sema_1 */
601
+ ref_ctr_offsets [1 ] = tmp_ref_ctr_offsets [1 ]; /* sema_2 */
602
+ ref_ctr_offsets [2 ] = tmp_ref_ctr_offsets [0 ]; /* sema_1, error */
603
+
604
+ opts .uprobe_multi .path = path ;
605
+ opts .uprobe_multi .offsets = (const unsigned long * ) & offsets ;
606
+ opts .uprobe_multi .ref_ctr_offsets = (const unsigned long * ) & ref_ctr_offsets ;
607
+ opts .uprobe_multi .cnt = 3 ;
608
+
609
+ link_fd = bpf_link_create (prog_fd , 0 , BPF_TRACE_UPROBE_MULTI , & opts );
610
+ if (!ASSERT_ERR (link_fd , "link_fd" ))
611
+ close (link_fd );
612
+
613
+ cleanup :
614
+ free (tmp_ref_ctr_offsets );
615
+ free (tmp_offsets );
616
+ }
617
+
618
+ static void test_attach_uprobe_fails (void )
619
+ {
620
+ struct uprobe_multi * skel = NULL ;
621
+
622
+ skel = uprobe_multi__open_and_load ();
623
+ if (!ASSERT_OK_PTR (skel , "uprobe_multi__open_and_load" ))
624
+ return ;
625
+
626
+ /* attach fails due to adding uprobe on trap instruction, x86_64 only */
627
+ attach_uprobe_fail_trap (skel );
628
+
629
+ /* attach fail due to wrong ref_ctr_offs on one of the uprobes */
630
+ attach_uprobe_fail_refctr (skel );
631
+
632
+ uprobe_multi__destroy (skel );
633
+ }
634
+
519
635
static void __test_link_api (struct child * child )
520
636
{
521
637
int prog_fd , link1_fd = -1 , link2_fd = -1 , link3_fd = -1 , link4_fd = -1 ;
@@ -703,4 +819,6 @@ void test_uprobe_multi_test(void)
703
819
test_bench_attach_usdt ();
704
820
if (test__start_subtest ("attach_api_fails" ))
705
821
test_attach_api_fails ();
822
+ if (test__start_subtest ("attach_uprobe_fails" ))
823
+ test_attach_uprobe_fails ();
706
824
}
0 commit comments