diff options
| author | Paolo Abeni <pabeni@redhat.com> | 2026-02-26 13:10:05 +0300 |
|---|---|---|
| committer | Paolo Abeni <pabeni@redhat.com> | 2026-02-26 13:10:06 +0300 |
| commit | f0a2f2aadbef0d44e6df7b43a32b509fbbf39349 (patch) | |
| tree | d00d3bb96d13214ca2a927071ef16b3e8d135c95 /include | |
| parent | 97f87e578883abe2c8bec947dbdfdc4bf624f796 (diff) | |
| parent | b6302e057fdc8f199ddae736ecdf45029f892e5c (diff) | |
| download | linux-f0a2f2aadbef0d44e6df7b43a32b509fbbf39349.tar.xz | |
Merge branch 'vsock-add-write-once-semantics-to-child_ns_mode'
Bobby Eshleman says:
====================
vsock: add write-once semantics to child_ns_mode
Two administrator processes may race when setting child_ns_mode: one
sets it to "local" and creates a namespace, but another changes it to
"global" in between. The first process ends up with a namespace in the
wrong mode. Make child_ns_mode write-once so that a namespace manager
can set it once, check the value, and be guaranteed it won't change
before creating its namespaces. Writing a different value after the
first write returns -EBUSY.
One patch for the implementation, one for docs, and one for tests.
v2: https://lore.kernel.org/r/20260218-vsock-ns-write-once-v2-0-19e4c50d509a@meta.com
v1: https://lore.kernel.org/r/20260217-vsock-ns-write-once-v1-1-a1fb30f289a9@meta.com
====================
Link: https://patch.msgid.link/20260223-vsock-ns-write-once-v3-0-c0cde6959923@meta.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'include')
| -rw-r--r-- | include/net/af_vsock.h | 13 | ||||
| -rw-r--r-- | include/net/netns/vsock.h | 3 |
2 files changed, 14 insertions, 2 deletions
diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h index d3ff48a2fbe0..533d8e75f7bb 100644 --- a/include/net/af_vsock.h +++ b/include/net/af_vsock.h @@ -276,10 +276,19 @@ static inline bool vsock_net_mode_global(struct vsock_sock *vsk) return vsock_net_mode(sock_net(sk_vsock(vsk))) == VSOCK_NET_MODE_GLOBAL; } -static inline void vsock_net_set_child_mode(struct net *net, +static inline bool vsock_net_set_child_mode(struct net *net, enum vsock_net_mode mode) { - WRITE_ONCE(net->vsock.child_ns_mode, mode); + int new_locked = mode + 1; + int old_locked = 0; /* unlocked */ + + if (try_cmpxchg(&net->vsock.child_ns_mode_locked, + &old_locked, new_locked)) { + WRITE_ONCE(net->vsock.child_ns_mode, mode); + return true; + } + + return old_locked == new_locked; } static inline enum vsock_net_mode vsock_net_child_mode(struct net *net) diff --git a/include/net/netns/vsock.h b/include/net/netns/vsock.h index b34d69a22fa8..dc8cbe45f406 100644 --- a/include/net/netns/vsock.h +++ b/include/net/netns/vsock.h @@ -17,5 +17,8 @@ struct netns_vsock { enum vsock_net_mode mode; enum vsock_net_mode child_ns_mode; + + /* 0 = unlocked, 1 = locked to global, 2 = locked to local */ + int child_ns_mode_locked; }; #endif /* __NET_NET_NAMESPACE_VSOCK_H */ |
