diff options
Diffstat (limited to 'net/core/sock_map.c')
-rw-r--r-- | net/core/sock_map.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 52d4faeee18b..1330a7442e5b 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c | |||
@@ -247,6 +247,8 @@ static void sock_map_free(struct bpf_map *map) | |||
247 | raw_spin_unlock_bh(&stab->lock); | 247 | raw_spin_unlock_bh(&stab->lock); |
248 | rcu_read_unlock(); | 248 | rcu_read_unlock(); |
249 | 249 | ||
250 | synchronize_rcu(); | ||
251 | |||
250 | bpf_map_area_free(stab->sks); | 252 | bpf_map_area_free(stab->sks); |
251 | kfree(stab); | 253 | kfree(stab); |
252 | } | 254 | } |
@@ -276,16 +278,20 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test, | |||
276 | struct sock **psk) | 278 | struct sock **psk) |
277 | { | 279 | { |
278 | struct sock *sk; | 280 | struct sock *sk; |
281 | int err = 0; | ||
279 | 282 | ||
280 | raw_spin_lock_bh(&stab->lock); | 283 | raw_spin_lock_bh(&stab->lock); |
281 | sk = *psk; | 284 | sk = *psk; |
282 | if (!sk_test || sk_test == sk) | 285 | if (!sk_test || sk_test == sk) |
283 | *psk = NULL; | 286 | sk = xchg(psk, NULL); |
287 | |||
288 | if (likely(sk)) | ||
289 | sock_map_unref(sk, psk); | ||
290 | else | ||
291 | err = -EINVAL; | ||
292 | |||
284 | raw_spin_unlock_bh(&stab->lock); | 293 | raw_spin_unlock_bh(&stab->lock); |
285 | if (unlikely(!sk)) | 294 | return err; |
286 | return -EINVAL; | ||
287 | sock_map_unref(sk, psk); | ||
288 | return 0; | ||
289 | } | 295 | } |
290 | 296 | ||
291 | static void sock_map_delete_from_link(struct bpf_map *map, struct sock *sk, | 297 | static void sock_map_delete_from_link(struct bpf_map *map, struct sock *sk, |
@@ -328,6 +334,7 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx, | |||
328 | struct sock *sk, u64 flags) | 334 | struct sock *sk, u64 flags) |
329 | { | 335 | { |
330 | struct bpf_stab *stab = container_of(map, struct bpf_stab, map); | 336 | struct bpf_stab *stab = container_of(map, struct bpf_stab, map); |
337 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
331 | struct sk_psock_link *link; | 338 | struct sk_psock_link *link; |
332 | struct sk_psock *psock; | 339 | struct sk_psock *psock; |
333 | struct sock *osk; | 340 | struct sock *osk; |
@@ -338,6 +345,8 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx, | |||
338 | return -EINVAL; | 345 | return -EINVAL; |
339 | if (unlikely(idx >= map->max_entries)) | 346 | if (unlikely(idx >= map->max_entries)) |
340 | return -E2BIG; | 347 | return -E2BIG; |
348 | if (unlikely(icsk->icsk_ulp_data)) | ||
349 | return -EINVAL; | ||
341 | 350 | ||
342 | link = sk_psock_init_link(); | 351 | link = sk_psock_init_link(); |
343 | if (!link) | 352 | if (!link) |