Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2019-03-16 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) Fix a umem memory leak on cleanup in AF_XDP, from Björn. 2) Fix BTF to properly resolve forward-declared enums into their corresponding full enum definition types during deduplication, from Andrii. 3) Fix libbpf to reject invalid flags in xsk_socket__create(), from Magnus. 4) Fix accessing invalid pointer returned from bpf_tcp_sock() and bpf_sk_fullsock() after bpf_sk_release() was called, from Martin. 5) Fix generation of load/store DW instructions in PPC JIT, from Naveen. 6) Various fixes in BPF helper function documentation in bpf.h UAPI header used to bpf-helpers(7) man page, from Quentin. 7) Fix segfault in BPF test_progs when prog loading failed, from Yonghong. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -1602,16 +1602,12 @@ static bool btf_equal_int(struct btf_type *t1, struct btf_type *t2)
|
||||
/* Calculate type signature hash of ENUM. */
|
||||
static __u32 btf_hash_enum(struct btf_type *t)
|
||||
{
|
||||
struct btf_enum *member = (struct btf_enum *)(t + 1);
|
||||
__u32 vlen = BTF_INFO_VLEN(t->info);
|
||||
__u32 h = btf_hash_common(t);
|
||||
int i;
|
||||
__u32 h;
|
||||
|
||||
for (i = 0; i < vlen; i++) {
|
||||
h = hash_combine(h, member->name_off);
|
||||
h = hash_combine(h, member->val);
|
||||
member++;
|
||||
}
|
||||
/* don't hash vlen and enum members to support enum fwd resolving */
|
||||
h = hash_combine(0, t->name_off);
|
||||
h = hash_combine(h, t->info & ~0xffff);
|
||||
h = hash_combine(h, t->size);
|
||||
return h;
|
||||
}
|
||||
|
||||
@@ -1637,6 +1633,22 @@ static bool btf_equal_enum(struct btf_type *t1, struct btf_type *t2)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool btf_is_enum_fwd(struct btf_type *t)
|
||||
{
|
||||
return BTF_INFO_KIND(t->info) == BTF_KIND_ENUM &&
|
||||
BTF_INFO_VLEN(t->info) == 0;
|
||||
}
|
||||
|
||||
static bool btf_compat_enum(struct btf_type *t1, struct btf_type *t2)
|
||||
{
|
||||
if (!btf_is_enum_fwd(t1) && !btf_is_enum_fwd(t2))
|
||||
return btf_equal_enum(t1, t2);
|
||||
/* ignore vlen when comparing */
|
||||
return t1->name_off == t2->name_off &&
|
||||
(t1->info & ~0xffff) == (t2->info & ~0xffff) &&
|
||||
t1->size == t2->size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate type signature hash of STRUCT/UNION, ignoring referenced type IDs,
|
||||
* as referenced type IDs equivalence is established separately during type
|
||||
@@ -1860,6 +1872,17 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
|
||||
new_id = cand_node->type_id;
|
||||
break;
|
||||
}
|
||||
if (d->opts.dont_resolve_fwds)
|
||||
continue;
|
||||
if (btf_compat_enum(t, cand)) {
|
||||
if (btf_is_enum_fwd(t)) {
|
||||
/* resolve fwd to full enum */
|
||||
new_id = cand_node->type_id;
|
||||
break;
|
||||
}
|
||||
/* resolve canonical enum fwd to full enum */
|
||||
d->map[cand_node->type_id] = type_id;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2084,15 +2107,15 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
|
||||
return fwd_kind == real_kind;
|
||||
}
|
||||
|
||||
if (cand_type->info != canon_type->info)
|
||||
return 0;
|
||||
|
||||
switch (cand_kind) {
|
||||
case BTF_KIND_INT:
|
||||
return btf_equal_int(cand_type, canon_type);
|
||||
|
||||
case BTF_KIND_ENUM:
|
||||
return btf_equal_enum(cand_type, canon_type);
|
||||
if (d->opts.dont_resolve_fwds)
|
||||
return btf_equal_enum(cand_type, canon_type);
|
||||
else
|
||||
return btf_compat_enum(cand_type, canon_type);
|
||||
|
||||
case BTF_KIND_FWD:
|
||||
return btf_equal_common(cand_type, canon_type);
|
||||
@@ -2103,6 +2126,8 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
|
||||
case BTF_KIND_PTR:
|
||||
case BTF_KIND_TYPEDEF:
|
||||
case BTF_KIND_FUNC:
|
||||
if (cand_type->info != canon_type->info)
|
||||
return 0;
|
||||
return btf_dedup_is_equiv(d, cand_type->type, canon_type->type);
|
||||
|
||||
case BTF_KIND_ARRAY: {
|
||||
|
@@ -835,12 +835,19 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags)
|
||||
obj->efile.maps_shndx = idx;
|
||||
else if (strcmp(name, BTF_ELF_SEC) == 0) {
|
||||
obj->btf = btf__new(data->d_buf, data->d_size);
|
||||
if (IS_ERR(obj->btf) || btf__load(obj->btf)) {
|
||||
if (IS_ERR(obj->btf)) {
|
||||
pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n",
|
||||
BTF_ELF_SEC, PTR_ERR(obj->btf));
|
||||
if (!IS_ERR(obj->btf))
|
||||
btf__free(obj->btf);
|
||||
obj->btf = NULL;
|
||||
continue;
|
||||
}
|
||||
err = btf__load(obj->btf);
|
||||
if (err) {
|
||||
pr_warning("Error loading %s into kernel: %d. Ignored and continue.\n",
|
||||
BTF_ELF_SEC, err);
|
||||
btf__free(obj->btf);
|
||||
obj->btf = NULL;
|
||||
err = 0;
|
||||
}
|
||||
} else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) {
|
||||
btf_ext_data = data;
|
||||
|
@@ -126,8 +126,8 @@ static void xsk_set_umem_config(struct xsk_umem_config *cfg,
|
||||
cfg->frame_headroom = usr_cfg->frame_headroom;
|
||||
}
|
||||
|
||||
static void xsk_set_xdp_socket_config(struct xsk_socket_config *cfg,
|
||||
const struct xsk_socket_config *usr_cfg)
|
||||
static int xsk_set_xdp_socket_config(struct xsk_socket_config *cfg,
|
||||
const struct xsk_socket_config *usr_cfg)
|
||||
{
|
||||
if (!usr_cfg) {
|
||||
cfg->rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS;
|
||||
@@ -135,14 +135,19 @@ static void xsk_set_xdp_socket_config(struct xsk_socket_config *cfg,
|
||||
cfg->libbpf_flags = 0;
|
||||
cfg->xdp_flags = 0;
|
||||
cfg->bind_flags = 0;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (usr_cfg->libbpf_flags & ~XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)
|
||||
return -EINVAL;
|
||||
|
||||
cfg->rx_size = usr_cfg->rx_size;
|
||||
cfg->tx_size = usr_cfg->tx_size;
|
||||
cfg->libbpf_flags = usr_cfg->libbpf_flags;
|
||||
cfg->xdp_flags = usr_cfg->xdp_flags;
|
||||
cfg->bind_flags = usr_cfg->bind_flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xsk_umem__create(struct xsk_umem **umem_ptr, void *umem_area, __u64 size,
|
||||
@@ -557,7 +562,9 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
||||
}
|
||||
strncpy(xsk->ifname, ifname, IFNAMSIZ);
|
||||
|
||||
xsk_set_xdp_socket_config(&xsk->config, usr_config);
|
||||
err = xsk_set_xdp_socket_config(&xsk->config, usr_config);
|
||||
if (err)
|
||||
goto out_socket;
|
||||
|
||||
if (rx) {
|
||||
err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING,
|
||||
|
Reference in New Issue
Block a user