Skip to content

Commit 41adb02

Browse files
alexandruagandreeaflorescu
authored andcommitted
data_model: removed FIRECRACKER_IS_JAILED
Removed the aforementioned global variable and reworked existing logic to accomodate this change. When Firecracker is jailed, some parameters are propagated from main.rs to the appropriate places in the implementation of struct Kvm, and that of ApiServer, in order to distinguish between having to create resources, and reusing a fd already opened by the jailer. Signed-off-by: Alexandru Agache <[email protected]>
1 parent 448ea43 commit 41adb02

File tree

7 files changed

+72
-48
lines changed

7 files changed

+72
-48
lines changed

api_server/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ tokio-io = "=0.1.5"
1616

1717
data_model = { path = "../data_model" }
1818
fc_util = { path = "../fc_util" }
19-
jailer = { path = "../jailer" }
2019
logger = { path = "../logger" }
2120
sys_util = { path = "../sys_util" }
2221
vmm = { path = "../vmm" }

api_server/src/lib.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ extern crate tokio_uds;
1010

1111
extern crate data_model;
1212
extern crate fc_util;
13-
extern crate jailer;
14-
extern crate vmm;
1513
#[macro_use]
1614
extern crate logger;
1715
extern crate sys_util;
16+
extern crate vmm;
1817

1918
mod http_service;
2019
pub mod request;
@@ -44,6 +43,11 @@ pub enum Error {
4443
Eventfd(sys_util::Error),
4544
}
4645

46+
pub enum UnixDomainSocket<P> {
47+
Path(P),
48+
Fd(i32),
49+
}
50+
4751
pub type Result<T> = std::result::Result<T, Error>;
4852

