Correct hostinet receive flag handling

Accept and discard Linux-inert send-only flags on hostinet receive calls, add native and runsc syscall coverage, and bind the resulting immutable runtime build.
This commit is contained in:
ms2k 2026-07-31 04:07:41 +09:00
commit b240bc1d12
5 changed files with 88 additions and 9 deletions

View file

@ -41,13 +41,13 @@ use validation::{
};
pub const NETWORK_NAMESPACE_PATH: &str = "/proc/self/ns/net";
pub const RUNSC_BUILD_ID: &str = "5b441d02d40792cfe228b294fb688a80cf6161fb6876d49ef03138618ae2562e";
pub const RUNSC_BUILD_ID: &str = "34ed2f67fc55ef97a0b1755b4a94ed682f6aae57a41ce27eceb66ea366185ca7";
pub const RUNSC_BUILD_ID_BYTES: [u8; 32] = [
91, 68, 29, 2, 212, 7, 146, 207, 226, 40, 178, 148, 251, 104, 138, 128, 207, 97, 97, 251, 104,
118, 212, 158, 240, 49, 56, 97, 138, 226, 86, 46,
52, 237, 47, 103, 252, 85, 239, 151, 160, 177, 117, 91, 74, 148, 237, 104, 47, 106, 174, 87,
164, 28, 226, 126, 206, 182, 110, 163, 102, 24, 92, 167,
];
pub const RUNSC_EXECUTABLE_NAME: &str =
"lazaret-runsc-5b441d02d40792cfe228b294fb688a80cf6161fb6876d49ef03138618ae2562e";
"lazaret-runsc-34ed2f67fc55ef97a0b1755b4a94ed682f6aae57a41ce27eceb66ea366185ca7";
pub const DOMAIN_OPEN_FILE_LIMIT: u64 = 524_288;
const OCI_VERSION: &str = "1.2.1";

View file

@ -0,0 +1,74 @@
diff --git a/pkg/sentry/socket/hostinet/socket.go b/pkg/sentry/socket/hostinet/socket.go
--- a/pkg/sentry/socket/hostinet/socket.go
+++ b/pkg/sentry/socket/hostinet/socket.go
@@ -516,7 +516,7 @@
func (s *Socket) recvMsgFromHost(iovs []unix.Iovec, flags int, senderRequested bool, controlLen uint64) (uint64, int, []byte, []byte, error) {
// We always do a non-blocking recv*().
- sysflags := flags | unix.MSG_DONTWAIT
+ sysflags := flags&^ignoredRecvMsgFlags | unix.MSG_DONTWAIT
msg := unix.Msghdr{}
if len(iovs) > 0 {
@@ -545,13 +545,18 @@
return n, int(msg.Flags), senderAddrBuf[:msg.Namelen], controlBuf[:msg.Controllen], err
}
-const allowedRecvMsgFlags = unix.MSG_CTRUNC |
- unix.MSG_DONTWAIT |
- unix.MSG_ERRQUEUE |
- unix.MSG_OOB |
- unix.MSG_PEEK |
- unix.MSG_TRUNC |
- unix.MSG_WAITALL
+const (
+ // Linux accepts these send-only flags on receive calls and ignores them.
+ ignoredRecvMsgFlags = unix.MSG_DONTROUTE | unix.MSG_NOSIGNAL
+ allowedRecvMsgFlags = ignoredRecvMsgFlags |
+ unix.MSG_CTRUNC |
+ unix.MSG_DONTWAIT |
+ unix.MSG_ERRQUEUE |
+ unix.MSG_OOB |
+ unix.MSG_PEEK |
+ unix.MSG_TRUNC |
+ unix.MSG_WAITALL
+)
// RecvMsg implements socket.Socket.RecvMsg.
func (s *Socket) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags int, haveDeadline bool, deadline ktime.Time, senderRequested bool, controlLen uint64) (int, int, linux.SockAddr, uint32, socket.ControlMessages, *syserr.Error) {
diff --git a/test/syscalls/linux/socket_ip_tcp_generic.cc b/test/syscalls/linux/socket_ip_tcp_generic.cc
--- a/test/syscalls/linux/socket_ip_tcp_generic.cc
+++ b/test/syscalls/linux/socket_ip_tcp_generic.cc
@@ -14,6 +14,8 @@
#include "test/syscalls/linux/socket_ip_tcp_generic.h"
+#include <array>
+
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -103,6 +105,23 @@
EXPECT_GT(opt.tcpi_rto, 0);
}
+TEST_P(TCPSocketPairTest, ReceiveIgnoresSendOnlyFlags) {
+ auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
+
+ constexpr std::array<int, 2> kFlags = {MSG_DONTROUTE, MSG_NOSIGNAL};
+ constexpr char kPayload = 'x';
+ for (int flags : kFlags) {
+ ASSERT_THAT(RetryEINTR(send)(sockets->first_fd(), &kPayload,
+ sizeof(kPayload), 0),
+ SyscallSucceedsWithValue(sizeof(kPayload)));
+ char received = 0;
+ ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), &received,
+ sizeof(received), flags),
+ SyscallSucceedsWithValue(sizeof(received)));
+ EXPECT_EQ(received, kPayload);
+ }
+}
+
// This test validates that an RST is sent instead of a FIN when data is
// unread on calls to close(2).
TEST_P(TCPSocketPairTest, RSTSentOnCloseWithUnreadData) {

View file

@ -407,7 +407,7 @@ class VerificationTests(unittest.TestCase):
)
def test_runsc_materializer_and_install_identity_are_exact(self) -> None:
build_id = "5b441d02d40792cfe228b294fb688a80cf6161fb6876d49ef03138618ae2562e"
build_id = "34ed2f67fc55ef97a0b1755b4a94ed682f6aae57a41ce27eceb66ea366185ca7"
materializer = (ROOT / "tools/materialize-runsc").read_text()
installer = (ROOT / "tools/install-to-host").read_text()
runtime = (ROOT / "crates/lazaret-runtime-supervisor/src/sandbox.rs").read_text()
@ -438,6 +438,9 @@ class VerificationTests(unittest.TestCase):
/ "patches/gvisor-9f8f6c917-per-description-file-handles.patch"
).is_file()
)
self.assertTrue(
(ROOT / "patches/gvisor-9f8f6c917-hostinet-recv-flags.patch").is_file()
)
self.assertTrue(
(ROOT / "patches/gvisor-9f8f6c917-MODULE.bazel.lock").is_file()
)

