Skip to content

Commit 1a51a47

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2019-10-27 The following pull-request contains BPF updates for your *net* tree. We've added 7 non-merge commits during the last 11 day(s) which contain a total of 7 files changed, 66 insertions(+), 16 deletions(-). The main changes are: 1) Fix two use-after-free bugs in relation to RCU in jited symbol exposure to kallsyms, from Daniel Borkmann. 2) Fix NULL pointer dereference in AF_XDP rx-only sockets, from Magnus Karlsson. 3) Fix hang in netdev unregister for hash based devmap as well as another overflow bug on 32 bit archs in memlock cost calculation, from Toke Høiland-Jørgensen. 4) Fix wrong memory access in LWT BPF programs on reroute due to invalid dst. Also fix BPF selftests to use more compatible nc options, from Jiri Benc. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 45f3380 + 2afd23f commit 1a51a47

File tree

7 files changed

+66
-16
lines changed

7 files changed

+66
-16
lines changed

include/linux/filter.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1099,7 +1099,6 @@ static inline void bpf_get_prog_name(const struct bpf_prog *prog, char *sym)
10991099

11001100
#endif /* CONFIG_BPF_JIT */
11011101

1102-
void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp);
11031102
void bpf_prog_kallsyms_del_all(struct bpf_prog *fp);
11041103

11051104
#define BPF_ANC BIT(15)

kernel/bpf/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt)
502502
return WARN_ON_ONCE(bpf_adj_branches(prog, off, off + cnt, off, false));
503503
}
504504

505-
void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp)
505+
static void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp)
506506
{
507507
int i;
508508

kernel/bpf/devmap.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr)
128128

129129
if (!dtab->n_buckets) /* Overflow check */
130130
return -EINVAL;
131-
cost += sizeof(struct hlist_head) * dtab->n_buckets;
131+
cost += (u64) sizeof(struct hlist_head) * dtab->n_buckets;
132132
}
133133

134134
/* if map size is larger than memlock limit, reject it */
@@ -719,6 +719,32 @@ const struct bpf_map_ops dev_map_hash_ops = {
719719
.map_check_btf = map_check_no_btf,
720720
};
721721

