forked from mirrors/linux
		
	libbpf: Add support for kprobe session attach
Adding support to attach program in kprobe session mode
with bpf_program__attach_kprobe_multi_opts function.
Adding session bool to bpf_kprobe_multi_opts struct that allows
to load and attach the bpf program via kprobe session.
the attachment to create kprobe multi session.
Also adding new program loader section that allows:
 SEC("kprobe.session/bpf_fentry_test*")
and loads/attaches kprobe program as kprobe session.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20240430112830.1184228-5-jolsa@kernel.org
			
			
This commit is contained in:
		
							parent
							
								
									5c919acef8
								
							
						
					
					
						commit
						2ca178f02b
					
				
					 3 changed files with 41 additions and 3 deletions
				
			
		| 
						 | 
					@ -766,6 +766,7 @@ int bpf_link_create(int prog_fd, int target_fd,
 | 
				
			||||||
			return libbpf_err(-EINVAL);
 | 
								return libbpf_err(-EINVAL);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case BPF_TRACE_KPROBE_MULTI:
 | 
						case BPF_TRACE_KPROBE_MULTI:
 | 
				
			||||||
 | 
						case BPF_TRACE_KPROBE_SESSION:
 | 
				
			||||||
		attr.link_create.kprobe_multi.flags = OPTS_GET(opts, kprobe_multi.flags, 0);
 | 
							attr.link_create.kprobe_multi.flags = OPTS_GET(opts, kprobe_multi.flags, 0);
 | 
				
			||||||
		attr.link_create.kprobe_multi.cnt = OPTS_GET(opts, kprobe_multi.cnt, 0);
 | 
							attr.link_create.kprobe_multi.cnt = OPTS_GET(opts, kprobe_multi.cnt, 0);
 | 
				
			||||||
		attr.link_create.kprobe_multi.syms = ptr_to_u64(OPTS_GET(opts, kprobe_multi.syms, 0));
 | 
							attr.link_create.kprobe_multi.syms = ptr_to_u64(OPTS_GET(opts, kprobe_multi.syms, 0));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9273,6 +9273,7 @@ static int attach_tp(const struct bpf_program *prog, long cookie, struct bpf_lin
 | 
				
			||||||
static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
					static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
				
			||||||
static int attach_trace(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
					static int attach_trace(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
				
			||||||
static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
					static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
				
			||||||
 | 
					static int attach_kprobe_session(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
				
			||||||
static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
					static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
				
			||||||
static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
					static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
				
			||||||
static int attach_iter(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
					static int attach_iter(const struct bpf_program *prog, long cookie, struct bpf_link **link);
 | 
				
			||||||
| 
						 | 
					@ -9289,6 +9290,7 @@ static const struct bpf_sec_def section_defs[] = {
 | 
				
			||||||
	SEC_DEF("uretprobe.s+",		KPROBE, 0, SEC_SLEEPABLE, attach_uprobe),
 | 
						SEC_DEF("uretprobe.s+",		KPROBE, 0, SEC_SLEEPABLE, attach_uprobe),
 | 
				
			||||||
	SEC_DEF("kprobe.multi+",	KPROBE,	BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
 | 
						SEC_DEF("kprobe.multi+",	KPROBE,	BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
 | 
				
			||||||
	SEC_DEF("kretprobe.multi+",	KPROBE,	BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
 | 
						SEC_DEF("kretprobe.multi+",	KPROBE,	BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
 | 
				
			||||||
 | 
						SEC_DEF("kprobe.session+",	KPROBE,	BPF_TRACE_KPROBE_SESSION, SEC_NONE, attach_kprobe_session),
 | 
				
			||||||
	SEC_DEF("uprobe.multi+",	KPROBE,	BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi),
 | 
						SEC_DEF("uprobe.multi+",	KPROBE,	BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi),
 | 
				
			||||||
	SEC_DEF("uretprobe.multi+",	KPROBE,	BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi),
 | 
						SEC_DEF("uretprobe.multi+",	KPROBE,	BPF_TRACE_UPROBE_MULTI, SEC_NONE, attach_uprobe_multi),
 | 
				
			||||||
	SEC_DEF("uprobe.multi.s+",	KPROBE,	BPF_TRACE_UPROBE_MULTI, SEC_SLEEPABLE, attach_uprobe_multi),
 | 
						SEC_DEF("uprobe.multi.s+",	KPROBE,	BPF_TRACE_UPROBE_MULTI, SEC_SLEEPABLE, attach_uprobe_multi),
 | 
				
			||||||
| 
						 | 
					@ -11381,13 +11383,14 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
 | 
				
			||||||
	struct kprobe_multi_resolve res = {
 | 
						struct kprobe_multi_resolve res = {
 | 
				
			||||||
		.pattern = pattern,
 | 
							.pattern = pattern,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
						enum bpf_attach_type attach_type;
 | 
				
			||||||
	struct bpf_link *link = NULL;
 | 
						struct bpf_link *link = NULL;
 | 
				
			||||||
	char errmsg[STRERR_BUFSIZE];
 | 
						char errmsg[STRERR_BUFSIZE];
 | 
				
			||||||
	const unsigned long *addrs;
 | 
						const unsigned long *addrs;
 | 
				
			||||||
	int err, link_fd, prog_fd;
 | 
						int err, link_fd, prog_fd;
 | 
				
			||||||
 | 
						bool retprobe, session;
 | 
				
			||||||
	const __u64 *cookies;
 | 
						const __u64 *cookies;
 | 
				
			||||||
	const char **syms;
 | 
						const char **syms;
 | 
				
			||||||
	bool retprobe;
 | 
					 | 
				
			||||||
	size_t cnt;
 | 
						size_t cnt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!OPTS_VALID(opts, bpf_kprobe_multi_opts))
 | 
						if (!OPTS_VALID(opts, bpf_kprobe_multi_opts))
 | 
				
			||||||
| 
						 | 
					@ -11426,6 +11429,12 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retprobe = OPTS_GET(opts, retprobe, false);
 | 
						retprobe = OPTS_GET(opts, retprobe, false);
 | 
				
			||||||
 | 
						session  = OPTS_GET(opts, session, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (retprobe && session)
 | 
				
			||||||
 | 
							return libbpf_err_ptr(-EINVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						attach_type = session ? BPF_TRACE_KPROBE_SESSION : BPF_TRACE_KPROBE_MULTI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lopts.kprobe_multi.syms = syms;
 | 
						lopts.kprobe_multi.syms = syms;
 | 
				
			||||||
	lopts.kprobe_multi.addrs = addrs;
 | 
						lopts.kprobe_multi.addrs = addrs;
 | 
				
			||||||
| 
						 | 
					@ -11440,7 +11449,7 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	link->detach = &bpf_link__detach_fd;
 | 
						link->detach = &bpf_link__detach_fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_KPROBE_MULTI, &lopts);
 | 
						link_fd = bpf_link_create(prog_fd, 0, attach_type, &lopts);
 | 
				
			||||||
	if (link_fd < 0) {
 | 
						if (link_fd < 0) {
 | 
				
			||||||
		err = -errno;
 | 
							err = -errno;
 | 
				
			||||||
		pr_warn("prog '%s': failed to attach: %s\n",
 | 
							pr_warn("prog '%s': failed to attach: %s\n",
 | 
				
			||||||
| 
						 | 
					@ -11546,6 +11555,32 @@ static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, stru
 | 
				
			||||||
	return libbpf_get_error(*link);
 | 
						return libbpf_get_error(*link);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int attach_kprobe_session(const struct bpf_program *prog, long cookie,
 | 
				
			||||||
 | 
									 struct bpf_link **link)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						LIBBPF_OPTS(bpf_kprobe_multi_opts, opts, .session = true);
 | 
				
			||||||
 | 
						const char *spec;
 | 
				
			||||||
 | 
						char *pattern;
 | 
				
			||||||
 | 
						int n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*link = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* no auto-attach for SEC("kprobe.session") */
 | 
				
			||||||
 | 
						if (strcmp(prog->sec_name, "kprobe.session") == 0)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spec = prog->sec_name + sizeof("kprobe.session/") - 1;
 | 
				
			||||||
 | 
						n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &pattern);
 | 
				
			||||||
 | 
						if (n < 1) {
 | 
				
			||||||
 | 
							pr_warn("kprobe session pattern is invalid: %s\n", pattern);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*link = bpf_program__attach_kprobe_multi_opts(prog, pattern, &opts);
 | 
				
			||||||
 | 
						free(pattern);
 | 
				
			||||||
 | 
						return *link ? 0 : -errno;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link)
 | 
					static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, struct bpf_link **link)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *probe_type = NULL, *binary_path = NULL, *func_name = NULL;
 | 
						char *probe_type = NULL, *binary_path = NULL, *func_name = NULL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -539,10 +539,12 @@ struct bpf_kprobe_multi_opts {
 | 
				
			||||||
	size_t cnt;
 | 
						size_t cnt;
 | 
				
			||||||
	/* create return kprobes */
 | 
						/* create return kprobes */
 | 
				
			||||||
	bool retprobe;
 | 
						bool retprobe;
 | 
				
			||||||
 | 
						/* create session kprobes */
 | 
				
			||||||
 | 
						bool session;
 | 
				
			||||||
	size_t :0;
 | 
						size_t :0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define bpf_kprobe_multi_opts__last_field retprobe
 | 
					#define bpf_kprobe_multi_opts__last_field session
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LIBBPF_API struct bpf_link *
 | 
					LIBBPF_API struct bpf_link *
 | 
				
			||||||
bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
 | 
					bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue