From e2c837320ef14069ca1d697e9bf1ed0568c18c64 Mon Sep 17 00:00:00 2001 From: Irene Zhang Date: Sat, 27 Apr 2024 02:41:31 +0000 Subject: [PATCH] [libos] Bug Fix: Check bind to local IP --- src/rust/demikernel/libos/mod.rs | 15 ++++++---- src/rust/demikernel/libos/network/libos.rs | 35 +++++++++++++++------- src/rust/inetstack/mod.rs | 6 +++- src/rust/inetstack/protocols/tcp/peer.rs | 7 +++-- src/rust/inetstack/test_helpers/engine.rs | 4 ++- tests/rust/common/libos.rs | 2 +- 6 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/rust/demikernel/libos/mod.rs b/src/rust/demikernel/libos/mod.rs index f6d9c631b..d88987487 100644 --- a/src/rust/demikernel/libos/mod.rs +++ b/src/rust/demikernel/libos/mod.rs @@ -119,6 +119,7 @@ impl LibOS { LibOSName::Catnap => Self::NetworkLibOS(NetworkLibOSWrapper::Catnap(SharedNetworkLibOS::< SharedCatnapTransport, >::new( + config.local_ipv4_addr(), runtime.clone(), SharedCatnapTransport::new(&config, &mut runtime), ))), @@ -133,7 +134,9 @@ impl LibOS { Self::NetworkLibOS(NetworkLibOSWrapper::Catpowder(SharedNetworkLibOS::< SharedInetStack, >::new( - runtime.clone(), inetstack + config.local_ipv4_addr(), + runtime.clone(), + inetstack, ))) }, #[cfg(feature = "catnip-libos")] @@ -146,7 +149,9 @@ impl LibOS { Self::NetworkLibOS(NetworkLibOSWrapper::Catnip(SharedNetworkLibOS::< SharedInetStack, >::new( - runtime.clone(), inetstack + config.local_ipv4_addr(), + runtime.clone(), + inetstack, ))) }, #[cfg(feature = "catmem-libos")] @@ -157,6 +162,7 @@ impl LibOS { LibOSName::Catloop => Self::NetworkLibOS(NetworkLibOSWrapper::Catloop(SharedNetworkLibOS::< SharedCatloopTransport, >::new( + config.local_ipv4_addr(), runtime.clone(), SharedCatloopTransport::new(&config, runtime.clone()), ))), @@ -512,9 +518,8 @@ impl LibOS { pub fn wait_next_n bool>( &mut self, acceptor: Acceptor, - timeout: Option - ) -> Result<(), Fail> - { + timeout: Option, + ) -> Result<(), Fail> { timer!("demikernel::wait_next_n"); match self { #[cfg(any( diff --git a/src/rust/demikernel/libos/network/libos.rs b/src/rust/demikernel/libos/network/libos.rs index 8edc6f63d..c18397a85 100644 --- a/src/rust/demikernel/libos/network/libos.rs +++ b/src/rust/demikernel/libos/network/libos.rs @@ -76,6 +76,7 @@ use crate::pal::linux::socketaddrv4_to_sockaddr; /// Catnap libOS. All state is kept in the [runtime] and [qtable]. /// TODO: Move [qtable] into [runtime] so all state is contained in the PosixRuntime. pub struct NetworkLibOS { + local_ipv4_addr: Ipv4Addr, /// Underlying runtime. runtime: SharedDemiRuntime, /// Underlying network transport. @@ -92,8 +93,9 @@ pub struct SharedNetworkLibOS(SharedObject> /// Associate Functions for Catnap LibOS impl SharedNetworkLibOS { /// Instantiates a Catnap LibOS. - pub fn new(runtime: SharedDemiRuntime, transport: T) -> Self { + pub fn new(local_ipv4_addr: Ipv4Addr, runtime: SharedDemiRuntime, transport: T) -> Self { Self(SharedObject::new(NetworkLibOS:: { + local_ipv4_addr, runtime: runtime.clone(), transport, })) @@ -127,13 +129,24 @@ impl SharedNetworkLibOS { pub fn bind(&mut self, qd: QDesc, mut local: SocketAddr) -> Result<(), Fail> { trace!("bind() qd={:?}, local={:?}", qd, local); + // We only support IPv4 addresses right now. let localv4: SocketAddrV4 = unwrap_socketaddr(local)?; - // Check if we are binding to the wildcard address. We only support this for UDP sockets right now. + + // Check address that we are using to bind. We only support the wildcard address for UDP sockets right now. // FIXME: https://github.com/demikernel/demikernel/issues/189 - if localv4.ip() == &Ipv4Addr::UNSPECIFIED && self.get_shared_queue(&qd)?.get_qtype() != QType::UdpSocket { - let cause: String = format!("cannot bind to wildcard address (qd={:?})", qd); - error!("bind(): {}", cause); - return Err(Fail::new(libc::ENOTSUP, &cause)); + match *localv4.ip() { + Ipv4Addr::UNSPECIFIED if self.get_shared_queue(&qd)?.get_qtype() == QType::UdpSocket => (), + Ipv4Addr::UNSPECIFIED => { + let cause: String = format!("cannot bind to wildcard address (qd={:?})", qd); + error!("bind(): {}", cause); + return Err(Fail::new(libc::ENOTSUP, &cause)); + }, + addr if addr != self.local_ipv4_addr => { + let cause: String = format!("cannot bind to non-local address: {:?}", addr); + error!("bind(): {}", &cause); + return Err(Fail::new(libc::EADDRNOTAVAIL, &cause)); + }, + _ => (), } // Check if this is an ephemeral port. @@ -508,11 +521,11 @@ impl SharedNetworkLibOS { pub fn wait_next_n bool>( &mut self, mut acceptor: Acceptor, - timeout: Duration - ) -> Result<(), Fail> - { - self.runtime.clone().wait_next_n( - |qt, qd, result| acceptor(self.create_result(result, qd, qt)), timeout) + timeout: Duration, + ) -> Result<(), Fail> { + self.runtime + .clone() + .wait_next_n(|qt, qd, result| acceptor(self.create_result(result, qd, qt)), timeout) } pub fn create_result(&self, result: OperationResult, qd: QDesc, qt: QToken) -> demi_qresult_t { diff --git a/src/rust/inetstack/mod.rs b/src/rust/inetstack/mod.rs index 5caab85a8..ebc63ab67 100644 --- a/src/rust/inetstack/mod.rs +++ b/src/rust/inetstack/mod.rs @@ -98,6 +98,9 @@ pub struct InetStack { runtime: SharedDemiRuntime, network: N, local_link_addr: MacAddress, + // Keeping this here for now in case we want to use it. + #[allow(unused)] + local_ipv4_addr: Ipv4Addr, } #[derive(Clone)] @@ -141,7 +144,8 @@ impl SharedInetStack { ipv4, runtime: runtime.clone(), network, - local_link_addr: local_link_addr, + local_link_addr, + local_ipv4_addr, })); runtime.insert_background_coroutine("inetstack::poll_recv", Box::pin(me.clone().poll().fuse()))?; Ok(me) diff --git a/src/rust/inetstack/protocols/tcp/peer.rs b/src/rust/inetstack/protocols/tcp/peer.rs index 54981148e..c908bdd6e 100644 --- a/src/rust/inetstack/protocols/tcp/peer.rs +++ b/src/rust/inetstack/protocols/tcp/peer.rs @@ -139,9 +139,12 @@ impl SharedTcpPeer { // Wait for accept to complete. match socket.accept().await { Ok(socket) => { - self.addresses.insert(SocketId::Active(socket.local().unwrap(), socket.remote().unwrap()), socket.clone()); + self.addresses.insert( + SocketId::Active(socket.local().unwrap(), socket.remote().unwrap()), + socket.clone(), + ); Ok(socket) - } + }, Err(e) => Err(e), } } diff --git a/src/rust/inetstack/test_helpers/engine.rs b/src/rust/inetstack/test_helpers/engine.rs index c0135ebf8..598bb6638 100644 --- a/src/rust/inetstack/test_helpers/engine.rs +++ b/src/rust/inetstack/test_helpers/engine.rs @@ -64,7 +64,9 @@ impl SharedEngine { )?; Ok(Self(SharedNetworkLibOS::>::new( - runtime, transport, + test_rig.get_ip_addr(), + runtime, + transport, ))) } diff --git a/tests/rust/common/libos.rs b/tests/rust/common/libos.rs index 84cfa4eb2..cca604d19 100644 --- a/tests/rust/common/libos.rs +++ b/tests/rust/common/libos.rs @@ -86,7 +86,7 @@ impl DummyLibOS { logging::initialize(); let transport = SharedInetStack::new_test(runtime.clone(), network, link_addr, ipv4_addr)?; Ok(Self(SharedNetworkLibOS::>::new( - runtime, transport, + ipv4_addr, runtime, transport, ))) }