4953
pub struct ApiServer {
@@ -73,22 +77,22 @@ impl ApiServer {
7377
// TODO: does tokio_uds also support abstract domain sockets?
7478
pub fn bind_and_run<P: AsRef<Path>>(
7579
&self,
76-
uds_path: P,
80+
path_or_fd: UnixDomainSocket<P>,
7781
jailer_start_time_ms: Option<u64>,
7882
) -> Result<()> {
7983
let mut core = Core::new().map_err(Error::Io)?;
8084
let handle = Rc::new(core.handle());
8185

82-
let listener = if data_model::FIRECRACKER_IS_JAILED
83-
.load(std::sync::atomic::Ordering::Relaxed)
84-
{
85-
// This is a UnixListener of the tokio_uds variety. Using fd inherited from the jailer.
86-
UnixListener::from_listener(
87-
unsafe { std::os::unix::net::UnixListener::from_raw_fd(jailer::LISTENER_FD) },
88-
&handle,
89-
).map_err(Error::Io)?
90-
} else {
91-
UnixListener::bind(uds_path, &handle).map_err(Error::Io)?
86+
let listener = match path_or_fd {
87+
UnixDomainSocket::Path(path) => UnixListener::bind(path, &handle).map_err(Error::Io)?,
88+
UnixDomainSocket::Fd(fd) => {
89+
// Safe because we assume fd is a valid file descriptor number, associated with a
90+
// previously bound UnixListener.
91+
UnixListener::from_listener(
92+
unsafe { std::os::unix::net::UnixListener::from_raw_fd(fd) },
93+
&handle,
94+
).map_err(Error::Io)?
95+
}
9296
};
9397

9498
if let Some(start_time_ms) = jailer_start_time_ms {

data_model/src/lib.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ extern crate fc_util;
1111
pub mod mmds;
1212
pub mod vm;
1313

14-
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
15-
16-
// ATOMIC_BOOL_INIT = false
17-
pub static FIRECRACKER_IS_JAILED: AtomicBool = ATOMIC_BOOL_INIT;
18-
1914
#[derive(Deserialize, Serialize)]
2015
#[serde(deny_unknown_fields)]
2116
pub struct FirecrackerContext {

kvm/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ authors = ["The Chromium OS Authors"]
77
byteorder = "=1.2.1"
88
libc = ">=0.2.39"
99

10-
data_model = { path = "../data_model" }
11-
jailer = { path = "../jailer" }
1210
kvm_sys = { path = "../kvm_sys" }
1311
memory_model = { path = "../memory_model" }
1412
sys_util = { path = "../sys_util" }

kvm/src/lib.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
extern crate byteorder;
88
extern crate libc;
99

10-
extern crate data_model;
11-
extern crate jailer;
1210
extern crate kvm_sys;
1311
extern crate memory_model;
1412
extern crate sys_util;
@@ -44,24 +42,23 @@ pub struct Kvm {
4442

4543
impl Kvm {
4644
/// Opens `/dev/kvm/` and returns a Kvm object on success.
47-
pub fn new() -> Result<Kvm> {
48-
let ret = if data_model::FIRECRACKER_IS_JAILED.load(std::sync::atomic::Ordering::Relaxed) {
49-
// /dev/kvm fd inherited from the jailer.
50-
jailer::KVM_FD
51-
} else {
52-
// Open calls are safe because we give a constant nul-terminated string and verify the
53-
// result.
54-
unsafe { open("/dev/kvm\0".as_ptr() as *const c_char, O_RDWR) }
55-
};
56-
45+
pub fn new() -> Result<Self> {
46+
// Safe because we give a constant nul-terminated string and verify the result.
47+
let ret = unsafe { open("/dev/kvm\0".as_ptr() as *const c_char, O_RDWR) };
5748
if ret < 0 {
5849
return errno_result();
5950
}
6051

6152
// Safe because we verify that ret is valid and we own the fd.
62-
Ok(Kvm {
63-
kvm: unsafe { File::from_raw_fd(ret) },
64-
})
53+
Ok(unsafe { Self::new_with_fd_number(ret) })
54+
}
55+
56+
/// Creates a new Kvm object assuming `fd` represents an existing open file descriptor
57+
/// associated with `/dev/kvm`.
58+
pub unsafe fn new_with_fd_number(fd: RawFd) -> Self {
59+
Kvm {
60+
kvm: File::from_raw_fd(fd),
61+
}
6562
}
6663

6764
pub fn get_api_version(&self) -> i32 {

src/main.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ extern crate serde_json;
55

66
extern crate api_server;
77
extern crate data_model;
8+
extern crate fc_util;
9+
extern crate jailer;
810
#[macro_use]
911
extern crate logger;
10-
extern crate fc_util;
1112
extern crate seccomp;
1213
extern crate vmm;
1314

@@ -18,7 +19,7 @@ use std::path::PathBuf;
1819
use std::sync::mpsc::channel;
1920
use std::sync::{Arc, RwLock};
2021

21-
use api_server::ApiServer;
22+
use api_server::{ApiServer, UnixDomainSocket};
2223
use data_model::mmds::MMDS;
2324
use data_model::FirecrackerContext;
2425
use logger::{Metric, LOGGER, METRICS};
@@ -74,10 +75,12 @@ fn main() {
7475
let mut instance_id = String::from(DEFAULT_INSTANCE_ID);
7576
let mut seccomp_level = 0;
7677
let mut start_time_ms = None;
78+
79+
let mut is_jailed = false;
80+
7781
if let Some(s) = cmd_arguments.value_of("context") {
7882
let context = serde_json::from_str::<FirecrackerContext>(s).unwrap();
79-
data_model::FIRECRACKER_IS_JAILED
80-
.store(context.jailed, std::sync::atomic::Ordering::Relaxed);
83+
is_jailed = context.jailed;
8184
instance_id = context.id;
8285
seccomp_level = context.seccomp_level;
8386
start_time_ms = Some(context.start_time_ms);
@@ -94,10 +97,23 @@ fn main() {
9497
let api_event_fd = server
9598
.get_event_fd_clone()
9699
.expect("Cannot clone API eventFD.");
100+
101+
let kvm_fd = if is_jailed {
102+
Some(jailer::KVM_FD)
103+
} else {
104+
None
105+
};
106+
97107
let _vmm_thread_handle =
98-
vmm::start_vmm_thread(shared_info, api_event_fd, from_api, seccomp_level);
108+
vmm::start_vmm_thread(shared_info, api_event_fd, from_api, seccomp_level, kvm_fd);
109+
110+
let uds_path_or_fd = if is_jailed {
111+
UnixDomainSocket::Fd(jailer::LISTENER_FD)
112+
} else {
113+
UnixDomainSocket::Path(bind_path)
114+
};
99115

100-
server.bind_and_run(bind_path, start_time_ms).unwrap();
116+
server.bind_and_run(uds_path_or_fd, start_time_ms).unwrap();
101117
}
102118

103119
#[cfg(test)]

vmm/src/lib.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,15 +191,20 @@ struct KvmContext {
191191
}
192192

193193
impl KvmContext {
194-
fn new() -> Result<Self> {
194+
fn new(kvm_fd: Option<RawFd>) -> Result<Self> {
195195
fn check_cap(kvm: &Kvm, cap: Cap) -> std::result::Result<(), Error> {
196196
if !kvm.check_extension(cap) {
197197
return Err(Error::KvmCap(cap));
198198
}
199199
Ok(())
200200
}
201201

202-
let kvm = Kvm::new().map_err(Error::Kvm)?;
202+
let kvm = if let Some(fd) = kvm_fd {
203+
// Safe because we expect kvm_fd to contain a valid fd number when is_some() == true.
204+
unsafe { Kvm::new_with_fd_number(fd) }
205+
} else {
206+
Kvm::new().map_err(Error::Kvm)?
207+
};
203208

204209
if kvm.get_api_version() != kvm::KVM_API_VERSION as i32 {
205210
return Err(Error::KvmApiVersion(kvm.get_api_version()));
@@ -476,6 +481,7 @@ impl Vmm {
476481
api_event_fd: EventFd,
477482
from_api: Receiver<Box<VmmAction>>,
478483
seccomp_level: u32,
484+
kvm_fd: Option<RawFd>,
479485
) -> Result<Self> {
480486
let mut epoll_context = EpollContext::new()?;
481487
// If this fails, it's fatal; using expect() to crash.
@@ -491,7 +497,7 @@ impl Vmm {
491497
).expect("Cannot add write metrics TimerFd to epoll.");
492498

493499
let block_device_configs = BlockDeviceConfigs::new();
494-
let kvm = KvmContext::new()?;
500+
let kvm = KvmContext::new(kvm_fd)?;
495501
let vm = Vm::new(kvm.fd()).map_err(Error::Vm)?;
496502

497503
Ok(Vmm {
@@ -1554,18 +1560,26 @@ impl PartialEq for VmmAction {
15541560
/// * `seccomp_level` - The level of seccomp filtering used. Filters are loaded before executing
15551561
/// guest code.
15561562
/// See `seccomp::SeccompLevel` for more information about seccomp levels.
1563+
/// * `kvm_fd` - Provides the option of supplying an already existing raw file descriptor
1564+
/// associated with `/dev/kvm`.
15571565
pub fn start_vmm_thread(
15581566
api_shared_info: Arc<RwLock<InstanceInfo>>,
15591567
api_event_fd: EventFd,
15601568
from_api: Receiver<Box<VmmAction>>,
15611569
seccomp_level: u32,
1570+
kvm_fd: Option<RawFd>,
15621571
) -> thread::JoinHandle<()> {
15631572
thread::Builder::new()
15641573
.name("fc_vmm".to_string())
15651574
.spawn(move || {
15661575
// If this fails, consider it fatal. Use expect().
1567-
let mut vmm = Vmm::new(api_shared_info, api_event_fd, from_api, seccomp_level)
1568-
.expect("Cannot create VMM.");
1576+
let mut vmm = Vmm::new(
1577+
api_shared_info,
1578+
api_event_fd,
1579+
from_api,
1580+
seccomp_level,
1581+
kvm_fd,
1582+
).expect("Cannot create VMM.");
15691583
match vmm.run_control() {
15701584
Ok(()) => vmm.stop(0),
15711585
Err(_) => vmm.stop(1),
@@ -1685,6 +1699,7 @@ mod tests {
16851699
EventFd::new().expect("cannot create eventFD"),
16861700
from_api,
16871701
seccomp::SECCOMP_LEVEL_ADVANCED,
1702+
None,
16881703
).expect("Cannot Create VMM");
16891704
return vmm;
16901705
}
@@ -2081,7 +2096,7 @@ mod tests {
20812096
use std::os::unix::fs::MetadataExt;
20822097
use std::os::unix::io::FromRawFd;
20832098

2084-
let c = KvmContext::new().unwrap();
2099+
let c = KvmContext::new(None).unwrap();
20852100
let nr_vcpus = c.nr_vcpus();
20862101
let max_vcpus = c.max_vcpus();
20872102

0 commit comments

Comments
 (0)