Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
All conflicts seemed rather trivial, with some guidance from Saeed Mameed on the tc_ct.c one. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -690,6 +690,15 @@ void dev_uc_unsync(struct net_device *to, struct net_device *from)
|
||||
if (to->addr_len != from->addr_len)
|
||||
return;
|
||||
|
||||
/* netif_addr_lock_bh() uses lockdep subclass 0, this is okay for two
|
||||
* reasons:
|
||||
* 1) This is always called without any addr_list_lock, so as the
|
||||
* outermost one here, it must be 0.
|
||||
* 2) This is called by some callers after unlinking the upper device,
|
||||
* so the dev->lower_level becomes 1 again.
|
||||
* Therefore, the subclass for 'from' is 0, for 'to' is either 1 or
|
||||
* larger.
|
||||
*/
|
||||
netif_addr_lock_bh(from);
|
||||
netif_addr_lock_nested(to);
|
||||
__hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
|
||||
@@ -911,6 +920,7 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from)
|
||||
if (to->addr_len != from->addr_len)
|
||||
return;
|
||||
|
||||
/* See the above comments inside dev_uc_unsync(). */
|
||||
netif_addr_lock_bh(from);
|
||||
netif_addr_lock_nested(to);
|
||||
__hw_addr_unsync(&to->mc, &from->mc, to->addr_len);
|
||||
|
||||
@@ -5889,12 +5889,16 @@ BPF_CALL_1(bpf_skb_ecn_set_ce, struct sk_buff *, skb)
|
||||
{
|
||||
unsigned int iphdr_len;
|
||||
|
||||
if (skb->protocol == cpu_to_be16(ETH_P_IP))
|
||||
switch (skb_protocol(skb, true)) {
|
||||
case cpu_to_be16(ETH_P_IP):
|
||||
iphdr_len = sizeof(struct iphdr);
|
||||
else if (skb->protocol == cpu_to_be16(ETH_P_IPV6))
|
||||
break;
|
||||
case cpu_to_be16(ETH_P_IPV6):
|
||||
iphdr_len = sizeof(struct ipv6hdr);
|
||||
else
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (skb_headlen(skb) < iphdr_len)
|
||||
return 0;
|
||||
|
||||
@@ -70,10 +70,10 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
|
||||
EXPORT_SYMBOL(skb_flow_dissector_init);
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
int flow_dissector_bpf_prog_attach(struct net *net, struct bpf_prog *prog)
|
||||
int flow_dissector_bpf_prog_attach_check(struct net *net,
|
||||
struct bpf_prog *prog)
|
||||
{
|
||||
enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR;
|
||||
struct bpf_prog *attached;
|
||||
|
||||
if (net == &init_net) {
|
||||
/* BPF flow dissector in the root namespace overrides
|
||||
@@ -86,26 +86,17 @@ int flow_dissector_bpf_prog_attach(struct net *net, struct bpf_prog *prog)
|
||||
for_each_net(ns) {
|
||||
if (ns == &init_net)
|
||||
continue;
|
||||
if (rcu_access_pointer(ns->bpf.progs[type]))
|
||||
if (rcu_access_pointer(ns->bpf.run_array[type]))
|
||||
return -EEXIST;
|
||||
}
|
||||
} else {
|
||||
/* Make sure root flow dissector is not attached
|
||||
* when attaching to the non-root namespace.
|
||||
*/
|
||||
if (rcu_access_pointer(init_net.bpf.progs[type]))
|
||||
if (rcu_access_pointer(init_net.bpf.run_array[type]))
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
attached = rcu_dereference_protected(net->bpf.progs[type],
|
||||
lockdep_is_held(&netns_bpf_mutex));
|
||||
if (attached == prog)
|
||||
/* The same program cannot be attached twice */
|
||||
return -EINVAL;
|
||||
|
||||
rcu_assign_pointer(net->bpf.progs[type], prog);
|
||||
if (attached)
|
||||
bpf_prog_put(attached);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BPF_SYSCALL */
|
||||
@@ -903,7 +894,6 @@ bool __skb_flow_dissect(const struct net *net,
|
||||
struct flow_dissector_key_addrs *key_addrs;
|
||||
struct flow_dissector_key_tags *key_tags;
|
||||
struct flow_dissector_key_vlan *key_vlan;
|
||||
struct bpf_prog *attached = NULL;
|
||||
enum flow_dissect_ret fdret;
|
||||
enum flow_dissector_key_id dissector_vlan = FLOW_DISSECTOR_KEY_MAX;
|
||||
bool mpls_el = false;
|
||||
@@ -960,14 +950,14 @@ bool __skb_flow_dissect(const struct net *net,
|
||||
WARN_ON_ONCE(!net);
|
||||
if (net) {
|
||||
enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR;
|
||||
struct bpf_prog_array *run_array;
|
||||
|
||||
rcu_read_lock();
|
||||
attached = rcu_dereference(init_net.bpf.progs[type]);
|
||||
run_array = rcu_dereference(init_net.bpf.run_array[type]);
|
||||
if (!run_array)
|
||||
run_array = rcu_dereference(net->bpf.run_array[type]);
|
||||
|
||||
if (!attached)
|
||||
attached = rcu_dereference(net->bpf.progs[type]);
|
||||
|
||||
if (attached) {
|
||||
if (run_array) {
|
||||
struct bpf_flow_keys flow_keys;
|
||||
struct bpf_flow_dissector ctx = {
|
||||
.flow_keys = &flow_keys,
|
||||
@@ -975,6 +965,7 @@ bool __skb_flow_dissect(const struct net *net,
|
||||
.data_end = data + hlen,
|
||||
};
|
||||
__be16 n_proto = proto;
|
||||
struct bpf_prog *prog;
|
||||
|
||||
if (skb) {
|
||||
ctx.skb = skb;
|
||||
@@ -985,7 +976,8 @@ bool __skb_flow_dissect(const struct net *net,
|
||||
n_proto = skb->protocol;
|
||||
}
|
||||
|
||||
ret = bpf_flow_dissect(attached, &ctx, n_proto, nhoff,
|
||||
prog = READ_ONCE(run_array->items[0].prog);
|
||||
ret = bpf_flow_dissect(prog, &ctx, n_proto, nhoff,
|
||||
hlen, flags);
|
||||
__skb_flow_bpf_to_target(&flow_keys, flow_dissector,
|
||||
target_container);
|
||||
|
||||
@@ -683,7 +683,7 @@ static struct sk_psock *sk_psock_from_strp(struct strparser *strp)
|
||||
return container_of(parser, struct sk_psock, parser);
|
||||
}
|
||||
|
||||
static void sk_psock_skb_redirect(struct sk_psock *psock, struct sk_buff *skb)
|
||||
static void sk_psock_skb_redirect(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_psock *psock_other;
|
||||
struct sock *sk_other;
|
||||
@@ -715,12 +715,11 @@ static void sk_psock_skb_redirect(struct sk_psock *psock, struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
static void sk_psock_tls_verdict_apply(struct sk_psock *psock,
|
||||
struct sk_buff *skb, int verdict)
|
||||
static void sk_psock_tls_verdict_apply(struct sk_buff *skb, int verdict)
|
||||
{
|
||||
switch (verdict) {
|
||||
case __SK_REDIRECT:
|
||||
sk_psock_skb_redirect(psock, skb);
|
||||
sk_psock_skb_redirect(skb);
|
||||
break;
|
||||
case __SK_PASS:
|
||||
case __SK_DROP:
|
||||
@@ -741,8 +740,8 @@ int sk_psock_tls_strp_read(struct sk_psock *psock, struct sk_buff *skb)
|
||||
ret = sk_psock_bpf_run(psock, prog, skb);
|
||||
ret = sk_psock_map_verd(ret, tcp_skb_bpf_redirect_fetch(skb));
|
||||
}
|
||||
sk_psock_tls_verdict_apply(skb, ret);
|
||||
rcu_read_unlock();
|
||||
sk_psock_tls_verdict_apply(psock, skb, ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sk_psock_tls_strp_read);
|
||||
@@ -770,7 +769,7 @@ static void sk_psock_verdict_apply(struct sk_psock *psock,
|
||||
}
|
||||
goto out_free;
|
||||
case __SK_REDIRECT:
|
||||
sk_psock_skb_redirect(psock, skb);
|
||||
sk_psock_skb_redirect(skb);
|
||||
break;
|
||||
case __SK_DROP:
|
||||
/* fall-through */
|
||||
@@ -782,11 +781,18 @@ out_free:
|
||||
|
||||
static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_psock *psock = sk_psock_from_strp(strp);
|
||||
struct sk_psock *psock;
|
||||
struct bpf_prog *prog;
|
||||
int ret = __SK_DROP;
|
||||
struct sock *sk;
|
||||
|
||||
rcu_read_lock();
|
||||
sk = strp->sk;
|
||||
psock = sk_psock(sk);
|
||||
if (unlikely(!psock)) {
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
prog = READ_ONCE(psock->progs.skb_verdict);
|
||||
if (likely(prog)) {
|
||||
skb_orphan(skb);
|
||||
@@ -794,8 +800,9 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)
|
||||
ret = sk_psock_bpf_run(psock, prog, skb);
|
||||
ret = sk_psock_map_verd(ret, tcp_skb_bpf_redirect_fetch(skb));
|
||||
}
|
||||
rcu_read_unlock();
|
||||
sk_psock_verdict_apply(psock, skb, ret);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int sk_psock_strp_read_done(struct strparser *strp, int err)
|
||||
|
||||
@@ -1917,7 +1917,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
|
||||
/* sk->sk_memcg will be populated at accept() time */
|
||||
newsk->sk_memcg = NULL;
|
||||
|
||||
cgroup_sk_alloc(&newsk->sk_cgrp_data);
|
||||
cgroup_sk_clone(&newsk->sk_cgrp_data);
|
||||
|
||||
rcu_read_lock();
|
||||
filter = rcu_dereference(sk->sk_filter);
|
||||
|
||||
@@ -70,11 +70,49 @@ int sock_map_get_from_fd(const union bpf_attr *attr, struct bpf_prog *prog)
|
||||
struct fd f;
|
||||
int ret;
|
||||
|
||||
if (attr->attach_flags || attr->replace_bpf_fd)
|
||||
return -EINVAL;
|
||||
|
||||
f = fdget(ufd);
|
||||
map = __bpf_map_get(f);
|
||||
if (IS_ERR(map))
|
||||
return PTR_ERR(map);
|
||||
ret = sock_map_prog_update(map, prog, attr->attach_type);
|
||||
ret = sock_map_prog_update(map, prog, NULL, attr->attach_type);
|
||||
fdput(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sock_map_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
|
||||
{
|
||||
u32 ufd = attr->target_fd;
|
||||
struct bpf_prog *prog;
|
||||
struct bpf_map *map;
|
||||
struct fd f;
|
||||
int ret;
|
||||
|
||||
if (attr->attach_flags || attr->replace_bpf_fd)
|
||||
return -EINVAL;
|
||||
|
||||
f = fdget(ufd);
|
||||
map = __bpf_map_get(f);
|
||||
if (IS_ERR(map))
|
||||
return PTR_ERR(map);
|
||||
|
||||
prog = bpf_prog_get(attr->attach_bpf_fd);
|
||||
if (IS_ERR(prog)) {
|
||||
ret = PTR_ERR(prog);
|
||||
goto put_map;
|
||||
}
|
||||
|
||||
if (prog->type != ptype) {
|
||||
ret = -EINVAL;
|
||||
goto put_prog;
|
||||
}
|
||||
|
||||
ret = sock_map_prog_update(map, NULL, prog, attr->attach_type);
|
||||
put_prog:
|
||||
bpf_prog_put(prog);
|
||||
put_map:
|
||||
fdput(f);
|
||||
return ret;
|
||||
}
|
||||
@@ -1209,27 +1247,32 @@ static struct sk_psock_progs *sock_map_progs(struct bpf_map *map)
|
||||
}
|
||||
|
||||
int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog,
|
||||
u32 which)
|
||||
struct bpf_prog *old, u32 which)
|
||||
{
|
||||
struct sk_psock_progs *progs = sock_map_progs(map);
|
||||
struct bpf_prog **pprog;
|
||||
|
||||
if (!progs)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (which) {
|
||||
case BPF_SK_MSG_VERDICT:
|
||||
psock_set_prog(&progs->msg_parser, prog);
|
||||
pprog = &progs->msg_parser;
|
||||
break;
|
||||
case BPF_SK_SKB_STREAM_PARSER:
|
||||
psock_set_prog(&progs->skb_parser, prog);
|
||||
pprog = &progs->skb_parser;
|
||||
break;
|
||||
case BPF_SK_SKB_STREAM_VERDICT:
|
||||
psock_set_prog(&progs->skb_verdict, prog);
|
||||
pprog = &progs->skb_verdict;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (old)
|
||||
return psock_replace_prog(pprog, prog, old);
|
||||
|
||||
psock_set_prog(pprog, prog);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ static int proc_dointvec_minmax_bpf_enable(struct ctl_table *table, int write,
|
||||
ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
|
||||
if (write && !ret) {
|
||||
if (jit_enable < 2 ||
|
||||
(jit_enable == 2 && bpf_dump_raw_ok())) {
|
||||
(jit_enable == 2 && bpf_dump_raw_ok(current_cred()))) {
|
||||
*(int *)table->data = jit_enable;
|
||||
if (jit_enable == 2)
|
||||
pr_warn("bpf_jit_enable = 2 was set! NEVER use this in production, only for JIT debugging!\n");
|
||||
|
||||
Reference in New Issue
Block a user