View file

@ -59,7 +59,7 @@ if readelf -l "$sandbox_init" | grep -q 'Requesting program interpreter' ||
fi
install -m 755 "$sandbox_init" "$install_dir/lazaret-sandbox-init"
runsc_build_id=5b441d02d40792cfe228b294fb688a80cf6161fb6876d49ef03138618ae2562e
runsc_build_id=34ed2f67fc55ef97a0b1755b4a94ed682f6aae57a41ce27eceb66ea366185ca7
runsc_name="lazaret-runsc-$runsc_build_id"
runsc_source="$root/.lazaret/bin/$runsc_name"
runsc_destination="$install_dir/$runsc_name"

View file

@ -8,17 +8,19 @@ patch_files=(
"$root/patches/gvisor-9f8f6c917-directory-handles.patch"
"$root/patches/gvisor-9f8f6c917-private-ownership.patch"
"$root/patches/gvisor-9f8f6c917-per-description-file-handles.patch"
"$root/patches/gvisor-9f8f6c917-hostinet-recv-flags.patch"
)
patch_checksums=(
541420eece9ec7efbef156bdb726744ead6b4d991d41c5560f4fdfe83fb2357a
79a8c98502d3bb7c254ffb0885dbd26afffac227d04a0091ff91383df0842561
2403efb81df3185145d18ebdf8d511252fbc2fb414bae4746d7fe471ec4ea9d9
d3f49a22fe60955d422f63557bc16907fdf65dff368dff296af5535a67b76e74
)
patch_digest=cb9126927fc45e4b0c4ec82e65b4244472b1427d850477432b62183b40e7443f
patch_digest=bd37be0b8303f3a1248abc1fc898bb2cc513bad1404743428f8e9be99cbafc84
bazel_version=8.3.1
module_lock="$root/patches/gvisor-9f8f6c917-MODULE.bazel.lock"
module_checksum=8402c7beb4baf2c666f4b78e400ea3f15514b56117598c2cb5411d6a35208d34
build_id=5b441d02d40792cfe228b294fb688a80cf6161fb6876d49ef03138618ae2562e
build_id=34ed2f67fc55ef97a0b1755b4a94ed682f6aae57a41ce27eceb66ea366185ca7
archive="$root/.lazaret/cache/gvisor-$revision.tar.gz"
source="$root/.lazaret/vendor/gvisor-$build_id"
binary="$root/.lazaret/bin/lazaret-runsc-$build_id"
@ -90,7 +92,7 @@ fi
if [[ "$mode" == test ]]; then
make -C "$source" test \
TARGETS='//pkg/sentry/fsimpl/gofer:gofer_test //runsc/fsgofer:lisafs_test'
TARGETS='//pkg/sentry/fsimpl/gofer:gofer_test //runsc/fsgofer:lisafs_test //test/syscalls:socket_ip_tcp_generic_loopback_test_native //test/syscalls:socket_ip_tcp_generic_loopback_test_runsc_systrap_hostnet'
fi
if [[ "$mode" != source ]]; then
make -C "$source" build TARGETS=//runsc:runsc