mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	bpf: Add support for BPF_OBJ_GET_INFO_BY_FD for bpf_link
Add ability to fetch bpf_link details through BPF_OBJ_GET_INFO_BY_FD command. Also enhance show_fdinfo to potentially include bpf_link type-specific information (similarly to obj_info). Also introduce enum bpf_link_type stored in bpf_link itself and expose it in UAPI. bpf_link_tracing also now will store and return bpf_attach_type. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20200429001614.1544-5-andriin@fb.com
This commit is contained in:
		
							parent
							
								
									2d602c8cf4
								
							
						
					
					
						commit
						f2e10bff16
					
				
					 9 changed files with 253 additions and 24 deletions
				
			
		| 
						 | 
				
			
			@ -57,8 +57,6 @@ struct bpf_cgroup_link {
 | 
			
		|||
	enum bpf_attach_type type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern const struct bpf_link_ops bpf_cgroup_link_lops;
 | 
			
		||||
 | 
			
		||||
struct bpf_prog_list {
 | 
			
		||||
	struct list_head node;
 | 
			
		||||
	struct bpf_prog *prog;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1026,9 +1026,11 @@ extern const struct file_operations bpf_prog_fops;
 | 
			
		|||
	extern const struct bpf_verifier_ops _name ## _verifier_ops;
 | 
			
		||||
#define BPF_MAP_TYPE(_id, _ops) \
 | 
			
		||||
	extern const struct bpf_map_ops _ops;
 | 
			
		||||
#define BPF_LINK_TYPE(_id, _name)
 | 
			
		||||
#include <linux/bpf_types.h>
 | 
			
		||||
#undef BPF_PROG_TYPE
 | 
			
		||||
#undef BPF_MAP_TYPE
 | 
			
		||||
#undef BPF_LINK_TYPE
 | 
			
		||||
 | 
			
		||||
extern const struct bpf_prog_ops bpf_offload_prog_ops;
 | 
			
		||||
extern const struct bpf_verifier_ops tc_cls_act_analyzer_ops;
 | 
			
		||||
| 
						 | 
				
			
			@ -1086,6 +1088,7 @@ int bpf_prog_new_fd(struct bpf_prog *prog);
 | 
			
		|||
struct bpf_link {
 | 
			
		||||
	atomic64_t refcnt;
 | 
			
		||||
	u32 id;
 | 
			
		||||
	enum bpf_link_type type;
 | 
			
		||||
	const struct bpf_link_ops *ops;
 | 
			
		||||
	struct bpf_prog *prog;
 | 
			
		||||
	struct work_struct work;
 | 
			
		||||
| 
						 | 
				
			
			@ -1103,9 +1106,12 @@ struct bpf_link_ops {
 | 
			
		|||
	void (*dealloc)(struct bpf_link *link);
 | 
			
		||||
	int (*update_prog)(struct bpf_link *link, struct bpf_prog *new_prog,
 | 
			
		||||
			   struct bpf_prog *old_prog);
 | 
			
		||||
	void (*show_fdinfo)(const struct bpf_link *link, struct seq_file *seq);
 | 
			
		||||
	int (*fill_link_info)(const struct bpf_link *link,
 | 
			
		||||
			      struct bpf_link_info *info);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void bpf_link_init(struct bpf_link *link,
 | 
			
		||||
void bpf_link_init(struct bpf_link *link, enum bpf_link_type type,
 | 
			
		||||
		   const struct bpf_link_ops *ops, struct bpf_prog *prog);
 | 
			
		||||
int bpf_link_prime(struct bpf_link *link, struct bpf_link_primer *primer);
 | 
			
		||||
int bpf_link_settle(struct bpf_link_primer *primer);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -118,3 +118,9 @@ BPF_MAP_TYPE(BPF_MAP_TYPE_STACK, stack_map_ops)
 | 
			
		|||
#if defined(CONFIG_BPF_JIT)
 | 
			
		||||
BPF_MAP_TYPE(BPF_MAP_TYPE_STRUCT_OPS, bpf_struct_ops_map_ops)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
BPF_LINK_TYPE(BPF_LINK_TYPE_RAW_TRACEPOINT, raw_tracepoint)
 | 
			
		||||
BPF_LINK_TYPE(BPF_LINK_TYPE_TRACING, tracing)
 | 
			
		||||
#ifdef CONFIG_CGROUP_BPF
 | 
			
		||||
BPF_LINK_TYPE(BPF_LINK_TYPE_CGROUP, cgroup)
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -222,6 +222,15 @@ enum bpf_attach_type {
 | 
			
		|||
 | 
			
		||||
#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
 | 
			
		||||
 | 
			
		||||
enum bpf_link_type {
 | 
			
		||||
	BPF_LINK_TYPE_UNSPEC = 0,
 | 
			
		||||
	BPF_LINK_TYPE_RAW_TRACEPOINT = 1,
 | 
			
		||||
	BPF_LINK_TYPE_TRACING = 2,
 | 
			
		||||
	BPF_LINK_TYPE_CGROUP = 3,
 | 
			
		||||
 | 
			
		||||
	MAX_BPF_LINK_TYPE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* cgroup-bpf attach flags used in BPF_PROG_ATTACH command
 | 
			
		||||
 *
 | 
			
		||||
 * NONE(default): No further bpf programs allowed in the subtree.
 | 
			
		||||
| 
						 | 
				
			
			@ -3612,6 +3621,25 @@ struct bpf_btf_info {
 | 
			
		|||
	__u32 id;
 | 
			
		||||
} __attribute__((aligned(8)));
 | 
			
		||||
 | 
			
		||||
struct bpf_link_info {
 | 
			
		||||
	__u32 type;
 | 
			
		||||
	__u32 id;
 | 
			
		||||
	__u32 prog_id;
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			__aligned_u64 tp_name; /* in/out: tp_name buffer ptr */
 | 
			
		||||
			__u32 tp_name_len;     /* in/out: tp_name buffer len */
 | 
			
		||||
		} raw_tracepoint;
 | 
			
		||||
		struct {
 | 
			
		||||
			__u32 attach_type;
 | 
			
		||||
		} tracing;
 | 
			
		||||
		struct {
 | 
			
		||||
			__u64 cgroup_id;
 | 
			
		||||
			__u32 attach_type;
 | 
			
		||||
		} cgroup;
 | 
			
		||||
	};
 | 
			
		||||
} __attribute__((aligned(8)));
 | 
			
		||||
 | 
			
		||||
/* User bpf_sock_addr struct to access socket fields and sockaddr struct passed
 | 
			
		||||
 * by user and intended to be used by socket (e.g. to bind to, depends on
 | 
			
		||||
 * attach attach type).
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3482,6 +3482,7 @@ extern char __weak __stop_BTF[];
 | 
			
		|||
extern struct btf *btf_vmlinux;
 | 
			
		||||
 | 
			
		||||
#define BPF_MAP_TYPE(_id, _ops)
 | 
			
		||||
#define BPF_LINK_TYPE(_id, _name)
 | 
			
		||||
static union {
 | 
			
		||||
	struct bpf_ctx_convert {
 | 
			
		||||
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
 | 
			
		||||
| 
						 | 
				
			
			@ -3508,6 +3509,7 @@ static u8 bpf_ctx_convert_map[] = {
 | 
			
		|||
	0, /* avoid empty array */
 | 
			
		||||
};
 | 
			
		||||
#undef BPF_MAP_TYPE
 | 
			
		||||
#undef BPF_LINK_TYPE
 | 
			
		||||
 | 
			
		||||
static const struct btf_member *
 | 
			
		||||
btf_get_prog_ctx_type(struct bpf_verifier_log *log, struct btf *btf,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -833,10 +833,48 @@ static void bpf_cgroup_link_dealloc(struct bpf_link *link)
 | 
			
		|||
	kfree(cg_link);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct bpf_link_ops bpf_cgroup_link_lops = {
 | 
			
		||||
static void bpf_cgroup_link_show_fdinfo(const struct bpf_link *link,
 | 
			
		||||
					struct seq_file *seq)
 | 
			
		||||
{
 | 
			
		||||
	struct bpf_cgroup_link *cg_link =
 | 
			
		||||
		container_of(link, struct bpf_cgroup_link, link);
 | 
			
		||||
	u64 cg_id = 0;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&cgroup_mutex);
 | 
			
		||||
	if (cg_link->cgroup)
 | 
			
		||||
		cg_id = cgroup_id(cg_link->cgroup);
 | 
			
		||||
	mutex_unlock(&cgroup_mutex);
 | 
			
		||||
 | 
			
		||||
	seq_printf(seq,
 | 
			
		||||
		   "cgroup_id:\t%llu\n"
 | 
			
		||||
		   "attach_type:\t%d\n",
 | 
			
		||||
		   cg_id,
 | 
			
		||||
		   cg_link->type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int bpf_cgroup_link_fill_link_info(const struct bpf_link *link,
 | 
			
		||||
					  struct bpf_link_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct bpf_cgroup_link *cg_link =
 | 
			
		||||
		container_of(link, struct bpf_cgroup_link, link);
 | 
			
		||||
	u64 cg_id = 0;
 | 
			
		||||
 | 
			
		||||
	mutex_lock(&cgroup_mutex);
 | 
			
		||||
	if (cg_link->cgroup)
 | 
			
		||||
		cg_id = cgroup_id(cg_link->cgroup);
 | 
			
		||||
	mutex_unlock(&cgroup_mutex);
 | 
			
		||||
 | 
			
		||||
	info->cgroup.cgroup_id = cg_id;
 | 
			
		||||
	info->cgroup.attach_type = cg_link->type;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct bpf_link_ops bpf_cgroup_link_lops = {
 | 
			
		||||
	.release = bpf_cgroup_link_release,
 | 
			
		||||
	.dealloc = bpf_cgroup_link_dealloc,
 | 
			
		||||
	.update_prog = cgroup_bpf_replace,
 | 
			
		||||
	.show_fdinfo = bpf_cgroup_link_show_fdinfo,
 | 
			
		||||
	.fill_link_info = bpf_cgroup_link_fill_link_info,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
 | 
			
		||||
| 
						 | 
				
			
			@ -858,7 +896,8 @@ int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
 | 
			
		|||
		err = -ENOMEM;
 | 
			
		||||
		goto out_put_cgroup;
 | 
			
		||||
	}
 | 
			
		||||
	bpf_link_init(&link->link, &bpf_cgroup_link_lops, prog);
 | 
			
		||||
	bpf_link_init(&link->link, BPF_LINK_TYPE_CGROUP, &bpf_cgroup_link_lops,
 | 
			
		||||
		      prog);
 | 
			
		||||
	link->cgroup = cgrp;
 | 
			
		||||
	link->type = attr->link_create.attach_type;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,9 +51,11 @@ static const struct bpf_map_ops * const bpf_map_types[] = {
 | 
			
		|||
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
 | 
			
		||||
#define BPF_MAP_TYPE(_id, _ops) \
 | 
			
		||||
	[_id] = &_ops,
 | 
			
		||||
#define BPF_LINK_TYPE(_id, _name)
 | 
			
		||||
#include <linux/bpf_types.h>
 | 
			
		||||
#undef BPF_PROG_TYPE
 | 
			
		||||
#undef BPF_MAP_TYPE
 | 
			
		||||
#undef BPF_LINK_TYPE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -1548,9 +1550,11 @@ static const struct bpf_prog_ops * const bpf_prog_types[] = {
 | 
			
		|||
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
 | 
			
		||||
	[_id] = & _name ## _prog_ops,
 | 
			
		||||
#define BPF_MAP_TYPE(_id, _ops)
 | 
			
		||||
#define BPF_LINK_TYPE(_id, _name)
 | 
			
		||||
#include <linux/bpf_types.h>
 | 
			
		||||
#undef BPF_PROG_TYPE
 | 
			
		||||
#undef BPF_MAP_TYPE
 | 
			
		||||
#undef BPF_LINK_TYPE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
 | 
			
		||||
| 
						 | 
				
			
			@ -2183,10 +2187,11 @@ static int bpf_obj_get(const union bpf_attr *attr)
 | 
			
		|||
				attr->file_flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bpf_link_init(struct bpf_link *link,
 | 
			
		||||
void bpf_link_init(struct bpf_link *link, enum bpf_link_type type,
 | 
			
		||||
		   const struct bpf_link_ops *ops, struct bpf_prog *prog)
 | 
			
		||||
{
 | 
			
		||||
	atomic64_set(&link->refcnt, 1);
 | 
			
		||||
	link->type = type;
 | 
			
		||||
	link->id = 0;
 | 
			
		||||
	link->ops = ops;
 | 
			
		||||
	link->prog = prog;
 | 
			
		||||
| 
						 | 
				
			
			@ -2266,27 +2271,23 @@ static int bpf_link_release(struct inode *inode, struct file *filp)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_PROC_FS
 | 
			
		||||
static const struct bpf_link_ops bpf_raw_tp_lops;
 | 
			
		||||
static const struct bpf_link_ops bpf_tracing_link_lops;
 | 
			
		||||
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
 | 
			
		||||
#define BPF_MAP_TYPE(_id, _ops)
 | 
			
		||||
#define BPF_LINK_TYPE(_id, _name) [_id] = #_name,
 | 
			
		||||
static const char *bpf_link_type_strs[] = {
 | 
			
		||||
	[BPF_LINK_TYPE_UNSPEC] = "<invalid>",
 | 
			
		||||
#include <linux/bpf_types.h>
 | 
			
		||||
};
 | 
			
		||||
#undef BPF_PROG_TYPE
 | 
			
		||||
#undef BPF_MAP_TYPE
 | 
			
		||||
#undef BPF_LINK_TYPE
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_PROC_FS
 | 
			
		||||
static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp)
 | 
			
		||||
{
 | 
			
		||||
	const struct bpf_link *link = filp->private_data;
 | 
			
		||||
	const struct bpf_prog *prog = link->prog;
 | 
			
		||||
	char prog_tag[sizeof(prog->tag) * 2 + 1] = { };
 | 
			
		||||
	const char *link_type;
 | 
			
		||||
 | 
			
		||||
	if (link->ops == &bpf_raw_tp_lops)
 | 
			
		||||
		link_type = "raw_tracepoint";
 | 
			
		||||
	else if (link->ops == &bpf_tracing_link_lops)
 | 
			
		||||
		link_type = "tracing";
 | 
			
		||||
#ifdef CONFIG_CGROUP_BPF
 | 
			
		||||
	else if (link->ops == &bpf_cgroup_link_lops)
 | 
			
		||||
		link_type = "cgroup";
 | 
			
		||||
#endif
 | 
			
		||||
	else
 | 
			
		||||
		link_type = "unknown";
 | 
			
		||||
 | 
			
		||||
	bin2hex(prog_tag, prog->tag, sizeof(prog->tag));
 | 
			
		||||
	seq_printf(m,
 | 
			
		||||
| 
						 | 
				
			
			@ -2294,10 +2295,12 @@ static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp)
 | 
			
		|||
		   "link_id:\t%u\n"
 | 
			
		||||
		   "prog_tag:\t%s\n"
 | 
			
		||||
		   "prog_id:\t%u\n",
 | 
			
		||||
		   link_type,
 | 
			
		||||
		   bpf_link_type_strs[link->type],
 | 
			
		||||
		   link->id,
 | 
			
		||||
		   prog_tag,
 | 
			
		||||
		   prog->aux->id);
 | 
			
		||||
	if (link->ops->show_fdinfo)
 | 
			
		||||
		link->ops->show_fdinfo(link, m);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2403,6 +2406,7 @@ struct bpf_link *bpf_link_get_from_fd(u32 ufd)
 | 
			
		|||
 | 
			
		||||
struct bpf_tracing_link {
 | 
			
		||||
	struct bpf_link link;
 | 
			
		||||
	enum bpf_attach_type attach_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void bpf_tracing_link_release(struct bpf_link *link)
 | 
			
		||||
| 
						 | 
				
			
			@ -2418,9 +2422,33 @@ static void bpf_tracing_link_dealloc(struct bpf_link *link)
 | 
			
		|||
	kfree(tr_link);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bpf_tracing_link_show_fdinfo(const struct bpf_link *link,
 | 
			
		||||
					 struct seq_file *seq)
 | 
			
		||||
{
 | 
			
		||||
	struct bpf_tracing_link *tr_link =
 | 
			
		||||
		container_of(link, struct bpf_tracing_link, link);
 | 
			
		||||
 | 
			
		||||
	seq_printf(seq,
 | 
			
		||||
		   "attach_type:\t%d\n",
 | 
			
		||||
		   tr_link->attach_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int bpf_tracing_link_fill_link_info(const struct bpf_link *link,
 | 
			
		||||
					   struct bpf_link_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct bpf_tracing_link *tr_link =
 | 
			
		||||
		container_of(link, struct bpf_tracing_link, link);
 | 
			
		||||
 | 
			
		||||
	info->tracing.attach_type = tr_link->attach_type;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct bpf_link_ops bpf_tracing_link_lops = {
 | 
			
		||||
	.release = bpf_tracing_link_release,
 | 
			
		||||
	.dealloc = bpf_tracing_link_dealloc,
 | 
			
		||||
	.show_fdinfo = bpf_tracing_link_show_fdinfo,
 | 
			
		||||
	.fill_link_info = bpf_tracing_link_fill_link_info,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int bpf_tracing_prog_attach(struct bpf_prog *prog)
 | 
			
		||||
| 
						 | 
				
			
			@ -2460,7 +2488,9 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog)
 | 
			
		|||
		err = -ENOMEM;
 | 
			
		||||
		goto out_put_prog;
 | 
			
		||||
	}
 | 
			
		||||
	bpf_link_init(&link->link, &bpf_tracing_link_lops, prog);
 | 
			
		||||
	bpf_link_init(&link->link, BPF_LINK_TYPE_TRACING,
 | 
			
		||||
		      &bpf_tracing_link_lops, prog);
 | 
			
		||||
	link->attach_type = prog->expected_attach_type;
 | 
			
		||||
 | 
			
		||||
	err = bpf_link_prime(&link->link, &link_primer);
 | 
			
		||||
	if (err) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2502,9 +2532,56 @@ static void bpf_raw_tp_link_dealloc(struct bpf_link *link)
 | 
			
		|||
	kfree(raw_tp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bpf_raw_tp_link_show_fdinfo(const struct bpf_link *link,
 | 
			
		||||
					struct seq_file *seq)
 | 
			
		||||
{
 | 
			
		||||
	struct bpf_raw_tp_link *raw_tp_link =
 | 
			
		||||
		container_of(link, struct bpf_raw_tp_link, link);
 | 
			
		||||
 | 
			
		||||
	seq_printf(seq,
 | 
			
		||||
		   "tp_name:\t%s\n",
 | 
			
		||||
		   raw_tp_link->btp->tp->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int bpf_raw_tp_link_fill_link_info(const struct bpf_link *link,
 | 
			
		||||
					  struct bpf_link_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct bpf_raw_tp_link *raw_tp_link =
 | 
			
		||||
		container_of(link, struct bpf_raw_tp_link, link);
 | 
			
		||||
	char __user *ubuf = u64_to_user_ptr(info->raw_tracepoint.tp_name);
 | 
			
		||||
	const char *tp_name = raw_tp_link->btp->tp->name;
 | 
			
		||||
	u32 ulen = info->raw_tracepoint.tp_name_len;
 | 
			
		||||
	size_t tp_len = strlen(tp_name);
 | 
			
		||||
 | 
			
		||||
	if (ulen && !ubuf)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	info->raw_tracepoint.tp_name_len = tp_len + 1;
 | 
			
		||||
 | 
			
		||||
	if (!ubuf)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (ulen >= tp_len + 1) {
 | 
			
		||||
		if (copy_to_user(ubuf, tp_name, tp_len + 1))
 | 
			
		||||
			return -EFAULT;
 | 
			
		||||
	} else {
 | 
			
		||||
		char zero = '\0';
 | 
			
		||||
 | 
			
		||||
		if (copy_to_user(ubuf, tp_name, ulen - 1))
 | 
			
		||||
			return -EFAULT;
 | 
			
		||||
		if (put_user(zero, ubuf + ulen - 1))
 | 
			
		||||
			return -EFAULT;
 | 
			
		||||
		return -ENOSPC;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct bpf_link_ops bpf_raw_tp_link_lops = {
 | 
			
		||||
	.release = bpf_raw_tp_link_release,
 | 
			
		||||
	.dealloc = bpf_raw_tp_link_dealloc,
 | 
			
		||||
	.show_fdinfo = bpf_raw_tp_link_show_fdinfo,
 | 
			
		||||
	.fill_link_info = bpf_raw_tp_link_fill_link_info,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
 | 
			
		||||
| 
						 | 
				
			
			@ -2570,7 +2647,8 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
 | 
			
		|||
		err = -ENOMEM;
 | 
			
		||||
		goto out_put_btp;
 | 
			
		||||
	}
 | 
			
		||||
	bpf_link_init(&link->link, &bpf_raw_tp_link_lops, prog);
 | 
			
		||||
	bpf_link_init(&link->link, BPF_LINK_TYPE_RAW_TRACEPOINT,
 | 
			
		||||
		      &bpf_raw_tp_link_lops, prog);
 | 
			
		||||
	link->btp = btp;
 | 
			
		||||
 | 
			
		||||
	err = bpf_link_prime(&link->link, &link_primer);
 | 
			
		||||
| 
						 | 
				
			
			@ -3366,6 +3444,42 @@ static int bpf_btf_get_info_by_fd(struct btf *btf,
 | 
			
		|||
	return btf_get_info_by_fd(btf, attr, uattr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int bpf_link_get_info_by_fd(struct bpf_link *link,
 | 
			
		||||
				  const union bpf_attr *attr,
 | 
			
		||||
				  union bpf_attr __user *uattr)
 | 
			
		||||
{
 | 
			
		||||
	struct bpf_link_info __user *uinfo = u64_to_user_ptr(attr->info.info);
 | 
			
		||||
	struct bpf_link_info info;
 | 
			
		||||
	u32 info_len = attr->info.info_len;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = bpf_check_uarg_tail_zero(uinfo, sizeof(info), info_len);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
	info_len = min_t(u32, sizeof(info), info_len);
 | 
			
		||||
 | 
			
		||||
	memset(&info, 0, sizeof(info));
 | 
			
		||||
	if (copy_from_user(&info, uinfo, info_len))
 | 
			
		||||
		return -EFAULT;
 | 
			
		||||
 | 
			
		||||
	info.type = link->type;
 | 
			
		||||
	info.id = link->id;
 | 
			
		||||
	info.prog_id = link->prog->aux->id;
 | 
			
		||||
 | 
			
		||||
	if (link->ops->fill_link_info) {
 | 
			
		||||
		err = link->ops->fill_link_info(link, &info);
 | 
			
		||||
		if (err)
 | 
			
		||||
			return err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (copy_to_user(uinfo, &info, info_len) ||
 | 
			
		||||
	    put_user(info_len, &uattr->info.info_len))
 | 
			
		||||
		return -EFAULT;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define BPF_OBJ_GET_INFO_BY_FD_LAST_FIELD info.info
 | 
			
		||||
 | 
			
		||||
static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
 | 
			
		||||
| 
						 | 
				
			
			@ -3390,6 +3504,9 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
 | 
			
		|||
					     uattr);
 | 
			
		||||
	else if (f.file->f_op == &btf_fops)
 | 
			
		||||
		err = bpf_btf_get_info_by_fd(f.file->private_data, attr, uattr);
 | 
			
		||||
	else if (f.file->f_op == &bpf_link_fops)
 | 
			
		||||
		err = bpf_link_get_info_by_fd(f.file->private_data,
 | 
			
		||||
					      attr, uattr);
 | 
			
		||||
	else
 | 
			
		||||
		err = -EINVAL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,9 +28,11 @@ static const struct bpf_verifier_ops * const bpf_verifier_ops[] = {
 | 
			
		|||
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) \
 | 
			
		||||
	[_id] = & _name ## _verifier_ops,
 | 
			
		||||
#define BPF_MAP_TYPE(_id, _ops)
 | 
			
		||||
#define BPF_LINK_TYPE(_id, _name)
 | 
			
		||||
#include <linux/bpf_types.h>
 | 
			
		||||
#undef BPF_PROG_TYPE
 | 
			
		||||
#undef BPF_MAP_TYPE
 | 
			
		||||
#undef BPF_LINK_TYPE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* bpf_check() is a static code analyzer that walks eBPF program
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,6 +113,8 @@ enum bpf_cmd {
 | 
			
		|||
	BPF_MAP_DELETE_BATCH,
 | 
			
		||||
	BPF_LINK_CREATE,
 | 
			
		||||
	BPF_LINK_UPDATE,
 | 
			
		||||
	BPF_LINK_GET_FD_BY_ID,
 | 
			
		||||
	BPF_LINK_GET_NEXT_ID,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum bpf_map_type {
 | 
			
		||||
| 
						 | 
				
			
			@ -220,6 +222,15 @@ enum bpf_attach_type {
 | 
			
		|||
 | 
			
		||||
#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
 | 
			
		||||
 | 
			
		||||
enum bpf_link_type {
 | 
			
		||||
	BPF_LINK_TYPE_UNSPEC = 0,
 | 
			
		||||
	BPF_LINK_TYPE_RAW_TRACEPOINT = 1,
 | 
			
		||||
	BPF_LINK_TYPE_TRACING = 2,
 | 
			
		||||
	BPF_LINK_TYPE_CGROUP = 3,
 | 
			
		||||
 | 
			
		||||
	MAX_BPF_LINK_TYPE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* cgroup-bpf attach flags used in BPF_PROG_ATTACH command
 | 
			
		||||
 *
 | 
			
		||||
 * NONE(default): No further bpf programs allowed in the subtree.
 | 
			
		||||
| 
						 | 
				
			
			@ -523,6 +534,7 @@ union bpf_attr {
 | 
			
		|||
			__u32		prog_id;
 | 
			
		||||
			__u32		map_id;
 | 
			
		||||
			__u32		btf_id;
 | 
			
		||||
			__u32		link_id;
 | 
			
		||||
		};
 | 
			
		||||
		__u32		next_id;
 | 
			
		||||
		__u32		open_flags;
 | 
			
		||||
| 
						 | 
				
			
			@ -3609,6 +3621,25 @@ struct bpf_btf_info {
 | 
			
		|||
	__u32 id;
 | 
			
		||||
} __attribute__((aligned(8)));
 | 
			
		||||
 | 
			
		||||
struct bpf_link_info {
 | 
			
		||||
	__u32 type;
 | 
			
		||||
	__u32 id;
 | 
			
		||||
	__u32 prog_id;
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			__aligned_u64 tp_name; /* in/out: tp_name buffer ptr */
 | 
			
		||||
			__u32 tp_name_len;     /* in/out: tp_name buffer len */
 | 
			
		||||
		} raw_tracepoint;
 | 
			
		||||
		struct {
 | 
			
		||||
			__u32 attach_type;
 | 
			
		||||
		} tracing;
 | 
			
		||||
		struct {
 | 
			
		||||
			__u64 cgroup_id;
 | 
			
		||||
			__u32 attach_type;
 | 
			
		||||
		} cgroup;
 | 
			
		||||
	};
 | 
			
		||||
} __attribute__((aligned(8)));
 | 
			
		||||
 | 
			
		||||
/* User bpf_sock_addr struct to access socket fields and sockaddr struct passed
 | 
			
		||||
 * by user and intended to be used by socket (e.g. to bind to, depends on
 | 
			
		||||
 * attach attach type).
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue