wasi-sockets: restore UDP send address validation - #13631
#13631Merged
alexcrichton merged 1 commit intoJun 13, 2026
Merged
wasi-sockets: restore UDP send address validation#13631
Conversation
alexcrichton
approved these changes
Jun 13, 2026
badeend
added a commit
to badeend/wasmtime
that referenced
this pull request
Jul 22, 2026
The shared socket code (crates/wasi/src/sockets/*) was modeled after the p2 interface, with p3 bindings papering over the differences, and some functionality duplicated between p2/* and p3/*. This has already caused bugs in the past (bytecodealliance#13631). Since the p3 interface is strictly a superset of p2, invert that relationship: the shared code becomes the canonical (p3-shaped) implementation, and p3's bindings are now a thin wrapper around it. All p2-only behavior & state moves into the p2 bindings layer instead (artificial restrictions like disallowing implicit binds, and the start/finish async bookkeeping). Other notable changes: - Each socket now stores its own copy of the WasiCtx's socket_addr_check at creation time, so all permission checks live in the shared socket code instead of being split across p2/p3. The p2 Network resource is now just an unforgeable capability token. - Removed the Bound state; whether a socket is bound is now determined lazily via getsockname/local_addr instead of tracked explicitly. This lets UdpSocket::send return a future that runs to completion independently, without needing to rendezvous back with the socket to update its state. - Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive; replaced UdpConnect with UdpSend/UdpReceive checks, since connecting a UDP socket is just a local operation that sets the default remote address and does no I/O of its own. connect() now succeeds as long as either send or receive is permitted for the address. - Tcp/UdpSocket::connect now also check the implicit bind the OS performs when connecting an unbound socket, matching the check already done for explicit binds. Added test coverage for previously-untested behavior: - test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP socket keeps it bound. - test_udp_send_receive_multiple (p2): bulk send/receive of multiple datagrams in a single call over a connected stream(). - test_udp_receive_after_connect (p2): datagrams from other peers queued before connecting are filtered out once connected.
badeend
added a commit
to badeend/wasmtime
that referenced
this pull request
Jul 22, 2026
The shared socket code (crates/wasi/src/sockets/*) was modeled after the p2 interface, with p3 bindings papering over the differences, and some functionality duplicated between p2/* and p3/*. This has already caused bugs in the past (bytecodealliance#13631). Since the p3 interface is strictly a superset of p2, invert that relationship: the shared code becomes the canonical (p3-shaped) implementation, and p3's bindings are now a thin wrapper around it. All p2-only behavior & state moves into the p2 bindings layer instead (artificial restrictions like disallowing implicit binds, and the start/finish async bookkeeping). Other notable changes: - Each socket now stores its own copy of the WasiCtx's socket_addr_check at creation time, so all permission checks live in the shared socket code instead of being split across p2/p3. The p2 Network resource is now just an unforgeable capability token. - Removed the Bound state; whether a socket is bound is now determined lazily via getsockname/local_addr instead of tracked explicitly. This lets UdpSocket::send return a future that runs to completion independently, without needing to rendezvous back with the socket to update its state. - Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive; replaced UdpConnect with UdpSend/UdpReceive checks, since connecting a UDP socket is just a local operation that sets the default remote address and does no I/O of its own. connect() now succeeds as long as either send or receive is permitted for the address. - Tcp/UdpSocket::connect now also check the implicit bind the OS performs when connecting an unbound socket, matching the check already done for explicit binds. Added test coverage for previously-untested behavior: - test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP socket keeps it bound. - test_udp_send_receive_multiple (p2): bulk send/receive of multiple datagrams in a single call over a connected stream(). - test_udp_receive_after_connect (p2): datagrams from other peers queued before connecting are filtered out once connected.
badeend
added a commit
to badeend/wasmtime
that referenced
this pull request
Jul 22, 2026
The shared socket code (crates/wasi/src/sockets/*) was modeled after the p2 interface, with p3 bindings papering over the differences, and some functionality duplicated between p2/* and p3/*. This has already caused bugs in the past (bytecodealliance#13631). Since the p3 interface is strictly a superset of p2, invert that relationship: the shared code becomes the canonical (p3-shaped) implementation, and p3's bindings are now a thin wrapper around it. All p2-only behavior & state moves into the p2 bindings layer instead (artificial restrictions like disallowing implicit binds, and the start/finish async bookkeeping). Other notable changes: - Each socket now stores its own copy of the WasiCtx's socket_addr_check at creation time, so all permission checks live in the shared socket code instead of being split across p2/p3. The p2 Network resource is now just an unforgeable capability token. - Removed the Bound state; whether a socket is bound is now determined lazily via getsockname/local_addr instead of tracked explicitly. This lets UdpSocket::send return a future that runs to completion independently, without needing to rendezvous back with the socket to update its state. - Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive; replaced UdpConnect with UdpSend/UdpReceive checks, since connecting a UDP socket is just a local operation that sets the default remote address and does no I/O of its own. connect() now succeeds as long as either send or receive is permitted for the address. - Tcp/UdpSocket::connect now also check the implicit bind the OS performs when connecting an unbound socket, matching the check already done for explicit binds. Added test coverage for previously-untested behavior: - test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP socket keeps it bound. - test_udp_send_receive_multiple (p2): bulk send/receive of multiple datagrams in a single call over a connected stream(). - test_udp_receive_after_connect (p2): datagrams from other peers queued before connecting are filtered out once connected.
badeend
added a commit
to badeend/wasmtime
that referenced
this pull request
Jul 22, 2026
The shared socket code (crates/wasi/src/sockets/*) was modeled after the p2 interface, with p3 bindings papering over the differences, and some functionality duplicated between p2/* and p3/*. This has already caused bugs in the past (bytecodealliance#13631). Since the p3 interface is strictly a superset of p2, invert that relationship: the shared code becomes the canonical (p3-shaped) implementation, and p3's bindings are now a thin wrapper around it. All p2-only behavior & state moves into the p2 bindings layer instead (artificial restrictions like disallowing implicit binds, and the start/finish async bookkeeping). Other notable changes: - Each socket now stores its own copy of the WasiCtx's socket_addr_check at creation time, so all permission checks live in the shared socket code instead of being split across p2/p3. The p2 Network resource is now just an unforgeable capability token. - Removed the Bound state; whether a socket is bound is now determined lazily via getsockname/local_addr instead of tracked explicitly. This lets UdpSocket::send return a future that runs to completion independently, without needing to rendezvous back with the socket to update its state. - Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive; replaced UdpConnect with UdpSend/UdpReceive checks, since connecting a UDP socket is just a local operation that sets the default remote address and does no I/O of its own. connect() now succeeds as long as either send or receive is permitted for the address. - Tcp/UdpSocket::connect now also check the implicit bind the OS performs when connecting an unbound socket, matching the check already done for explicit binds. Added test coverage for previously-untested behavior: - test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP socket keeps it bound. - test_udp_send_receive_multiple (p2): bulk send/receive of multiple datagrams in a single call over a connected stream(). - test_udp_receive_after_connect (p2): datagrams from other peers queued before connecting are filtered out once connected.
badeend
added a commit
to badeend/wasmtime
that referenced
this pull request
Jul 22, 2026
The shared socket code (crates/wasi/src/sockets/*) was modeled after the p2 interface, with p3 bindings papering over the differences, and some functionality duplicated between p2/* and p3/*. This has already caused bugs in the past (bytecodealliance#13631). Since the p3 interface is strictly a superset of p2, invert that relationship: the shared code becomes the canonical (p3-shaped) implementation, and p3's bindings are now a thin wrapper around it. All p2-only behavior & state moves into the p2 bindings layer instead (artificial restrictions like disallowing implicit binds, and the start/finish async bookkeeping). Other notable changes: - Each socket now stores its own copy of the WasiCtx's socket_addr_check at creation time, so all permission checks live in the shared socket code instead of being split across p2/p3. The p2 Network resource is now just an unforgeable capability token. - Removed the Bound state; whether a socket is bound is now determined lazily via getsockname/local_addr instead of tracked explicitly. This lets UdpSocket::send return a future that runs to completion independently, without needing to rendezvous back with the socket to update its state. - Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive; replaced UdpConnect with UdpSend/UdpReceive checks, since connecting a UDP socket is just a local operation that sets the default remote address and does no I/O of its own. connect() now succeeds as long as either send or receive is permitted for the address. - Tcp/UdpSocket::connect now also check the implicit bind the OS performs when connecting an unbound socket, matching the check already done for explicit binds. Added test coverage for previously-untested behavior: - test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP socket keeps it bound. - test_udp_send_receive_multiple (p2): bulk send/receive of multiple datagrams in a single call over a connected stream(). - test_udp_receive_after_connect (p2): datagrams from other peers queued before connecting are filtered out once connected.
pull Bot
pushed a commit
to eduardomourar/wasmtime
that referenced
this pull request
Jul 23, 2026
* Unify the p2 & p3 socket implementations The shared socket code (crates/wasi/src/sockets/*) was modeled after the p2 interface, with p3 bindings papering over the differences, and some functionality duplicated between p2/* and p3/*. This has already caused bugs in the past (bytecodealliance#13631). Since the p3 interface is strictly a superset of p2, invert that relationship: the shared code becomes the canonical (p3-shaped) implementation, and p3's bindings are now a thin wrapper around it. All p2-only behavior & state moves into the p2 bindings layer instead (artificial restrictions like disallowing implicit binds, and the start/finish async bookkeeping). Other notable changes: - Each socket now stores its own copy of the WasiCtx's socket_addr_check at creation time, so all permission checks live in the shared socket code instead of being split across p2/p3. The p2 Network resource is now just an unforgeable capability token. - Removed the Bound state; whether a socket is bound is now determined lazily via getsockname/local_addr instead of tracked explicitly. This lets UdpSocket::send return a future that runs to completion independently, without needing to rendezvous back with the socket to update its state. - Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive; replaced UdpConnect with UdpSend/UdpReceive checks, since connecting a UDP socket is just a local operation that sets the default remote address and does no I/O of its own. connect() now succeeds as long as either send or receive is permitted for the address. - Tcp/UdpSocket::connect now also check the implicit bind the OS performs when connecting an unbound socket, matching the check already done for explicit binds. Added test coverage for previously-untested behavior: - test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP socket keeps it bound. - test_udp_send_receive_multiple (p2): bulk send/receive of multiple datagrams in a single call over a connected stream(). - test_udp_receive_after_connect (p2): datagrams from other peers queued before connecting are filtered out once connected. * Give it one last poll before finishing up
yagehu
pushed a commit
to yagehu/wasmtime-x
that referenced
this pull request
Jul 26, 2026
* Unify the p2 & p3 socket implementations The shared socket code (crates/wasi/src/sockets/*) was modeled after the p2 interface, with p3 bindings papering over the differences, and some functionality duplicated between p2/* and p3/*. This has already caused bugs in the past (bytecodealliance#13631). Since the p3 interface is strictly a superset of p2, invert that relationship: the shared code becomes the canonical (p3-shaped) implementation, and p3's bindings are now a thin wrapper around it. All p2-only behavior & state moves into the p2 bindings layer instead (artificial restrictions like disallowing implicit binds, and the start/finish async bookkeeping). Other notable changes: - Each socket now stores its own copy of the WasiCtx's socket_addr_check at creation time, so all permission checks live in the shared socket code instead of being split across p2/p3. The p2 Network resource is now just an unforgeable capability token. - Removed the Bound state; whether a socket is bound is now determined lazily via getsockname/local_addr instead of tracked explicitly. This lets UdpSocket::send return a future that runs to completion independently, without needing to rendezvous back with the socket to update its state. - Updated SocketAddrUse: added TcpListen, TcpAccept, UdpReceive; replaced UdpConnect with UdpSend/UdpReceive checks, since connecting a UDP socket is just a local operation that sets the default remote address and does no I/O of its own. connect() now succeeds as long as either send or receive is permitted for the address. - Tcp/UdpSocket::connect now also check the implicit bind the OS performs when connecting an unbound socket, matching the check already done for explicit binds. Added test coverage for previously-untested behavior: - test_udp_disconnect_local_address (p2 & p3): disconnecting a UDP socket keeps it bound. - test_udp_send_receive_multiple (p2): bulk send/receive of multiple datagrams in a single call over a connected stream(). - test_udp_receive_after_connect (p2): datagrams from other peers queued before connecting are filtered out once connected. * Give it one last poll before finishing up
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Make the P3 implementation of UDP
sendperform the same validation as in P2Fixes #12568
Relates to #12475