mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	bpf, libbpf: introduce bpf_object__probe_caps to test BPF capabilities
It currently only checks whether kernel supports map/prog names. This capability check will be used in the next two commits to skip setting prog/map names. Suggested-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Stanislav Fomichev <sdf@google.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
		
							parent
							
								
									8c4905b995
								
							
						
					
					
						commit
						47eff61777
					
				
					 1 changed files with 58 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -24,6 +24,7 @@
 | 
			
		|||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/bpf.h>
 | 
			
		||||
#include <linux/btf.h>
 | 
			
		||||
#include <linux/filter.h>
 | 
			
		||||
#include <linux/list.h>
 | 
			
		||||
#include <linux/limits.h>
 | 
			
		||||
#include <linux/perf_event.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +115,11 @@ void libbpf_set_print(libbpf_print_fn_t warn,
 | 
			
		|||
# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct bpf_capabilities {
 | 
			
		||||
	/* v4.14: kernel support for program & map names. */
 | 
			
		||||
	__u32 name:1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * bpf_prog should be a better name but it has been used in
 | 
			
		||||
 * linux/filter.h.
 | 
			
		||||
| 
						 | 
				
			
			@ -160,6 +166,8 @@ struct bpf_program {
 | 
			
		|||
	void *func_info;
 | 
			
		||||
	__u32 func_info_rec_size;
 | 
			
		||||
	__u32 func_info_len;
 | 
			
		||||
 | 
			
		||||
	struct bpf_capabilities *caps;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct bpf_map {
 | 
			
		||||
| 
						 | 
				
			
			@ -221,6 +229,8 @@ struct bpf_object {
 | 
			
		|||
	void *priv;
 | 
			
		||||
	bpf_object_clear_priv_t clear_priv;
 | 
			
		||||
 | 
			
		||||
	struct bpf_capabilities caps;
 | 
			
		||||
 | 
			
		||||
	char path[];
 | 
			
		||||
};
 | 
			
		||||
#define obj_elf_valid(o)	((o)->efile.elf)
 | 
			
		||||
| 
						 | 
				
			
			@ -342,6 +352,7 @@ bpf_object__add_program(struct bpf_object *obj, void *data, size_t size,
 | 
			
		|||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	prog.caps = &obj->caps;
 | 
			
		||||
	progs = obj->programs;
 | 
			
		||||
	nr_progs = obj->nr_programs;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1135,6 +1146,52 @@ int bpf_map__reuse_fd(struct bpf_map *map, int fd)
 | 
			
		|||
	return -errno;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
bpf_object__probe_name(struct bpf_object *obj)
 | 
			
		||||
{
 | 
			
		||||
	struct bpf_load_program_attr attr;
 | 
			
		||||
	char *cp, errmsg[STRERR_BUFSIZE];
 | 
			
		||||
	struct bpf_insn insns[] = {
 | 
			
		||||
		BPF_MOV64_IMM(BPF_REG_0, 0),
 | 
			
		||||
		BPF_EXIT_INSN(),
 | 
			
		||||
	};
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	/* make sure basic loading works */
 | 
			
		||||
 | 
			
		||||
	memset(&attr, 0, sizeof(attr));
 | 
			
		||||
	attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
 | 
			
		||||
	attr.insns = insns;
 | 
			
		||||
	attr.insns_cnt = ARRAY_SIZE(insns);
 | 
			
		||||
	attr.license = "GPL";
 | 
			
		||||
 | 
			
		||||
	ret = bpf_load_program_xattr(&attr, NULL, 0);
 | 
			
		||||
	if (ret < 0) {
 | 
			
		||||
		cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
 | 
			
		||||
		pr_warning("Error in %s():%s(%d). Couldn't load basic 'r0 = 0' BPF program.\n",
 | 
			
		||||
			   __func__, cp, errno);
 | 
			
		||||
		return -errno;
 | 
			
		||||
	}
 | 
			
		||||
	close(ret);
 | 
			
		||||
 | 
			
		||||
	/* now try the same program, but with the name */
 | 
			
		||||
 | 
			
		||||
	attr.name = "test";
 | 
			
		||||
	ret = bpf_load_program_xattr(&attr, NULL, 0);
 | 
			
		||||
	if (ret >= 0) {
 | 
			
		||||
		obj->caps.name = 1;
 | 
			
		||||
		close(ret);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
bpf_object__probe_caps(struct bpf_object *obj)
 | 
			
		||||
{
 | 
			
		||||
	return bpf_object__probe_name(obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
bpf_object__create_maps(struct bpf_object *obj)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1708,6 +1765,7 @@ int bpf_object__load(struct bpf_object *obj)
 | 
			
		|||
 | 
			
		||||
	obj->loaded = true;
 | 
			
		||||
 | 
			
		||||
	CHECK_ERR(bpf_object__probe_caps(obj), err, out);
 | 
			
		||||
	CHECK_ERR(bpf_object__create_maps(obj), err, out);
 | 
			
		||||
	CHECK_ERR(bpf_object__relocate(obj), err, out);
 | 
			
		||||
	CHECK_ERR(bpf_object__load_progs(obj), err, out);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue