Skip to content

Commit 87f9893

Browse files
Merge #373
373: [PLAT-367] Connection info r=raoulstrackx a=raoulstrackx When `TcpListener`s or `TcpStream`s are created from a `RawFd`, they lack information about local and/or peer ports used in the runner. When this information is requested, it needs to be fetched from the runner. Co-authored-by: Raoul Strackx <[email protected]>
2 parents 2a7b85d + 2e60bd7 commit 87f9893

File tree

3 files changed

+96
-8
lines changed
  • fortanix-vme

3 files changed

+96
-8
lines changed

fortanix-vme/fortanix-vme-abi/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ pub enum Request {
3030
Close {
3131
enclave_port: u32,
3232
},
33+
Info {
34+
enclave_port: u32,
35+
runner_port: Option<u32>,
36+
},
3337
}
3438

3539
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -92,6 +96,18 @@ pub enum Response {
9296
proxy_port: u32,
9397
},
9498
Closed,
99+
Info {
100+
/// The local address (as used by the runner)
101+
local: Addr,
102+
/// The address of the remote party for open connection, None for server sockets
103+
peer: Option<Addr>,
104+
},
105+
Failed(Error),
106+
}
107+
108+
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
109+
pub enum Error {
110+
ConnectionNotFound,
95111
}
96112

97113
#[cfg(test)]

fortanix-vme/fortanix-vme-runner/src/lib.rs

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::io::{self, Error as IoError, ErrorKind as IoErrorKind, Read, Write};
99
use std::net::{Shutdown, TcpListener, TcpStream};
1010
use std::os::unix::io::AsRawFd;
1111
use std::sync::{Arc, Mutex, RwLock};
12-
use fortanix_vme_abi::{self, Addr, Response, Request};
12+
use fortanix_vme_abi::{self, Addr, Error as VmeError, Response, Request};
1313
use vsock::{self, SockAddr as VsockAddr, Std, Vsock, VsockListener, VsockStream};
1414

