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 2019-01-31

The following pull-request contains BPF updates for your *net* tree.

The main changes are:

1) disable preemption in sender side of socket filters, from Alexei.

2) fix two potential deadlocks in syscall bpf lookup and prog_register,
   from Martin and Alexei.

3) fix BTF to allow typedef on func_proto, from Yonghong.

4) two bpftool fixes, from Jiri and Paolo.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 1, 2019
2 parents 9b1f19d + f01c280 commit e7b8164
Show file tree
Hide file tree
Showing 16 changed files with 127 additions and 67 deletions.
5 changes: 5 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -2848,6 +2848,9 @@ F: include/uapi/linux/if_bonding.h
BPF (Safe dynamic programs and tools)
M: Alexei Starovoitov <ast@kernel.org>
M: Daniel Borkmann <daniel@iogearbox.net>
R: Martin KaFai Lau <kafai@fb.com>
R: Song Liu <songliubraving@fb.com>
R: Yonghong Song <yhs@fb.com>
L: netdev@vger.kernel.org
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
Expand All @@ -2873,6 +2876,8 @@ F: samples/bpf/
F: tools/bpf/
F: tools/lib/bpf/
F: tools/testing/selftests/bpf/
K: bpf
N: bpf

BPF JIT for ARM
M: Shubham Bansal <illusionist.neo@gmail.com>
Expand Down
21 changes: 18 additions & 3 deletions include/linux/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,8 @@ static inline u8 *bpf_skb_cb(struct sk_buff *skb)
return qdisc_skb_cb(skb)->data;
}

static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
struct sk_buff *skb)
static inline u32 __bpf_prog_run_save_cb(const struct bpf_prog *prog,
struct sk_buff *skb)
{
u8 *cb_data = bpf_skb_cb(skb);
u8 cb_saved[BPF_SKB_CB_LEN];
Expand All @@ -611,15 +611,30 @@ static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
return res;
}

static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
struct sk_buff *skb)
{
u32 res;

preempt_disable();
res = __bpf_prog_run_save_cb(prog, skb);
preempt_enable();
return res;
}

static inline u32 bpf_prog_run_clear_cb(const struct bpf_prog *prog,
struct sk_buff *skb)
{
u8 *cb_data = bpf_skb_cb(skb);
u32 res;

if (unlikely(prog->cb_access))
memset(cb_data, 0, BPF_SKB_CB_LEN);

return BPF_PROG_RUN(prog, skb);
preempt_disable();
res = BPF_PROG_RUN(prog, skb);
preempt_enable();
return res;
}

static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog,
Expand Down
3 changes: 2 additions & 1 deletion kernel/bpf/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1459,7 +1459,8 @@ static int btf_modifier_resolve(struct btf_verifier_env *env,

/* "typedef void new_void", "const void"...etc */
if (!btf_type_is_void(next_type) &&
!btf_type_is_fwd(next_type)) {
!btf_type_is_fwd(next_type) &&
!btf_type_is_func_proto(next_type)) {
btf_verifier_log_type(env, v->t, "Invalid type_id");
return -EINVAL;
}
Expand Down
2 changes: 1 addition & 1 deletion kernel/bpf/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ int __cgroup_bpf_run_filter_skb(struct sock *sk,
bpf_compute_and_save_data_end(skb, &saved_data_end);

ret = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], skb,
bpf_prog_run_save_cb);
__bpf_prog_run_save_cb);
bpf_restore_data_end(skb, saved_data_end);
__skb_pull(skb, offset);
skb->sk = save_sk;
Expand Down
4 changes: 2 additions & 2 deletions kernel/bpf/hashtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
}

if (htab_is_prealloc(htab)) {
pcpu_freelist_push(&htab->freelist, &l->fnode);
__pcpu_freelist_push(&htab->freelist, &l->fnode);
} else {
atomic_dec(&htab->count);
l->htab = htab;
Expand Down Expand Up @@ -748,7 +748,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
} else {
struct pcpu_freelist_node *l;

l = pcpu_freelist_pop(&htab->freelist);
l = __pcpu_freelist_pop(&htab->freelist);
if (!l)
return ERR_PTR(-E2BIG);
l_new = container_of(l, struct htab_elem, fnode);
Expand Down
41 changes: 29 additions & 12 deletions kernel/bpf/percpu_freelist.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,31 @@ void pcpu_freelist_destroy(struct pcpu_freelist *s)
free_percpu(s->freelist);
}

