forked from Minki/linux
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Alexei Starovoitov says: ==================== pull-request: bpf 2021-04-01 The following pull-request contains BPF updates for your *net* tree. We've added 11 non-merge commits during the last 8 day(s) which contain a total of 10 files changed, 151 insertions(+), 26 deletions(-). The main changes are: 1) xsk creation fixes, from Ciara. 2) bpf_get_task_stack fix, from Dave. 3) trampoline in modules fix, from Jiri. 4) bpf_obj_get fix for links and progs, from Lorenz. 5) struct_ops progs must be gpl compatible fix, from Toke. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
29684d802e
@ -40,6 +40,7 @@ struct bpf_local_storage;
|
||||
struct bpf_local_storage_map;
|
||||
struct kobject;
|
||||
struct mem_cgroup;
|
||||
struct module;
|
||||
|
||||
extern struct idr btf_idr;
|
||||
extern spinlock_t btf_idr_lock;
|
||||
@ -623,6 +624,7 @@ struct bpf_trampoline {
|
||||
/* Executable image of trampoline */
|
||||
struct bpf_tramp_image *cur_image;
|
||||
u64 selector;
|
||||
struct module *mod;
|
||||
};
|
||||
|
||||
struct bpf_attach_target_info {
|
||||
|
@ -84,7 +84,7 @@ static const char *const bpf_atomic_alu_string[16] = {
|
||||
[BPF_ADD >> 4] = "add",
|
||||
[BPF_AND >> 4] = "and",
|
||||
[BPF_OR >> 4] = "or",
|
||||
[BPF_XOR >> 4] = "or",
|
||||
[BPF_XOR >> 4] = "xor",
|
||||
};
|
||||
|
||||
static const char *const bpf_ldst_string[] = {
|
||||
|
@ -543,11 +543,11 @@ int bpf_obj_get_user(const char __user *pathname, int flags)
|
||||
return PTR_ERR(raw);
|
||||
|
||||
if (type == BPF_TYPE_PROG)
|
||||
ret = bpf_prog_new_fd(raw);
|
||||
ret = (f_flags != O_RDWR) ? -EINVAL : bpf_prog_new_fd(raw);
|
||||
else if (type == BPF_TYPE_MAP)
|
||||
ret = bpf_map_new_fd(raw, f_flags);
|
||||
else if (type == BPF_TYPE_LINK)
|
||||
ret = bpf_link_new_fd(raw);
|
||||
ret = (f_flags != O_RDWR) ? -EINVAL : bpf_link_new_fd(raw);
|
||||
else
|
||||
return -ENOENT;
|
||||
|
||||
|
@ -517,9 +517,17 @@ const struct bpf_func_proto bpf_get_stack_proto = {
|
||||
BPF_CALL_4(bpf_get_task_stack, struct task_struct *, task, void *, buf,
|
||||
u32, size, u64, flags)
|
||||
{
|
||||
struct pt_regs *regs = task_pt_regs(task);
|
||||
struct pt_regs *regs;
|
||||
long res;
|
||||
|
||||
return __bpf_get_stack(regs, task, NULL, buf, size, flags);
|
||||
if (!try_get_task_stack(task))
|
||||
return -EFAULT;
|
||||
|
||||
regs = task_pt_regs(task);
|
||||
res = __bpf_get_stack(regs, task, NULL, buf, size, flags);
|
||||
put_task_stack(task);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
BTF_ID_LIST_SINGLE(bpf_get_task_stack_btf_ids, struct, task_struct)
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/btf.h>
|
||||
#include <linux/rcupdate_trace.h>
|
||||
#include <linux/rcupdate_wait.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/* dummy _ops. The verifier will operate on target program's ops. */
|
||||
const struct bpf_verifier_ops bpf_extension_verifier_ops = {
|
||||
@ -87,6 +88,26 @@ out:
|
||||
return tr;
|
||||
}
|
||||
|
||||
static int bpf_trampoline_module_get(struct bpf_trampoline *tr)
|
||||
{
|
||||
struct module *mod;
|
||||
int err = 0;
|
||||
|
||||
preempt_disable();
|
||||
mod = __module_text_address((unsigned long) tr->func.addr);
|
||||
if (mod && !try_module_get(mod))
|
||||
err = -ENOENT;
|
||||
preempt_enable();
|
||||
tr->mod = mod;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void bpf_trampoline_module_put(struct bpf_trampoline *tr)
|
||||
{
|
||||
module_put(tr->mod);
|
||||
tr->mod = NULL;
|
||||
}
|
||||
|
||||
static int is_ftrace_location(void *ip)
|
||||
{
|
||||
long addr;
|
||||
@ -108,6 +129,9 @@ static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr)
|
||||
ret = unregister_ftrace_direct((long)ip, (long)old_addr);
|
||||
else
|
||||
ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, NULL);
|
||||
|
||||
if (!ret)
|
||||
bpf_trampoline_module_put(tr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -134,10 +158,16 @@ static int register_fentry(struct bpf_trampoline *tr, void *new_addr)
|
||||
return ret;
|
||||
tr->func.ftrace_managed = ret;
|
||||
|
||||
if (bpf_trampoline_module_get(tr))
|
||||
return -ENOENT;
|
||||
|
||||
if (tr->func.ftrace_managed)
|
||||
ret = register_ftrace_direct((long)ip, (long)new_addr);
|
||||
else
|
||||
ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, NULL, new_addr);
|
||||
|
||||
if (ret)
|
||||
bpf_trampoline_module_put(tr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -12158,6 +12158,11 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env)
|
||||
u32 btf_id, member_idx;
|
||||
const char *mname;
|
||||
|
||||
if (!prog->gpl_compatible) {
|
||||
verbose(env, "struct ops programs must have a GPL compatible license\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
btf_id = prog->aux->attach_btf_id;
|
||||
st_ops = bpf_struct_ops_find(btf_id);
|
||||
if (!st_ops) {
|
||||
|
@ -227,7 +227,7 @@ static int ringbuf_process_ring(struct ring* r)
|
||||
if ((len & BPF_RINGBUF_DISCARD_BIT) == 0) {
|
||||
sample = (void *)len_ptr + BPF_RINGBUF_HDR_SZ;
|
||||
err = r->sample_cb(r->ctx, sample, len);
|
||||
if (err) {
|
||||
if (err < 0) {
|
||||
/* update consumer pos and bail out */
|
||||
smp_store_release(r->consumer_pos,
|
||||
cons_pos);
|
||||
|
@ -59,6 +59,8 @@ struct xsk_umem {
|
||||
int fd;
|
||||
int refcount;
|
||||
struct list_head ctx_list;
|
||||
bool rx_ring_setup_done;
|
||||
bool tx_ring_setup_done;
|
||||
};
|
||||
|
||||
struct xsk_ctx {
|
||||
@ -743,26 +745,30 @@ static struct xsk_ctx *xsk_get_ctx(struct xsk_umem *umem, int ifindex,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void xsk_put_ctx(struct xsk_ctx *ctx)
|
||||
static void xsk_put_ctx(struct xsk_ctx *ctx, bool unmap)
|
||||
{
|
||||
struct xsk_umem *umem = ctx->umem;
|
||||
struct xdp_mmap_offsets off;
|
||||
int err;
|
||||
|
||||
if (--ctx->refcount == 0) {
|
||||
err = xsk_get_mmap_offsets(umem->fd, &off);
|
||||
if (!err) {
|
||||
munmap(ctx->fill->ring - off.fr.desc,
|
||||
off.fr.desc + umem->config.fill_size *
|
||||
sizeof(__u64));
|
||||
munmap(ctx->comp->ring - off.cr.desc,
|
||||
off.cr.desc + umem->config.comp_size *
|
||||
sizeof(__u64));
|
||||
}
|
||||
if (--ctx->refcount)
|
||||
return;
|
||||
|
||||
list_del(&ctx->list);
|
||||
free(ctx);
|
||||
}
|
||||
if (!unmap)
|
||||
goto out_free;
|
||||
|
||||
err = xsk_get_mmap_offsets(umem->fd, &off);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
munmap(ctx->fill->ring - off.fr.desc, off.fr.desc + umem->config.fill_size *
|
||||
sizeof(__u64));
|
||||
munmap(ctx->comp->ring - off.cr.desc, off.cr.desc + umem->config.comp_size *
|
||||
sizeof(__u64));
|
||||
|
||||
out_free:
|
||||
list_del(&ctx->list);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static struct xsk_ctx *xsk_create_ctx(struct xsk_socket *xsk,
|
||||
@ -797,8 +803,6 @@ static struct xsk_ctx *xsk_create_ctx(struct xsk_socket *xsk,
|
||||
memcpy(ctx->ifname, ifname, IFNAMSIZ - 1);
|
||||
ctx->ifname[IFNAMSIZ - 1] = '\0';
|
||||
|
||||
umem->fill_save = NULL;
|
||||
umem->comp_save = NULL;
|
||||
ctx->fill = fill;
|
||||
ctx->comp = comp;
|
||||
list_add(&ctx->list, &umem->ctx_list);
|
||||
@ -854,6 +858,8 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
|
||||
struct xsk_socket *xsk;
|
||||
struct xsk_ctx *ctx;
|
||||
int err, ifindex;
|
||||
bool unmap = umem->fill_save != fill;
|
||||
bool rx_setup_done = false, tx_setup_done = false;
|
||||
|
||||
if (!umem || !xsk_ptr || !(rx || tx))
|
||||
return -EFAULT;
|
||||
@ -881,6 +887,8 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
|
||||
}
|
||||
} else {
|
||||
xsk->fd = umem->fd;
|
||||
rx_setup_done = umem->rx_ring_setup_done;
|
||||
tx_setup_done = umem->tx_ring_setup_done;
|
||||
}
|
||||
|
||||
ctx = xsk_get_ctx(umem, ifindex, queue_id);
|
||||
@ -899,7 +907,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
|
||||
}
|
||||
xsk->ctx = ctx;
|
||||
|
||||
if (rx) {
|
||||
if (rx && !rx_setup_done) {
|
||||
err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING,
|
||||
&xsk->config.rx_size,
|
||||
sizeof(xsk->config.rx_size));
|
||||
@ -907,8 +915,10 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
|
||||
err = -errno;
|
||||
goto out_put_ctx;
|
||||
}
|
||||
if (xsk->fd == umem->fd)
|
||||
umem->rx_ring_setup_done = true;
|
||||
}
|
||||
if (tx) {
|
||||
if (tx && !tx_setup_done) {
|
||||
err = setsockopt(xsk->fd, SOL_XDP, XDP_TX_RING,
|
||||
&xsk->config.tx_size,
|
||||
sizeof(xsk->config.tx_size));
|
||||
@ -916,6 +926,8 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
|
||||
err = -errno;
|
||||
goto out_put_ctx;
|
||||
}
|
||||
if (xsk->fd == umem->fd)
|
||||
umem->rx_ring_setup_done = true;
|
||||
}
|
||||
|
||||
err = xsk_get_mmap_offsets(xsk->fd, &off);
|
||||
@ -994,6 +1006,8 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
|
||||
}
|
||||
|
||||
*xsk_ptr = xsk;
|
||||
umem->fill_save = NULL;
|
||||
umem->comp_save = NULL;
|
||||
return 0;
|
||||
|
||||
out_mmap_tx:
|
||||
@ -1005,7 +1019,7 @@ out_mmap_rx:
|
||||
munmap(rx_map, off.rx.desc +
|
||||
xsk->config.rx_size * sizeof(struct xdp_desc));
|
||||
out_put_ctx:
|
||||
xsk_put_ctx(ctx);
|
||||
xsk_put_ctx(ctx, unmap);
|
||||
out_socket:
|
||||
if (--umem->refcount)
|
||||
close(xsk->fd);
|
||||
@ -1019,6 +1033,9 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname,
|
||||
struct xsk_ring_cons *rx, struct xsk_ring_prod *tx,
|
||||
const struct xsk_socket_config *usr_config)
|
||||
{
|
||||
if (!umem)
|
||||
return -EFAULT;
|
||||
|
||||
return xsk_socket__create_shared(xsk_ptr, ifname, queue_id, umem,
|
||||
rx, tx, umem->fill_save,
|
||||
umem->comp_save, usr_config);
|
||||
@ -1068,7 +1085,7 @@ void xsk_socket__delete(struct xsk_socket *xsk)
|
||||
}
|
||||
}
|
||||
|
||||
xsk_put_ctx(ctx);
|
||||
xsk_put_ctx(ctx, true);
|
||||
|
||||
umem->refcount--;
|
||||
/* Do not close an fd that also has an associated umem connected
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <test_progs.h>
|
||||
#include "bpf_dctcp.skel.h"
|
||||
#include "bpf_cubic.skel.h"
|
||||
#include "bpf_tcp_nogpl.skel.h"
|
||||
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
@ -227,10 +228,53 @@ static void test_dctcp(void)
|
||||
bpf_dctcp__destroy(dctcp_skel);
|
||||
}
|
||||
|
||||
static char *err_str;
|
||||
static bool found;
|
||||
|
||||
static int libbpf_debug_print(enum libbpf_print_level level,
|
||||
const char *format, va_list args)
|
||||
{
|
||||
char *log_buf;
|
||||
|
||||
if (level != LIBBPF_WARN ||
|
||||
strcmp(format, "libbpf: \n%s\n")) {
|
||||
vprintf(format, args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_buf = va_arg(args, char *);
|
||||
if (!log_buf)
|
||||
goto out;
|
||||
if (err_str && strstr(log_buf, err_str) != NULL)
|
||||
found = true;
|
||||
out:
|
||||
printf(format, log_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_invalid_license(void)
|
||||
{
|
||||
libbpf_print_fn_t old_print_fn;
|
||||
struct bpf_tcp_nogpl *skel;
|
||||
|
||||
err_str = "struct ops programs must have a GPL compatible license";
|
||||
found = false;
|
||||
old_print_fn = libbpf_set_print(libbpf_debug_print);
|
||||
|
||||
skel = bpf_tcp_nogpl__open_and_load();
|
||||
ASSERT_NULL(skel, "bpf_tcp_nogpl");
|
||||
ASSERT_EQ(found, true, "expected_err_msg");
|
||||
|
||||
bpf_tcp_nogpl__destroy(skel);
|
||||
libbpf_set_print(old_print_fn);
|
||||
}
|
||||
|
||||
void test_bpf_tcp_ca(void)
|
||||
{
|
||||
if (test__start_subtest("dctcp"))
|
||||
test_dctcp();
|
||||
if (test__start_subtest("cubic"))
|
||||
test_cubic();
|
||||
if (test__start_subtest("invalid_license"))
|
||||
test_invalid_license();
|
||||
}
|
||||
|
19
tools/testing/selftests/bpf/progs/bpf_tcp_nogpl.c
Normal file
19
tools/testing/selftests/bpf/progs/bpf_tcp_nogpl.c
Normal file
@ -0,0 +1,19 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/types.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include "bpf_tcp_helpers.h"
|
||||
|
||||
char _license[] SEC("license") = "X";
|
||||
|
||||
void BPF_STRUCT_OPS(nogpltcp_init, struct sock *sk)
|
||||
{
|
||||
}
|
||||
|
||||
SEC(".struct_ops")
|
||||
struct tcp_congestion_ops bpf_nogpltcp = {
|
||||
.init = (void *)nogpltcp_init,
|
||||
.name = "bpf_nogpltcp",
|
||||
};
|
Loading…
Reference in New Issue
Block a user