crosvm: use sys_util::clone_process to create proxy device

The `clone_process` function was created to safely encapsulate
fork/clone usage for the proxy device. This patch changes proxy device
to do utilize that.

TEST=cargo run -- -u <other crosvm args>...
BUG=None

Change-Id: I2d9f1794be61be31f3aae21037c7df14b7691172
Reviewed-on: https://chromium-review.googlesource.com/518935
Commit-Ready: Stephen Barber <smbarber@chromium.org>
Tested-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
Zach Reizner 2017-05-31 09:47:23 -07:00 committed by chrome-bot
parent 2b2952ff1f
commit f651357433
3 changed files with 13 additions and 35 deletions

View file

@ -15,7 +15,6 @@ x86_64 = { path = "x86_64" }
kernel_loader = { path = "kernel_loader" } kernel_loader = { path = "kernel_loader" }
libc = "0.2.21" libc = "0.2.21"
byteorder = "1" byteorder = "1"
syscall_defines = { path = "syscall_defines" }
[dependencies.clap] [dependencies.clap]
version = "*" version = "*"

View file

@ -4,18 +4,14 @@
//! Runs hardware devices in child processes. //! Runs hardware devices in child processes.
use std::process; use std::io::{Error, ErrorKind, Result};
use std::io::{Error, Result};
use std::os::unix::net::UnixDatagram; use std::os::unix::net::UnixDatagram;
use std::time::Duration; use std::time::Duration;
use libc;
use libc::pid_t;
use byteorder::{NativeEndian, ByteOrder}; use byteorder::{NativeEndian, ByteOrder};
use hw::BusDevice; use hw::BusDevice;
use syscall_defines::linux::LinuxSyscall::SYS_clone; use sys_util::{clone_process, CloneNamespace};
const SOCKET_TIMEOUT_MS: u64 = 2000; const SOCKET_TIMEOUT_MS: u64 = 2000;
const MSG_SIZE: usize = 24; const MSG_SIZE: usize = 24;
@ -27,7 +23,7 @@ enum Command {
Shutdown = 2, Shutdown = 2,
} }
fn child_proc(sock: UnixDatagram, device: &mut BusDevice) -> ! { fn child_proc(sock: UnixDatagram, device: &mut BusDevice) {
let mut running = true; let mut running = true;
let res = handle_eintr!(sock.send(&CHILD_SIGNATURE)); let res = handle_eintr!(sock.send(&CHILD_SIGNATURE));
@ -75,23 +71,6 @@ fn child_proc(sock: UnixDatagram, device: &mut BusDevice) -> ! {
break; break;
} }
} }
// ! Never returns
process::exit(0);
}
unsafe fn do_clone() -> Result<pid_t> {
// Forking is unsafe, this function must be unsafe as there is no way to
// guarantee saftey without more context about the state of the program.
let pid = libc::syscall(SYS_clone as i64,
libc::CLONE_NEWUSER | libc::CLONE_NEWPID |
libc::SIGCHLD as i32,
0);
if pid < 0 {
Err(Error::last_os_error())
} else {
Ok(pid as pid_t)
}
} }
/// Wraps an inner `hw::BusDevice` that is run inside a child process via fork. /// Wraps an inner `hw::BusDevice` that is run inside a child process via fork.
@ -107,20 +86,21 @@ impl ProxyDevice {
/// ///
/// The forked process will automatically be terminated when this is dropped, so be sure to keep /// The forked process will automatically be terminated when this is dropped, so be sure to keep
/// a reference. /// a reference.
/// `post_clone_cb` - Called after forking the child process, passed the ///
/// child end of the pipe that must be kep open. /// # Arguments
/// * `device` - The device to isolate to another process.
/// * `post_clone_cb` - Called after forking the child process, passed the child end of the pipe
/// that must be kept open.
pub fn new<D: BusDevice, F>(mut device: D, post_clone_cb: F) -> Result<ProxyDevice> pub fn new<D: BusDevice, F>(mut device: D, post_clone_cb: F) -> Result<ProxyDevice>
where F: FnOnce(&UnixDatagram) { where F: FnOnce(&UnixDatagram)
{
let (child_sock, parent_sock) = UnixDatagram::pair()?; let (child_sock, parent_sock) = UnixDatagram::pair()?;
// Forking a new process is unsafe, we must ensure no resources required clone_process(CloneNamespace::NewUserPid, move || {
// by the other side are freed after the two processes start.
let ret = unsafe { do_clone()? };
if ret == 0 {
post_clone_cb(&child_sock); post_clone_cb(&child_sock);
// ! Never returns
child_proc(child_sock, &mut device); child_proc(child_sock, &mut device);
} })
.map_err(|e| Error::new(ErrorKind::Other, format!("{:?}", e)))?;
let mut buf = [0; MSG_SIZE]; let mut buf = [0; MSG_SIZE];
parent_sock parent_sock

View file

@ -12,7 +12,6 @@ extern crate x86_64;
extern crate kernel_loader; extern crate kernel_loader;
extern crate byteorder; extern crate byteorder;
#[macro_use] extern crate sys_util; #[macro_use] extern crate sys_util;
extern crate syscall_defines;
use std::ffi::{CString, CStr}; use std::ffi::{CString, CStr};
use std::fmt; use std::fmt;