Skip to content

Commit 46ed5fc

Browse files
anakryikoAlexei Starovoitov
authored and
Alexei Starovoitov
committed
libbpf: Refactor and simplify legacy kprobe code
Refactor legacy kprobe handling code to follow the same logic as uprobe legacy logic added in the next patchs: - add append_to_file() helper that makes it simpler to work with tracefs file-based interface for creating and deleting probes; - move out probe/event name generation outside of the code that adds/removes it, which simplifies bookkeeping significantly; - change the probe name format to start with "libbpf_" prefix and include offset within kernel function; - switch 'unsigned long' to 'size_t' for specifying kprobe offsets, which is consistent with how uprobes define that, simplifies printf()-ing internally, and also avoids unnecessary complications on architectures where sizeof(long) != sizeof(void *). This patch also implicitly fixes the problem with invalid open() error handling present in poke_kprobe_events(), which (the function) this patch removes. Fixes: ca304b4 ("libbpf: Introduce legacy kprobe events support") Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent d3b0e3b commit 46ed5fc

File tree

2 files changed

+88
-73
lines changed

2 files changed

+88
-73
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 87 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -9011,59 +9011,17 @@ int bpf_link__unpin(struct bpf_link *link)
90119011
return 0;
90129012
}
90139013

9014-
static int poke_kprobe_events(bool add, const char *name, bool retprobe, uint64_t offset)
9015-
{
9016-
int fd, ret = 0;
9017-
pid_t p = getpid();
9018-
char cmd[260], probename[128], probefunc[128];
9019-
const char *file = "/sys/kernel/debug/tracing/kprobe_events";
9020-
9021-
if (retprobe)
9022-
snprintf(probename, sizeof(probename), "kretprobes/%s_libbpf_%u", name, p);
9023-
else
9024-
snprintf(probename, sizeof(probename), "kprobes/%s_libbpf_%u", name, p);
9025-
9026-
if (offset)
9027-
snprintf(probefunc, sizeof(probefunc), "%s+%zu", name, (size_t)offset);
9028-
9029-
if (add) {
9030-
snprintf(cmd, sizeof(cmd), "%c:%s %s",
9031-
retprobe ? 'r' : 'p',
9032-
probename,
9033-
offset ? probefunc : name);
9034-
} else {
9035-
snprintf(cmd, sizeof(cmd), "-:%s", probename);
9036-
}
9037-
9038-
fd = open(file, O_WRONLY | O_APPEND, 0);
9039-
if (!fd)
9040-
return -errno;
9041-
ret = write(fd, cmd, strlen(cmd));
9042-
if (ret < 0)
9043-
ret = -errno;
9044-
close(fd);
9045-
9046-
return ret;
9047-
}
9048-
9049-
static inline int add_kprobe_event_legacy(const char *name, bool retprobe, uint64_t offset)
9050-
{
9051-
return poke_kprobe_events(true, name, retprobe, offset);
9052-
}
9053-
9054-
static inline int remove_kprobe_event_legacy(const char *name, bool retprobe)
9055-
{
9056-
return poke_kprobe_events(false, name, retprobe, 0);
9057-
}
9058-
90599014
struct bpf_link_perf {
90609015
struct bpf_link link;
90619016
int perf_event_fd;
90629017
/* legacy kprobe support: keep track of probe identifier and type */
90639018
char *legacy_probe_name;
9019+
bool legacy_is_kprobe;
90649020
bool legacy_is_retprobe;
90659021
};
90669022

9023+
static int remove_kprobe_event_legacy(const char *probe_name, bool retprobe);
9024+
90679025
static int bpf_link_perf_detach(struct bpf_link *link)
90689026
{
90699027
struct bpf_link_perf *perf_link = container_of(link, struct bpf_link_perf, link);
@@ -9077,9 +9035,12 @@ static int bpf_link_perf_detach(struct bpf_link *link)
90779035
close(link->fd);
90789036

90799037
/* legacy kprobe needs to be removed after perf event fd closure */
9080-
if (perf_link->legacy_probe_name)
9081-
err = remove_kprobe_event_legacy(perf_link->legacy_probe_name,
9082-
perf_link->legacy_is_retprobe);
9038+
if (perf_link->legacy_probe_name) {
9039+
if (perf_link->legacy_is_kprobe) {
9040+
err = remove_kprobe_event_legacy(perf_link->legacy_probe_name,
9041+
perf_link->legacy_is_retprobe);
9042+
}
9043+
}
90839044

90849045
return err;
90859046
}
@@ -9202,18 +9163,6 @@ static int parse_uint_from_file(const char *file, const char *fmt)
92029163
return ret;
92039164
}
92049165

