aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2018-07-07 18:19:30 -0400
committerAlexei Starovoitov <ast@kernel.org>2018-07-07 18:19:31 -0400
commit4fb126cbcbd6870851f0b3ba503e8ec0e66b9dd5 (patch)
tree9b658d4f6d41e66372940e9ddd47feefee66cda8 /kernel
parent631da8534aeea2e2f8b36a832d065a203f24fa43 (diff)
parent0ea488ff8d23c93da383fcf424825c298b13b1fb (diff)
Merge branch 'sockhash-fixes'
John Fastabend says: ==================== First three patches resolve issues found while testing sockhash and reviewing code. Syzbot also found them about the same time as I was working on fixes. The main issue is in the sockhash path we reduced the scope of sk_callback lock but this meant we could get update and close running in parallel so fix that here. Then testing sk_msg and sk_skb programs together found that skb->dev is not always assigned and some of the helpers were depending on this to lookup max mtu. Fix this by using SKB_MAX_ALLOC when no MTU is available. Finally, Martin spotted that the sockmap code was still using the qdisc skb cb structure. But I was sure we had fixed this long ago. Looks like we missed it in a merge conflict resolution and then by chance data_end offset was the same in both structures so everything sort of continued to work even though it could break at any moment if the structs ever change. So redo the conversion and this time also convert the helpers. v2: fix '0 files changed' issue in patches ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/sockmap.c24
-rw-r--r--kernel/bpf/syscall.c4
2 files changed, 24 insertions, 4 deletions
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index 00fb2e328d1b..98fb7938beea 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -312,10 +312,12 @@ static void bpf_tcp_close(struct sock *sk, long timeout)
312 struct smap_psock *psock; 312 struct smap_psock *psock;
313 struct sock *osk; 313 struct sock *osk;
314 314
315 lock_sock(sk);
315 rcu_read_lock(); 316 rcu_read_lock();
316 psock = smap_psock_sk(sk); 317 psock = smap_psock_sk(sk);
317 if (unlikely(!psock)) { 318 if (unlikely(!psock)) {
318 rcu_read_unlock(); 319 rcu_read_unlock();
320 release_sock(sk);
319 return sk->sk_prot->close(sk, timeout); 321 return sk->sk_prot->close(sk, timeout);
320 } 322 }
321 323
@@ -371,6 +373,7 @@ static void bpf_tcp_close(struct sock *sk, long timeout)
371 e = psock_map_pop(sk, psock); 373 e = psock_map_pop(sk, psock);
372 } 374 }
373 rcu_read_unlock(); 375 rcu_read_unlock();
376 release_sock(sk);
374 close_fun(sk, timeout); 377 close_fun(sk, timeout);
375} 378}
376 379
@@ -568,7 +571,8 @@ static int free_sg(struct sock *sk, int start, struct sk_msg_buff *md)
568 while (sg[i].length) { 571 while (sg[i].length) {
569 free += sg[i].length; 572 free += sg[i].length;
570 sk_mem_uncharge(sk, sg[i].length); 573 sk_mem_uncharge(sk, sg[i].length);
571 put_page(sg_page(&sg[i])); 574 if (!md->skb)
575 put_page(sg_page(&sg[i]));
572 sg[i].length = 0; 576 sg[i].length = 0;
573 sg[i].page_link = 0; 577 sg[i].page_link = 0;
574 sg[i].offset = 0; 578 sg[i].offset = 0;
@@ -577,6 +581,8 @@ static int free_sg(struct sock *sk, int start, struct sk_msg_buff *md)
577 if (i == MAX_SKB_FRAGS) 581 if (i == MAX_SKB_FRAGS)
578 i = 0; 582 i = 0;
579 } 583 }
584 if (md->skb)
585 consume_skb(md->skb);
580 586
581 return free; 587 return free;
582} 588}
@@ -1230,7 +1236,7 @@ static int smap_verdict_func(struct smap_psock *psock, struct sk_buff *skb)
1230 */ 1236 */
1231 TCP_SKB_CB(skb)->bpf.sk_redir = NULL; 1237 TCP_SKB_CB(skb)->bpf.sk_redir = NULL;
1232 skb->sk = psock->sock; 1238 skb->sk = psock->sock;
1233 bpf_compute_data_pointers(skb); 1239 bpf_compute_data_end_sk_skb(skb);
1234 preempt_disable(); 1240 preempt_disable();
1235 rc = (*prog->bpf_func)(skb, prog->insnsi); 1241 rc = (*prog->bpf_func)(skb, prog->insnsi);
1236 preempt_enable(); 1242 preempt_enable();
@@ -1485,7 +1491,7 @@ static int smap_parse_func_strparser(struct strparser *strp,
1485 * any socket yet. 1491 * any socket yet.
1486 */ 1492 */
1487 skb->sk = psock->sock; 1493 skb->sk = psock->sock;
1488 bpf_compute_data_pointers(skb); 1494 bpf_compute_data_end_sk_skb(skb);
1489 rc = (*prog->bpf_func)(skb, prog->insnsi); 1495 rc = (*prog->bpf_func)(skb, prog->insnsi);
1490 skb->sk = NULL; 1496 skb->sk = NULL;
1491 rcu_read_unlock(); 1497 rcu_read_unlock();
@@ -2069,7 +2075,13 @@ static int sock_map_update_elem(struct bpf_map *map,
2069 return -EOPNOTSUPP; 2075 return -EOPNOTSUPP;
2070 } 2076 }
2071 2077
2078 lock_sock(skops.sk);
2079 preempt_disable();
2080 rcu_read_lock();
2072 err = sock_map_ctx_update_elem(&skops, map, key, flags); 2081 err = sock_map_ctx_update_elem(&skops, map, key, flags);
2082 rcu_read_unlock();
2083 preempt_enable();
2084 release_sock(skops.sk);
2073 fput(socket->file); 2085 fput(socket->file);
2074 return err; 2086 return err;
2075} 2087}
@@ -2410,7 +2422,13 @@ static int sock_hash_update_elem(struct bpf_map *map,
2410 return -EINVAL; 2422 return -EINVAL;
2411 } 2423 }
2412 2424
2425 lock_sock(skops.sk);
2426 preempt_disable();
2427 rcu_read_lock();
2413 err = sock_hash_ctx_update_elem(&skops, map, key, flags); 2428 err = sock_hash_ctx_update_elem(&skops, map, key, flags);
2429 rcu_read_unlock();
2430 preempt_enable();
2431 release_sock(skops.sk);
2414 fput(socket->file); 2432 fput(socket->file);
2415 return err; 2433 return err;
2416} 2434}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index d10ecd78105f..a31a1ba0f8ea 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -735,7 +735,9 @@ static int map_update_elem(union bpf_attr *attr)
735 if (bpf_map_is_dev_bound(map)) { 735 if (bpf_map_is_dev_bound(map)) {
736 err = bpf_map_offload_update_elem(map, key, value, attr->flags); 736 err = bpf_map_offload_update_elem(map, key, value, attr->flags);
737 goto out; 737 goto out;
738 } else if (map->map_type == BPF_MAP_TYPE_CPUMAP) { 738 } else if (map->map_type == BPF_MAP_TYPE_CPUMAP ||
739 map->map_type == BPF_MAP_TYPE_SOCKHASH ||
740 map->map_type == BPF_MAP_TYPE_SOCKMAP) {
739 err = map->ops->map_update_elem(map, key, value, attr->flags); 741 err = map->ops->map_update_elem(map, key, value, attr->flags);
740 goto out; 742 goto out;
741 } 743 }