1515
const PROXY_BUFF_SIZE: usize = 4192;
@@ -98,6 +98,10 @@ struct Connection {
9898

9999
#[derive(Clone, Debug)]
100100
struct ConnectionInfo {
101+
/// The local address (as used by the runner)
102+
local: Addr,
103+
/// The address of the remote party for open connection, None for server sockets
104+
peer: Addr,
101105
}
102106

103107
impl Connection {
@@ -110,7 +114,10 @@ impl Connection {
110114
}
111115

112116
pub fn info(&self) -> ConnectionInfo {
113-
ConnectionInfo{}
117+
ConnectionInfo {
118+
local: self.tcp_stream.local_addr().unwrap().into(),
119+
peer: self.tcp_stream.peer_addr().unwrap().into(),
120+
}
114121
}
115122

116123
/// Exchanges messages between the remote server and enclave. Returns on error, or when one of
@@ -317,9 +324,15 @@ impl Server {
317324
self.listeners.write().unwrap().remove(&addr)
318325
}
319326

320-
// Preliminary work for PLAT-367
321-
#[allow(dead_code)]
322-
fn connection(&self, enclave: VsockAddr, runner: VsockAddr) -> Option<ConnectionInfo> {
327+
fn connection_info(&self, enclave: VsockAddr, runner_port: u32) -> Option<ConnectionInfo> {
328+
// There's an interesting vsock bug. When a new connection is created to the enclave in
329+
// the `handle_request_accept` function (from `ConnectionKey::from_vsock_stream`), the
330+
// local cid is different from the cid received when inspecting `enclave: VsockStream`.
331+
// Locating the cid of the runner through the `get_local_cid` does give the same result.
332+
// When PLAT-288 lands, the cid may also here be retrieved through the open runner-enclave
333+
// connection
334+
let runner_cid = vsock::get_local_cid().unwrap_or(vsock::VMADDR_CID_LOCAL);
335+
let runner = VsockAddr::new(runner_cid, runner_port);
323336
let k = ConnectionKey::from_addresses(enclave, runner);
324337
self.connections
325338
.read()
@@ -439,11 +452,53 @@ impl Server {
439452
Ok(())
440453
}
441454

455+
fn handle_request_info(self: Arc<Self>, enclave_port: u32, runner_port: Option<u32>, enclave: &mut VsockStream) -> Result<(), IoError> {
456+
let enclave_cid: u32 = enclave.peer().unwrap().parse().unwrap_or(vsock::VMADDR_CID_HYPERVISOR);
457+
let enclave_addr = VsockAddr::new(enclave_cid, enclave_port);
458+
let response = if let Some(runner_port) = runner_port {
459+
// We're looking for a Connection
460+
if let Some(ConnectionInfo{ local, peer }) = self.connection_info(enclave_addr, runner_port) {
461+
Response::Info {
462+
local,
463+
peer: Some(peer),
464+
}
465+
} else {
466+
// Connection not found
467+
Response::Failed(VmeError::ConnectionNotFound)
468+
}
469+
} else {
470+
// We're looking for a Listener
471+
if let Some(listener) = self.listener(&enclave_addr) {
472+
let listener = listener.lock().unwrap();
473+
Response::Info {
474+
local: listener.listener.local_addr()?.into(),
475+
peer: None,
476+
}
477+
} else {
478+
// Listener not found
479+
Response::Failed(VmeError::ConnectionNotFound)
480+
}
481+
};
482+
Self::log_communication(
483+
"runner",
484+
enclave.local_port().unwrap_or_default(),
485+
"enclave",
486+
enclave.peer_port().unwrap_or_default(),
487+
&format!("{:?}", &response),
488+
Direction::Right,
489+
"vsock");
490+
enclave.write(&serde_cbor::ser::to_vec(&response).unwrap())?;
491+
Ok(())
492+
}
493+
442494
fn handle_client(self: Arc<Self>, stream: &mut VsockStream) -> Result<(), IoError> {
443495
match Self::read_request(stream) {
444496
Ok(Request::Connect{ addr }) => self.handle_request_connect(&addr, stream)?,
445497
Ok(Request::Bind{ addr, enclave_port }) => self.handle_request_bind(&addr, enclave_port, stream)?,
446498
Ok(Request::Accept{ enclave_port }) => self.handle_request_accept(enclave_port, stream)?,
499+
Ok(Request::Info{
500+
enclave_port,
501+
runner_port }) => self.handle_request_info(enclave_port, runner_port, stream)?,
447502
Ok(Request::Close{ enclave_port }) => self.handle_request_close(enclave_port, stream)?,
448503
Err(_e) => return Err(IoError::new(IoErrorKind::InvalidData, "Failed to read request")),
449504
};

fortanix-vme/tests/incoming_connection/src/main.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,38 @@
1-
use std::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, TcpListener};
2-
use std::io::{Read, Write};
1+
#![feature(io_error_uncategorized)]
2+
use std::io::{ErrorKind, Read, Write};
3+
use std::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, TcpListener, TcpStream};
4+
use std::os::unix::io::{AsRawFd, FromRawFd};
35

46
fn server_run() {
57
println!("Bind TCP socket to port 3400");
68
let listener = TcpListener::bind("127.0.0.1:3400").expect("Bind failed");
79
assert_eq!(listener.local_addr().unwrap(), SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 3400));
810

11+
let fd = listener.as_raw_fd();
12+
let listener1 = unsafe { TcpListener::from_raw_fd(fd) };
13+
assert_eq!(listener1.local_addr().unwrap(), SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 3400));
14+
915
println!("Listening for incoming connections...");
1016
for id in 1..3 {
1117
println!("Waiting for connection {}", id);
1218
match listener.accept() {
13-
Ok((mut stream, addr)) => {
19+
Ok((stream, addr)) => {
1420
println!("# addr = {:?}", addr);
1521
assert_eq!(stream.peer_addr().unwrap().ip(), Ipv4Addr::new(127, 0, 0, 1));
1622
assert!(stream.peer_addr().unwrap().port() != 3400);
1723
assert_eq!(stream.local_addr().unwrap().ip(), Ipv4Addr::new(127, 0, 0, 1));
1824
assert_eq!(stream.local_addr().unwrap().port(), 3400);
25+
26+
let fd = stream.as_raw_fd();
27+
let mut stream = unsafe { TcpStream::from_raw_fd(fd) };
28+
assert_eq!(stream.peer_addr().unwrap().ip(), Ipv4Addr::new(127, 0, 0, 1));
29+
assert!(stream.peer_addr().unwrap().port() != 3400);
30+
assert_eq!(stream.local_addr().unwrap().ip(), Ipv4Addr::new(127, 0, 0, 1));
31+
assert_eq!(stream.local_addr().unwrap().port(), 3400);
32+
33+
let no_stream = unsafe { TcpStream::from_raw_fd(666.into()) };
34+
assert_eq!(no_stream.peer_addr().unwrap_err().kind(), ErrorKind::Uncategorized);
35+
1936
println!("Connection {}: Connected", id);
2037
let mut buff_in = [0u8; 4192];
2138
let n = stream.read(&mut buff_in).unwrap();

0 commit comments

Comments
 (0)