722+
static void dev_map_hash_remove_netdev(struct bpf_dtab *dtab,
723+
struct net_device *netdev)
724+
{
725+
unsigned long flags;
726+
u32 i;
727+
728+
spin_lock_irqsave(&dtab->index_lock, flags);
729+
for (i = 0; i < dtab->n_buckets; i++) {
730+
struct bpf_dtab_netdev *dev;
731+
struct hlist_head *head;
732+
struct hlist_node *next;
733+
734+
head = dev_map_index_hash(dtab, i);
735+
736+
hlist_for_each_entry_safe(dev, next, head, index_hlist) {
737+
if (netdev != dev->dev)
738+
continue;
739+
740+
dtab->items--;
741+
hlist_del_rcu(&dev->index_hlist);
742+
call_rcu(&dev->rcu, __dev_map_entry_free);
743+
}
744+
}
745+
spin_unlock_irqrestore(&dtab->index_lock, flags);
746+
}
747+
722748
static int dev_map_notification(struct notifier_block *notifier,
723749
ulong event, void *ptr)
724750
{
@@ -735,6 +761,11 @@ static int dev_map_notification(struct notifier_block *notifier,
735761
*/
736762
rcu_read_lock();
737763
list_for_each_entry_rcu(dtab, &dev_map_list, list) {
764+
if (dtab->map.map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
765+
dev_map_hash_remove_netdev(dtab, netdev);
766+
continue;
767+
}
768+
738769
for (i = 0; i < dtab->map.max_entries; i++) {
739770
struct bpf_dtab_netdev *dev, *odev;
740771

kernel/bpf/syscall.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,24 +1326,32 @@ static void __bpf_prog_put_rcu(struct rcu_head *rcu)
13261326
{
13271327
struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
13281328

1329+
kvfree(aux->func_info);
13291330
free_used_maps(aux);
13301331
bpf_prog_uncharge_memlock(aux->prog);
13311332
security_bpf_prog_free(aux);
13321333
bpf_prog_free(aux->prog);
13331334
}
13341335

1336+
static void __bpf_prog_put_noref(struct bpf_prog *prog, bool deferred)
1337+
{
1338+
bpf_prog_kallsyms_del_all(prog);
1339+
btf_put(prog->aux->btf);
1340+
bpf_prog_free_linfo(prog);
1341+
1342+
if (deferred)
1343+
call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
1344+
else
1345+
__bpf_prog_put_rcu(&prog->aux->rcu);
1346+
}
1347+
13351348
static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
13361349
{
13371350
if (atomic_dec_and_test(&prog->aux->refcnt)) {
13381351
perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
13391352
/* bpf_prog_free_id() must be called first */
13401353
bpf_prog_free_id(prog, do_idr_lock);
1341-
bpf_prog_kallsyms_del_all(prog);
1342-
btf_put(prog->aux->btf);
1343-
kvfree(prog->aux->func_info);
1344-
bpf_prog_free_linfo(prog);
1345-
1346-
call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
1354+
__bpf_prog_put_noref(prog, true);
13471355
}
13481356
}
13491357

@@ -1741,11 +1749,12 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
17411749
return err;
17421750

17431751
free_used_maps:
1744-
bpf_prog_free_linfo(prog);
1745-
kvfree(prog->aux->func_info);
1746-
btf_put(prog->aux->btf);
1747-
bpf_prog_kallsyms_del_subprogs(prog);
1748-
free_used_maps(prog->aux);
1752+
/* In case we have subprogs, we need to wait for a grace
1753+
* period before we can tear down JIT memory since symbols
1754+
* are already exposed under kallsyms.
1755+
*/
1756+
__bpf_prog_put_noref(prog, prog->aux->func_cnt);
1757+
return err;
17491758
free_prog:
17501759
bpf_prog_uncharge_memlock(prog);
17511760
free_prog_sec:

net/core/lwt_bpf.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,16 @@ static int bpf_lwt_input_reroute(struct sk_buff *skb)
8888
int err = -EINVAL;
8989

9090
if (skb->protocol == htons(ETH_P_IP)) {
91+
struct net_device *dev = skb_dst(skb)->dev;
9192
struct iphdr *iph = ip_hdr(skb);
9293

94+
dev_hold(dev);
95+
skb_dst_drop(skb);
9396
err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
94-
iph->tos, skb_dst(skb)->dev);
97+
iph->tos, dev);
98+
dev_put(dev);
9599
} else if (skb->protocol == htons(ETH_P_IPV6)) {
100+
skb_dst_drop(skb);
96101
err = ipv6_stub->ipv6_route_input(skb);
97102
} else {
98103
err = -EAFNOSUPPORT;

net/xdp/xdp_umem.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ void xdp_add_sk_umem(struct xdp_umem *umem, struct xdp_sock *xs)
2727
{
2828
unsigned long flags;
2929

30+
if (!xs->tx)
31+
return;
32+
3033
spin_lock_irqsave(&umem->xsk_list_lock, flags);
3134
list_add_rcu(&xs->list, &umem->xsk_list);
3235
spin_unlock_irqrestore(&umem->xsk_list_lock, flags);
@@ -36,6 +39,9 @@ void xdp_del_sk_umem(struct xdp_umem *umem, struct xdp_sock *xs)
3639
{
3740
unsigned long flags;
3841

42+
if (!xs->tx)
43+
return;
44+
3945
spin_lock_irqsave(&umem->xsk_list_lock, flags);
4046
list_del_rcu(&xs->list);
4147
spin_unlock_irqrestore(&umem->xsk_list_lock, flags);

tools/testing/selftests/bpf/test_tc_edt.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ ip netns exec ${NS_SRC} tc filter add dev veth_src egress \
5959

6060
# start the listener
6161
ip netns exec ${NS_DST} bash -c \
62-
"nc -4 -l -s ${IP_DST} -p 9000 >/dev/null &"
62+
"nc -4 -l -p 9000 >/dev/null &"
6363
declare -i NC_PID=$!
6464
sleep 1
6565

0 commit comments

Comments
 (0)