9205-
static int determine_kprobe_perf_type_legacy(const char *func_name, bool is_retprobe)
9206-
{
9207-
char file[192];
9208-
9209-
snprintf(file, sizeof(file),
9210-
"/sys/kernel/debug/tracing/events/%s/%s_libbpf_%d/id",
9211-
is_retprobe ? "kretprobes" : "kprobes",
9212-
func_name, getpid());
9213-
9214-
return parse_uint_from_file(file, "%d\n");
9215-
}
9216-
92179166
static int determine_kprobe_perf_type(void)
92189167
{
92199168
const char *file = "/sys/bus/event_source/devices/kprobe/type";
@@ -9296,21 +9245,79 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name,
92969245
return pfd;
92979246
}
92989247

9299-
static int perf_event_kprobe_open_legacy(bool retprobe, const char *name, uint64_t offset, int pid)
9248+
static int append_to_file(const char *file, const char *fmt, ...)
9249+
{
9250+
int fd, n, err = 0;
9251+
va_list ap;
9252+
9253+
fd = open(file, O_WRONLY | O_APPEND, 0);
9254+
if (fd < 0)
9255+
return -errno;
9256+
9257+
va_start(ap, fmt);
9258+
n = vdprintf(fd, fmt, ap);
9259+
va_end(ap);
9260+
9261+
if (n < 0)
9262+
err = -errno;
9263+
9264+
close(fd);
9265+
return err;
9266+
}
9267+
9268+
static void gen_kprobe_legacy_event_name(char *buf, size_t buf_sz,
9269+
const char *kfunc_name, size_t offset)
9270+
{
9271+
snprintf(buf, buf_sz, "libbpf_%u_%s_0x%zx", getpid(), kfunc_name, offset);
9272+
}
9273+
9274+
static int add_kprobe_event_legacy(const char *probe_name, bool retprobe,
9275+
const char *kfunc_name, size_t offset)
9276+
{
9277+
const char *file = "/sys/kernel/debug/tracing/kprobe_events";
9278+
9279+
return append_to_file(file, "%c:%s/%s %s+0x%zx",
9280+
retprobe ? 'r' : 'p',
9281+
retprobe ? "kretprobes" : "kprobes",
9282+
probe_name, kfunc_name, offset);
9283+
}
9284+
9285+
static int remove_kprobe_event_legacy(const char *probe_name, bool retprobe)
9286+
{
9287+
const char *file = "/sys/kernel/debug/tracing/kprobe_events";
9288+
9289+
return append_to_file(file, "-:%s/%s", retprobe ? "kretprobes" : "kprobes", probe_name);
9290+
}
9291+
9292+
static int determine_kprobe_perf_type_legacy(const char *probe_name, bool retprobe)
9293+
{
9294+
char file[256];
9295+
9296+
snprintf(file, sizeof(file),
9297+
"/sys/kernel/debug/tracing/events/%s/%s/id",
9298+
retprobe ? "kretprobes" : "kprobes", probe_name);
9299+
9300+
return parse_uint_from_file(file, "%d\n");
9301+
}
9302+
9303+
static int perf_event_kprobe_open_legacy(const char *probe_name, bool retprobe,
9304+
const char *kfunc_name, size_t offset, int pid)
93009305
{
93019306
struct perf_event_attr attr = {};
93029307
char errmsg[STRERR_BUFSIZE];
93039308
int type, pfd, err;
93049309

9305-
err = add_kprobe_event_legacy(name, retprobe, offset);
9310+
err = add_kprobe_event_legacy(probe_name, retprobe, kfunc_name, offset);
93069311
if (err < 0) {
9307-
pr_warn("failed to add legacy kprobe event: %s\n",
9312+
pr_warn("failed to add legacy kprobe event for '%s+0x%zx': %s\n",
9313+
kfunc_name, offset,
93089314
libbpf_strerror_r(err, errmsg, sizeof(errmsg)));
93099315
return err;
93109316
}
9311-
type = determine_kprobe_perf_type_legacy(name, retprobe);
9317+
type = determine_kprobe_perf_type_legacy(probe_name, retprobe);
93129318
if (type < 0) {
9313-
pr_warn("failed to determine legacy kprobe event id: %s\n",
9319+
pr_warn("failed to determine legacy kprobe event id for '%s+0x%zx': %s\n",
9320+
kfunc_name, offset,
93149321
libbpf_strerror_r(type, errmsg, sizeof(errmsg)));
93159322
return type;
93169323
}
@@ -9340,7 +9347,7 @@ bpf_program__attach_kprobe_opts(const struct bpf_program *prog,
93409347
char errmsg[STRERR_BUFSIZE];
93419348
char *legacy_probe = NULL;
93429349
struct bpf_link *link;
9343-
unsigned long offset;
9350+
size_t offset;
93449351
bool retprobe, legacy;
93459352
int pfd, err;
93469353

@@ -9357,33 +9364,41 @@ bpf_program__attach_kprobe_opts(const struct bpf_program *prog,
93579364
func_name, offset,
93589365
-1 /* pid */, 0 /* ref_ctr_off */);
93599366
} else {
9367+
char probe_name[256];
9368+
9369+
gen_kprobe_legacy_event_name(probe_name, sizeof(probe_name),
9370+
func_name, offset);
9371+
93609372
legacy_probe = strdup(func_name);
93619373
if (!legacy_probe)
93629374
return libbpf_err_ptr(-ENOMEM);
93639375

9364-
pfd = perf_event_kprobe_open_legacy(retprobe, func_name,
9376+
pfd = perf_event_kprobe_open_legacy(legacy_probe, retprobe, func_name,
93659377
offset, -1 /* pid */);
93669378
}
93679379
if (pfd < 0) {
9368-
err = pfd;
9369-
pr_warn("prog '%s': failed to create %s '%s' perf event: %s\n",
9370-
prog->name, retprobe ? "kretprobe" : "kprobe", func_name,
9380+
err = -errno;
9381+
pr_warn("prog '%s': failed to create %s '%s+0x%zx' perf event: %s\n",
9382+
prog->name, retprobe ? "kretprobe" : "kprobe",
9383+
func_name, offset,
93719384
libbpf_strerror_r(err, errmsg, sizeof(errmsg)));
93729385
goto err_out;
93739386
}
93749387
link = bpf_program__attach_perf_event_opts(prog, pfd, &pe_opts);
93759388
err = libbpf_get_error(link);
93769389
if (err) {
93779390
close(pfd);
9378-
pr_warn("prog '%s': failed to attach to %s '%s': %s\n",
9379-
prog->name, retprobe ? "kretprobe" : "kprobe", func_name,
9391+
pr_warn("prog '%s': failed to attach to %s '%s+0x%zx': %s\n",
9392+
prog->name, retprobe ? "kretprobe" : "kprobe",
9393+
func_name, offset,
93809394
libbpf_strerror_r(err, errmsg, sizeof(errmsg)));
93819395
goto err_out;
93829396
}
93839397
if (legacy) {
93849398
struct bpf_link_perf *perf_link = container_of(link, struct bpf_link_perf, link);
93859399

93869400
perf_link->legacy_probe_name = legacy_probe;
9401+
perf_link->legacy_is_kprobe = true;
93879402
perf_link->legacy_is_retprobe = retprobe;
93889403
}
93899404

tools/lib/bpf/libbpf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ struct bpf_kprobe_opts {
269269
/* custom user-provided value fetchable through bpf_get_attach_cookie() */
270270
__u64 bpf_cookie;
271271
/* function's offset to install kprobe to */
272-
unsigned long offset;
272+
size_t offset;
273273
/* kprobe is return probe */
274274
bool retprobe;
275275
size_t :0;

0 commit comments

Comments
 (0)