Skip to content

Commit 7f884cb

Browse files
jrfastabgregkh
authored andcommitted
bpf, sockmap: Remove bucket->lock from sock_{hash|map}_free
commit 90db6d7 upstream. The bucket->lock is not needed in the sock_hash_free and sock_map_free calls, in fact it is causing a splat due to being inside rcu block. | BUG: sleeping function called from invalid context at net/core/sock.c:2935 | in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 62, name: kworker/0:1 | 3 locks held by kworker/0:1/62: | #0: ffff88813b019748 ((wq_completion)events){+.+.}, at: process_one_work+0x1d7/0x5e0 | #1: ffffc900000abe50 ((work_completion)(&map->work)){+.+.}, at: process_one_work+0x1d7/0x5e0 | #2: ffff8881381f6df8 (&stab->lock){+...}, at: sock_map_free+0x26/0x180 | CPU: 0 PID: 62 Comm: kworker/0:1 Not tainted 5.5.0-04008-g7b083332376e #454 | Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-ppc64le-16.ppc.fedoraproject.org-3.fc31 04/01/2014 | Workqueue: events bpf_map_free_deferred | Call Trace: | dump_stack+0x71/0xa0 | ___might_sleep.cold+0xa6/0xb6 | lock_sock_nested+0x28/0x90 | sock_map_free+0x5f/0x180 | bpf_map_free_deferred+0x58/0x80 | process_one_work+0x260/0x5e0 | worker_thread+0x4d/0x3e0 | kthread+0x108/0x140 | ? process_one_work+0x5e0/0x5e0 | ? kthread_park+0x90/0x90 | ret_from_fork+0x3a/0x50 The reason we have stab->lock and bucket->locks in sockmap code is to handle checking EEXIST in update/delete cases. We need to be careful during an update operation that we check for EEXIST and we need to ensure that the psock object is not in some partial state of removal/insertion while we do this. So both map_update_common and sock_map_delete need to guard from being run together potentially deleting an entry we are checking, etc. But by the time we get to the tear-down code in sock_{ma[|hash}_free we have already disconnected the map and we just did synchronize_rcu() in the line above so no updates/deletes should be in flight. Because of this we can drop the bucket locks from the map free'ing code, noting no update/deletes can be in-flight. Fixes: 604326b ("bpf, sockmap: convert to generic sk_msg interface") Reported-by: Jakub Sitnicki <[email protected]> Suggested-by: Jakub Sitnicki <[email protected]> Signed-off-by: John Fastabend <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Link: https://lore.kernel.org/bpf/158385850787.30597.8346421465837046618.stgit@john-Precision-5820-Tower Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 657559d commit 7f884cb

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

net/core/sock_map.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,11 @@ static void sock_map_free(struct bpf_map *map)
233233
struct bpf_stab *stab = container_of(map, struct bpf_stab, map);
234234
int i;
235235

236+
/* After the sync no updates or deletes will be in-flight so it
237+
* is safe to walk map and remove entries without risking a race
238+
* in EEXIST update case.
239+
*/
236240
synchronize_rcu();
237-
raw_spin_lock_bh(&stab->lock);
238241
for (i = 0; i < stab->map.max_entries; i++) {
239242
struct sock **psk = &stab->sks[i];
240243
struct sock *sk;
@@ -248,7 +251,6 @@ static void sock_map_free(struct bpf_map *map)
248251
release_sock(sk);
249252
}
250253
}
251-
raw_spin_unlock_bh(&stab->lock);
252254

253255
/* wait for psock readers accessing its map link */
254256
synchronize_rcu();
@@ -863,10 +865,13 @@ static void sock_hash_free(struct bpf_map *map)
863865
struct hlist_node *node;
864866
int i;
865867

868+
/* After the sync no updates or deletes will be in-flight so it
869+
* is safe to walk map and remove entries without risking a race
870+
* in EEXIST update case.
871+
*/
866872
synchronize_rcu();
867873
for (i = 0; i < htab->buckets_num; i++) {
868874
bucket = sock_hash_select_bucket(htab, i);
869-
raw_spin_lock_bh(&bucket->lock);
870875
hlist_for_each_entry_safe(elem, node, &bucket->head, node) {
871876
hlist_del_rcu(&elem->node);
872877
lock_sock(elem->sk);
@@ -875,7 +880,6 @@ static void sock_hash_free(struct bpf_map *map)
875880
rcu_read_unlock();
876881
release_sock(elem->sk);
877882
}
878-
raw_spin_unlock_bh(&bucket->lock);
879883
}
880884

881885
/* wait for psock readers accessing its map link */

0 commit comments

Comments
 (0)