@@ -8993,9 +8993,57 @@ int bpf_link__unpin(struct bpf_link *link)
89938993 return 0 ;
89948994}
89958995
8996+ static int poke_kprobe_events (bool add , const char * name , bool retprobe , uint64_t offset )
8997+ {
8998+ int fd , ret = 0 ;
8999+ pid_t p = getpid ();
9000+ char cmd [260 ], probename [128 ], probefunc [128 ];
9001+ const char * file = "/sys/kernel/debug/tracing/kprobe_events" ;
9002+
9003+ if (retprobe )
9004+ snprintf (probename , sizeof (probename ), "kretprobes/%s_libbpf_%u" , name , p );
9005+ else
9006+ snprintf (probename , sizeof (probename ), "kprobes/%s_libbpf_%u" , name , p );
9007+
9008+ if (offset )
9009+ snprintf (probefunc , sizeof (probefunc ), "%s+%zu" , name , (size_t )offset );
9010+
9011+ if (add ) {
9012+ snprintf (cmd , sizeof (cmd ), "%c:%s %s" ,
9013+ retprobe ? 'r' : 'p' ,
9014+ probename ,
9015+ offset ? probefunc : name );
9016+ } else {
9017+ snprintf (cmd , sizeof (cmd ), "-:%s" , probename );
9018+ }
9019+
9020+ fd = open (file , O_WRONLY | O_APPEND , 0 );
9021+ if (!fd )
9022+ return - errno ;
9023+ ret = write (fd , cmd , strlen (cmd ));
9024+ if (ret < 0 )
9025+ ret = - errno ;
9026+ close (fd );
9027+
9028+ return ret ;
9029+ }
9030+
9031+ static inline int add_kprobe_event_legacy (const char * name , bool retprobe , uint64_t offset )
9032+ {
9033+ return poke_kprobe_events (true, name , retprobe , offset );
9034+ }
9035+
9036+ static inline int remove_kprobe_event_legacy (const char * name , bool retprobe )
9037+ {
9038+ return poke_kprobe_events (false, name , retprobe , 0 );
9039+ }
9040+
89969041struct bpf_link_perf {
89979042 struct bpf_link link ;
89989043 int perf_event_fd ;
9044+ /* legacy kprobe support: keep track of probe identifier and type */
9045+ char * legacy_probe_name ;
9046+ bool legacy_is_retprobe ;
89999047};
90009048
90019049static int bpf_link_perf_detach (struct bpf_link * link )
@@ -9010,13 +9058,19 @@ static int bpf_link_perf_detach(struct bpf_link *link)
90109058 close (perf_link -> perf_event_fd );
90119059 close (link -> fd );
90129060
9013- return libbpf_err (err );
9061+ /* legacy kprobe needs to be removed after perf event fd closure */
9062+ if (perf_link -> legacy_probe_name )
9063+ err = remove_kprobe_event_legacy (perf_link -> legacy_probe_name ,
9064+ perf_link -> legacy_is_retprobe );
9065+
9066+ return err ;
90149067}
90159068
90169069static void bpf_link_perf_dealloc (struct bpf_link * link )
90179070{
90189071 struct bpf_link_perf * perf_link = container_of (link , struct bpf_link_perf , link );
90199072
9073+ free (perf_link -> legacy_probe_name );
90209074 free (perf_link );
90219075}
90229076
@@ -9130,6 +9184,18 @@ static int parse_uint_from_file(const char *file, const char *fmt)
91309184 return ret ;
91319185}
91329186
9187+ static int determine_kprobe_perf_type_legacy (const char * func_name , bool is_retprobe )
9188+ {
9189+ char file [192 ];
9190+
9191+ snprintf (file , sizeof (file ),
9192+ "/sys/kernel/debug/tracing/events/%s/%s_libbpf_%d/id" ,
9193+ is_retprobe ? "kretprobes" : "kprobes" ,
9194+ func_name , getpid ());
9195+
9196+ return parse_uint_from_file (file , "%d\n" );
9197+ }
9198+
91339199static int determine_kprobe_perf_type (void )
91349200{
91359201 const char * file = "/sys/bus/event_source/devices/kprobe/type" ;
@@ -9212,16 +9278,52 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name,
92129278 return pfd ;
92139279}
92149280
9281+ static int perf_event_kprobe_open_legacy (bool retprobe , const char * name , uint64_t offset , int pid )
9282+ {
9283+ struct perf_event_attr attr = {};
9284+ char errmsg [STRERR_BUFSIZE ];
9285+ int type , pfd , err ;
9286+
9287+ err = add_kprobe_event_legacy (name , retprobe , offset );
9288+ if (err < 0 ) {
9289+ pr_warn ("failed to add legacy kprobe event: %s\n" ,
9290+ libbpf_strerror_r (err , errmsg , sizeof (errmsg )));
9291+ return err ;
9292+ }
9293+ type = determine_kprobe_perf_type_legacy (name , retprobe );
9294+ if (type < 0 ) {
9295+ pr_warn ("failed to determine legacy kprobe event id: %s\n" ,
9296+ libbpf_strerror_r (type , errmsg , sizeof (errmsg )));
9297+ return type ;
9298+ }
9299+ attr .size = sizeof (attr );
9300+ attr .config = type ;
9301+ attr .type = PERF_TYPE_TRACEPOINT ;
9302+
9303+ pfd = syscall (__NR_perf_event_open , & attr ,
9304+ pid < 0 ? -1 : pid , /* pid */
9305+ pid == -1 ? 0 : -1 , /* cpu */
9306+ -1 /* group_fd */ , PERF_FLAG_FD_CLOEXEC );
9307+ if (pfd < 0 ) {
9308+ err = - errno ;
9309+ pr_warn ("legacy kprobe perf_event_open() failed: %s\n" ,
9310+ libbpf_strerror_r (err , errmsg , sizeof (errmsg )));
9311+ return err ;
9312+ }
9313+ return pfd ;
9314+ }
9315+
92159316struct bpf_link *
92169317bpf_program__attach_kprobe_opts (struct bpf_program * prog ,
92179318 const char * func_name ,
92189319 const struct bpf_kprobe_opts * opts )
92199320{
92209321 DECLARE_LIBBPF_OPTS (bpf_perf_event_opts , pe_opts );
92219322 char errmsg [STRERR_BUFSIZE ];
9323+ char * legacy_probe = NULL ;
92229324 struct bpf_link * link ;
92239325 unsigned long offset ;
9224- bool retprobe ;
9326+ bool retprobe , legacy ;
92259327 int pfd , err ;
92269328
92279329 if (!OPTS_VALID (opts , bpf_kprobe_opts ))
@@ -9231,8 +9333,19 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog,
92319333 offset = OPTS_GET (opts , offset , 0 );
92329334 pe_opts .bpf_cookie = OPTS_GET (opts , bpf_cookie , 0 );
92339335
9234- pfd = perf_event_open_probe (false /* uprobe */ , retprobe , func_name ,
9235- offset , -1 /* pid */ , 0 /* ref_ctr_off */ );
9336+ legacy = determine_kprobe_perf_type () < 0 ;
9337+ if (!legacy ) {
9338+ pfd = perf_event_open_probe (false /* uprobe */ , retprobe ,
9339+ func_name , offset ,
9340+ -1 /* pid */ , 0 /* ref_ctr_off */ );
9341+ } else {
9342+ legacy_probe = strdup (func_name );
9343+ if (!legacy_probe )
9344+ return libbpf_err_ptr (- ENOMEM );
9345+
9346+ pfd = perf_event_kprobe_open_legacy (retprobe , func_name ,
9347+ offset , -1 /* pid */ );
9348+ }
92369349 if (pfd < 0 ) {
92379350 pr_warn ("prog '%s': failed to create %s '%s' perf event: %s\n" ,
92389351 prog -> name , retprobe ? "kretprobe" : "kprobe" , func_name ,
@@ -9248,6 +9361,13 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog,
92489361 libbpf_strerror_r (err , errmsg , sizeof (errmsg )));
92499362 return libbpf_err_ptr (err );
92509363 }
9364+ if (legacy ) {
9365+ struct bpf_link_perf * perf_link = container_of (link , struct bpf_link_perf , link );
9366+
9367+ perf_link -> legacy_probe_name = legacy_probe ;
9368+ perf_link -> legacy_is_retprobe = retprobe ;
9369+ }
9370+
92519371 return link ;
92529372}
92539373
0 commit comments