static inline void __pcpu_freelist_push(struct pcpu_freelist_head *head,
struct pcpu_freelist_node *node)
static inline void ___pcpu_freelist_push(struct pcpu_freelist_head *head,
struct pcpu_freelist_node *node)
{
raw_spin_lock(&head->lock);
node->next = head->first;
head->first = node;
raw_spin_unlock(&head->lock);
}

void pcpu_freelist_push(struct pcpu_freelist *s,
void __pcpu_freelist_push(struct pcpu_freelist *s,
struct pcpu_freelist_node *node)
{
struct pcpu_freelist_head *head = this_cpu_ptr(s->freelist);

__pcpu_freelist_push(head, node);
___pcpu_freelist_push(head, node);
}

void pcpu_freelist_push(struct pcpu_freelist *s,
struct pcpu_freelist_node *node)
{
unsigned long flags;

local_irq_save(flags);
__pcpu_freelist_push(s, node);
local_irq_restore(flags);
}

void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
Expand All @@ -63,7 +73,7 @@ void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
for_each_possible_cpu(cpu) {
again:
head = per_cpu_ptr(s->freelist, cpu);
__pcpu_freelist_push(head, buf);
___pcpu_freelist_push(head, buf);
i++;
buf += elem_size;
if (i == nr_elems)
Expand All @@ -74,31 +84,38 @@ void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
local_irq_restore(flags);
}

struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *s)
{
struct pcpu_freelist_head *head;
struct pcpu_freelist_node *node;
unsigned long flags;
int orig_cpu, cpu;

local_irq_save(flags);
orig_cpu = cpu = raw_smp_processor_id();
while (1) {
head = per_cpu_ptr(s->freelist, cpu);
raw_spin_lock(&head->lock);
node = head->first;
if (node) {
head->first = node->next;
raw_spin_unlock_irqrestore(&head->lock, flags);
raw_spin_unlock(&head->lock);
return node;
}
raw_spin_unlock(&head->lock);
cpu = cpumask_next(cpu, cpu_possible_mask);
if (cpu >= nr_cpu_ids)
cpu = 0;
if (cpu == orig_cpu) {
local_irq_restore(flags);
if (cpu == orig_cpu)
return NULL;
}
}
}

struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
{
struct pcpu_freelist_node *ret;
unsigned long flags;

local_irq_save(flags);
ret = __pcpu_freelist_pop(s);
local_irq_restore(flags);
return ret;
}
4 changes: 4 additions & 0 deletions kernel/bpf/percpu_freelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ struct pcpu_freelist_node {
struct pcpu_freelist_node *next;
};

/* pcpu_freelist_* do spin_lock_irqsave. */
void pcpu_freelist_push(struct pcpu_freelist *, struct pcpu_freelist_node *);
struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *);
/* __pcpu_freelist_* do spin_lock only. caller must disable irqs. */
void __pcpu_freelist_push(struct pcpu_freelist *, struct pcpu_freelist_node *);
struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *);
void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
u32 nr_elems);
int pcpu_freelist_init(struct pcpu_freelist *);
Expand Down
12 changes: 10 additions & 2 deletions kernel/bpf/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,13 @@ static int map_lookup_elem(union bpf_attr *attr)

if (bpf_map_is_dev_bound(map)) {
err = bpf_map_offload_lookup_elem(map, key, value);
} else if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
goto done;
}

preempt_disable();
this_cpu_inc(bpf_prog_active);
if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
err = bpf_percpu_hash_copy(map, key, value);
} else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
err = bpf_percpu_array_copy(map, key, value);
Expand Down Expand Up @@ -744,7 +749,10 @@ static int map_lookup_elem(union bpf_attr *attr)
}
rcu_read_unlock();
}
this_cpu_dec(bpf_prog_active);
preempt_enable();

done:
if (err)
goto free_value;

Expand Down
14 changes: 2 additions & 12 deletions kernel/trace/bpf_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1204,22 +1204,12 @@ static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *

int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
{
int err;

mutex_lock(&bpf_event_mutex);
err = __bpf_probe_register(btp, prog);
mutex_unlock(&bpf_event_mutex);
return err;
return __bpf_probe_register(btp, prog);
}

int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
{
int err;

mutex_lock(&bpf_event_mutex);
err = tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog);
mutex_unlock(&bpf_event_mutex);
return err;
return tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog);
}

