It makes little sense for copying sk_user_data of reuseport_array during sk_clone_lock(). This patch reuses the SK_USER_DATA_NOCOPY bit introduced in commit f1ff5ce2cd5e ("net, sk_msg: Clear sk_user_data pointer on clone if tagged"). It is used to mark the sk_user_data is not supposed to be copied to its clone. Although the cloned sk's sk_user_data will not be used/freed in bpf_sk_reuseport_detach(), this change can still allow the cloned sk's sk_user_data to be used by some other means. Freeing the reuseport_array's sk_user_data does not require a rcu grace period. Thus, the existing rcu_assign_sk_user_data_nocopy() is not used.
Unified · Split
| @@ -20,11 +20,14 @@ static struct reuseport_array *reuseport_array(struct bpf_map *map) · 19 unmodified lines | ||
| 20 | 20 | /* The caller must hold the reuseport_lock */ |
| 21 | 21 | void bpf_sk_reuseport_detach(struct sock *sk) |
| 22 | 22 | { |
| 23 | − struct sock __rcu **socks; | |
| 23 | + uintptr_t sk_user_data; | |
| 24 | 24 | |
| 25 | 25 | write_lock_bh(&sk->sk_callback_lock); |
| 26 | − socks = sk->sk_user_data; | |
| 27 | − if (socks) { | |
| 26 | + sk_user_data = (uintptr_t)sk->sk_user_data; | |
| 27 | + if (sk_user_data) { | |
| 28 | + struct sock __rcu **socks; | |
| 29 | + | |
| 30 | + socks = (void *)(sk_user_data & SK_USER_DATA_PTRMASK); | |
| 28 | 31 | WRITE_ONCE(sk->sk_user_data, NULL); |
| 29 | 32 | /* |
| 30 | 33 | * Do not move this NULL assignment outside of |
| @@ -252,6 +255,7 @@ int bpf_fd_reuseport_array_update_elem(struct bpf_map *map, void *key, · 221 unmodified lines | ||
| 252 | 255 | struct sock *free_osk = NULL, *osk, *nsk; |
| 253 | 256 | struct sock_reuseport *reuse; |
| 254 | 257 | u32 index = *(u32 *)key; |
| 258 | + uintptr_t sk_user_data; | |
| 255 | 259 | struct socket *socket; |
| 256 | 260 | int err, fd; |
| 257 | 261 | |
| @@ -305,7 +309,8 @@ int bpf_fd_reuseport_array_update_elem(struct bpf_map *map, void *key, · 47 unmodified lines | ||
| 305 | 309 | if (err) |
| 306 | 310 | goto put_file_unlock; |
| 307 | 311 | |
| 308 | − WRITE_ONCE(nsk->sk_user_data, &array->ptrs[index]); | |
| 312 | + sk_user_data = (uintptr_t)&array->ptrs[index] | SK_USER_DATA_NOCOPY; | |
| 313 | + WRITE_ONCE(nsk->sk_user_data, (void *)sk_user_data); | |
| 309 | 314 | rcu_assign_pointer(array->ptrs[index], nsk); |
| 310 | 315 | free_osk = osk; |
| 311 | 316 | err = 0; |