Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
davem330 committed Apr 2, 2021
2 parents 9256ce3 + 6dcc4e3 commit 29684d8
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 26 deletions.
2 changes: 2 additions & 0 deletions include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion kernel/bpf/disasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
Expand Down
4 changes: 2 additions & 2 deletions kernel/bpf/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
12 changes: 10 additions & 2 deletions kernel/bpf/stackmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
30 changes: 30 additions & 0 deletions kernel/bpf/trampoline.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -87,6 +88,26 @@ static struct bpf_trampoline *bpf_trampoline_lookup(u64 key)
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;
Expand All @@ -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;
}

Expand All @@ -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;
}

Expand Down
5 changes: 5 additions & 0 deletions kernel/bpf/verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion tools/lib/bpf/ringbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
57 changes: 37 additions & 20 deletions tools/lib/bpf/xsk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -899,23 +907,27 @@ 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));
if (err) {
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));
if (err) {
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);
Expand Down Expand Up @@ -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:
Expand All @@ -1005,7 +1019,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
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);
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down
44 changes: 44 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down Expand Up @@ -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 changes: 19 additions & 0 deletions tools/testing/selftests/bpf/progs/bpf_tcp_nogpl.c
Original file line number Diff line number Diff line change
@@ -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",
};

0 comments on commit 29684d8

Please sign in to comment.