int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
Expand Down
2 changes: 2 additions & 0 deletions net/core/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -4112,10 +4112,12 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
/* Only some socketops are supported */
switch (optname) {
case SO_RCVBUF:
val = min_t(u32, val, sysctl_rmem_max);
sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF);
break;
case SO_SNDBUF:
val = min_t(u32, val, sysctl_wmem_max);
sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF);
break;
Expand Down
3 changes: 1 addition & 2 deletions net/core/skmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,7 @@ static void sk_psock_destroy_deferred(struct work_struct *gc)
struct sk_psock *psock = container_of(gc, struct sk_psock, gc);

/* No sk_callback_lock since already detached. */
if (psock->parser.enabled)
strp_done(&psock->parser.strp);
strp_done(&psock->parser.strp);

cancel_work_sync(&psock->work);

Expand Down
6 changes: 1 addition & 5 deletions tools/bpf/bpftool/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,8 @@ char *get_fdinfo(int fd, const char *key)
snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd);

fdi = fopen(path, "r");
if (!fdi) {
p_err("can't open fdinfo: %s", strerror(errno));
if (!fdi)
return NULL;
}

while ((n = getline(&line, &line_n, fdi)) > 0) {
char *value;
Expand All @@ -313,7 +311,6 @@ char *get_fdinfo(int fd, const char *key)

value = strchr(line, '\t');
if (!value || !value[1]) {
p_err("malformed fdinfo!?");
free(line);
return NULL;
}
Expand All @@ -326,7 +323,6 @@ char *get_fdinfo(int fd, const char *key)
return line;
}

p_err("key '%s' not found in fdinfo", key);
free(line);
fclose(fdi);
return NULL;
Expand Down
33 changes: 24 additions & 9 deletions tools/bpf/bpftool/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,20 @@ static char **parse_bytes(char **argv, const char *name, unsigned char *val,
return argv + i;
}

/* on per cpu maps we must copy the provided value on all value instances */
static void fill_per_cpu_value(struct bpf_map_info *info, void *value)
{
unsigned int i, n, step;

if (!map_is_per_cpu(info->type))
return;

n = get_possible_cpus();
step = round_up(info->value_size, 8);
for (i = 1; i < n; i++)
memcpy(value + i * step, value, info->value_size);
}

static int parse_elem(char **argv, struct bpf_map_info *info,
void *key, void *value, __u32 key_size, __u32 value_size,
__u32 *flags, __u32 **value_fd)
Expand Down Expand Up @@ -426,6 +440,8 @@ static int parse_elem(char **argv, struct bpf_map_info *info,
argv = parse_bytes(argv, "value", value, value_size);
if (!argv)
return -1;

fill_per_cpu_value(info, value);
}

return parse_elem(argv, info, key, NULL, key_size, value_size,
Expand Down Expand Up @@ -497,10 +513,9 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
jsonw_uint_field(json_wtr, "owner_prog_type",
prog_type);
}
if (atoi(owner_jited))
jsonw_bool_field(json_wtr, "owner_jited", true);
else
jsonw_bool_field(json_wtr, "owner_jited", false);
if (owner_jited)
jsonw_bool_field(json_wtr, "owner_jited",
!!atoi(owner_jited));

free(owner_prog_type);
free(owner_jited);
Expand Down Expand Up @@ -553,7 +568,8 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
char *owner_jited = get_fdinfo(fd, "owner_jited");

printf("\n\t");
if (owner_prog_type || owner_jited)
printf("\n\t");
if (owner_prog_type) {
unsigned int prog_type = atoi(owner_prog_type);

Expand All @@ -563,10 +579,9 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
else
printf("owner_prog_type %d ", prog_type);
}
if (atoi(owner_jited))
printf("owner jited");
else
printf("owner not jited");
if (owner_jited)
printf("owner%s jited",
atoi(owner_jited) ? "" : " not");

free(owner_prog_type);
free(owner_jited);
Expand Down
5 changes: 3 additions & 2 deletions tools/bpf/bpftool/prog.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,14 @@ static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)

static int prog_fd_by_tag(unsigned char *tag)
{
struct bpf_prog_info info = {};
__u32 len = sizeof(info);
unsigned int id = 0;
int err;
int fd;

while (true) {
struct bpf_prog_info info = {};
__u32 len = sizeof(info);

err = bpf_prog_get_next_id(id, &id);
if (err) {
p_err("%s", strerror(errno));
Expand Down
Loading

0 comments on commit e7b8164

Please sign in to comment.