mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-11 04:26:38 +00:00
linux: refactor creating jails of devices
Use a function to reduce the repetition. BUG=None TEST=some basic build and runtime tests on an eve device: () run 'cargo check' and 'emerge-eve crosvm' () launch default termina VM from GUI, install and open eclipse app to test network, input and graphic features () launch a test VM instance from shell and vsh into it, verify virtio devices are created at /sys/bus/virtio/devices/ Change-Id: If66defdd584cf9afa6f38531e41b85d327362dfa Signed-off-by: Jianxun Zhang <jianxun.zhang@intel.com> Reviewed-on: https://chromium-review.googlesource.com/1480738 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: David Tolnay <dtolnay@chromium.org> Reviewed-by: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
7898632b42
commit
8f4d7687ea
1 changed files with 179 additions and 239 deletions
418
src/linux.rs
418
src/linux.rs
|
@ -223,6 +223,21 @@ fn create_base_minijail(root: &Path, seccomp_policy: &Path) -> Result<Minijail>
|
||||||
Ok(j)
|
Ok(j)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn simple_jail(cfg: &Config, policy: &str) -> Result<Option<Minijail>> {
|
||||||
|
if cfg.multiprocess {
|
||||||
|
let pivot_root: &str = option_env!("DEFAULT_PIVOT_ROOT").unwrap_or("/var/empty");
|
||||||
|
// A directory for a jailed device's pivot root.
|
||||||
|
let root_path = Path::new(pivot_root);
|
||||||
|
if !root_path.exists() {
|
||||||
|
return Err(Error::PivotRootDoesntExist(pivot_root));
|
||||||
|
}
|
||||||
|
let policy_path: PathBuf = cfg.seccomp_policy_dir.join(policy);
|
||||||
|
Ok(Some(create_base_minijail(root_path, &policy_path)?))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn create_virtio_devs(
|
fn create_virtio_devs(
|
||||||
cfg: Config,
|
cfg: Config,
|
||||||
mem: &GuestMemory,
|
mem: &GuestMemory,
|
||||||
|
@ -231,16 +246,8 @@ fn create_virtio_devs(
|
||||||
balloon_device_socket: UnixSeqpacket,
|
balloon_device_socket: UnixSeqpacket,
|
||||||
disk_device_sockets: &mut Vec<UnixSeqpacket>,
|
disk_device_sockets: &mut Vec<UnixSeqpacket>,
|
||||||
) -> std::result::Result<Vec<(Box<PciDevice + 'static>, Option<Minijail>)>, Box<error::Error>> {
|
) -> std::result::Result<Vec<(Box<PciDevice + 'static>, Option<Minijail>)>, Box<error::Error>> {
|
||||||
let default_pivot_root: &str = option_env!("DEFAULT_PIVOT_ROOT").unwrap_or("/var/empty");
|
|
||||||
|
|
||||||
let mut devs = Vec::new();
|
let mut devs = Vec::new();
|
||||||
|
|
||||||
// An empty directory for jailed device's pivot root.
|
|
||||||
let empty_root_path = Path::new(default_pivot_root);
|
|
||||||
if cfg.multiprocess && !empty_root_path.exists() {
|
|
||||||
return Err(Box::new(Error::PivotRootDoesntExist(default_pivot_root)));
|
|
||||||
}
|
|
||||||
|
|
||||||
for disk in &cfg.disks {
|
for disk in &cfg.disks {
|
||||||
let disk_device_socket = disk_device_sockets.remove(0);
|
let disk_device_socket = disk_device_sockets.remove(0);
|
||||||
|
|
||||||
|
@ -289,49 +296,32 @@ fn create_virtio_devs(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let jail = if cfg.multiprocess {
|
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("block_device.policy");
|
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
devs.push(VirtioDeviceStub {
|
devs.push(VirtioDeviceStub {
|
||||||
dev: block_box,
|
dev: block_box,
|
||||||
jail,
|
jail: simple_jail(&cfg, "block_device.policy")?,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let rng_box = Box::new(devices::virtio::Rng::new().map_err(Error::RngDeviceNew)?);
|
let rng_box = Box::new(devices::virtio::Rng::new().map_err(Error::RngDeviceNew)?);
|
||||||
let rng_jail = if cfg.multiprocess {
|
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("rng_device.policy");
|
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
devs.push(VirtioDeviceStub {
|
devs.push(VirtioDeviceStub {
|
||||||
dev: rng_box,
|
dev: rng_box,
|
||||||
jail: rng_jail,
|
jail: simple_jail(&cfg, "rng_device.policy")?,
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(feature = "tpm")]
|
#[cfg(feature = "tpm")]
|
||||||
{
|
{
|
||||||
if cfg.software_tpm {
|
if cfg.software_tpm {
|
||||||
let tpm_box = Box::new(devices::virtio::Tpm::new());
|
let tpm_box = Box::new(devices::virtio::Tpm::new());
|
||||||
let tpm_jail = if cfg.multiprocess {
|
|
||||||
let policy_path = cfg.seccomp_policy_dir.join("tpm_device.policy");
|
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
devs.push(VirtioDeviceStub {
|
devs.push(VirtioDeviceStub {
|
||||||
dev: tpm_box,
|
dev: tpm_box,
|
||||||
jail: tpm_jail,
|
jail: simple_jail(&cfg, "tpm_device.policy")?,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(trackpad_spec) = cfg.virtio_trackpad {
|
if let Some(trackpad_spec) = &cfg.virtio_trackpad {
|
||||||
match create_input_socket(&trackpad_spec.path) {
|
match create_input_socket(&trackpad_spec.path) {
|
||||||
Ok(socket) => {
|
Ok(socket) => {
|
||||||
let trackpad_box = Box::new(
|
let trackpad_box = Box::new(
|
||||||
|
@ -342,15 +332,10 @@ fn create_virtio_devs(
|
||||||
)
|
)
|
||||||
.map_err(Error::InputDeviceNew)?,
|
.map_err(Error::InputDeviceNew)?,
|
||||||
);
|
);
|
||||||
let trackpad_jail = if cfg.multiprocess {
|
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("input_device.policy");
|
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
devs.push(VirtioDeviceStub {
|
devs.push(VirtioDeviceStub {
|
||||||
dev: trackpad_box,
|
dev: trackpad_box,
|
||||||
jail: trackpad_jail,
|
jail: simple_jail(&cfg, "input_device.policy")?,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -360,20 +345,15 @@ fn create_virtio_devs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mouse_socket) = cfg.virtio_mouse {
|
if let Some(mouse_socket) = &cfg.virtio_mouse {
|
||||||
match create_input_socket(&mouse_socket) {
|
match create_input_socket(&mouse_socket) {
|
||||||
Ok(socket) => {
|
Ok(socket) => {
|
||||||
let mouse_box =
|
let mouse_box =
|
||||||
Box::new(devices::virtio::new_mouse(socket).map_err(Error::InputDeviceNew)?);
|
Box::new(devices::virtio::new_mouse(socket).map_err(Error::InputDeviceNew)?);
|
||||||
let mouse_jail = if cfg.multiprocess {
|
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("input_device.policy");
|
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
devs.push(VirtioDeviceStub {
|
devs.push(VirtioDeviceStub {
|
||||||
dev: mouse_box,
|
dev: mouse_box,
|
||||||
jail: mouse_jail,
|
jail: simple_jail(&cfg, "input_device.policy")?,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -383,20 +363,15 @@ fn create_virtio_devs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(keyboard_socket) = cfg.virtio_keyboard {
|
if let Some(keyboard_socket) = &cfg.virtio_keyboard {
|
||||||
match create_input_socket(&keyboard_socket) {
|
match create_input_socket(&keyboard_socket) {
|
||||||
Ok(socket) => {
|
Ok(socket) => {
|
||||||
let keyboard_box =
|
let keyboard_box =
|
||||||
Box::new(devices::virtio::new_keyboard(socket).map_err(Error::InputDeviceNew)?);
|
Box::new(devices::virtio::new_keyboard(socket).map_err(Error::InputDeviceNew)?);
|
||||||
let keyboard_jail = if cfg.multiprocess {
|
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("input_device.policy");
|
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
devs.push(VirtioDeviceStub {
|
devs.push(VirtioDeviceStub {
|
||||||
dev: keyboard_box,
|
dev: keyboard_box,
|
||||||
jail: keyboard_jail,
|
jail: simple_jail(&cfg, "input_device.policy")?,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -406,7 +381,7 @@ fn create_virtio_devs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for dev_path in cfg.virtio_input_evdevs {
|
for dev_path in &cfg.virtio_input_evdevs {
|
||||||
let dev_file = OpenOptions::new()
|
let dev_file = OpenOptions::new()
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
|
@ -414,50 +389,35 @@ fn create_virtio_devs(
|
||||||
.map_err(|e| Box::new(e))?;
|
.map_err(|e| Box::new(e))?;
|
||||||
let vinput_box =
|
let vinput_box =
|
||||||
Box::new(devices::virtio::new_evdev(dev_file).map_err(Error::InputDeviceNew)?);
|
Box::new(devices::virtio::new_evdev(dev_file).map_err(Error::InputDeviceNew)?);
|
||||||
let vinput_jail = if cfg.multiprocess {
|
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("input_device.policy");
|
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
devs.push(VirtioDeviceStub {
|
devs.push(VirtioDeviceStub {
|
||||||
dev: vinput_box,
|
dev: vinput_box,
|
||||||
jail: vinput_jail,
|
jail: simple_jail(&cfg, "input_device.policy")?,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let balloon_box = Box::new(
|
let balloon_box = Box::new(
|
||||||
devices::virtio::Balloon::new(balloon_device_socket).map_err(Error::BalloonDeviceNew)?,
|
devices::virtio::Balloon::new(balloon_device_socket).map_err(Error::BalloonDeviceNew)?,
|
||||||
);
|
);
|
||||||
let balloon_jail = if cfg.multiprocess {
|
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("balloon_device.policy");
|
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
devs.push(VirtioDeviceStub {
|
devs.push(VirtioDeviceStub {
|
||||||
dev: balloon_box,
|
dev: balloon_box,
|
||||||
jail: balloon_jail,
|
jail: simple_jail(&cfg, "balloon_device.policy")?,
|
||||||
});
|
});
|
||||||
|
|
||||||
// We checked above that if the IP is defined, then the netmask is, too.
|
// We checked above that if the IP is defined, then the netmask is, too.
|
||||||
for tap_fd in cfg.tap_fd {
|
for tap_fd in &cfg.tap_fd {
|
||||||
// Safe because we ensure that we get a unique handle to the fd.
|
// Safe because we ensure that we get a unique handle to the fd.
|
||||||
let tap = unsafe {
|
let tap = unsafe {
|
||||||
Tap::from_raw_fd(validate_raw_fd(tap_fd).map_err(Error::ValidateRawFd)?)
|
Tap::from_raw_fd(validate_raw_fd(*tap_fd).map_err(Error::ValidateRawFd)?)
|
||||||
.map_err(Error::CreateTapDevice)?
|
.map_err(Error::CreateTapDevice)?
|
||||||
};
|
};
|
||||||
let net_box = Box::new(devices::virtio::Net::from(tap).map_err(Error::NetDeviceNew)?);
|
let net_box = Box::new(devices::virtio::Net::from(tap).map_err(Error::NetDeviceNew)?);
|
||||||
|
|
||||||
let jail = if cfg.multiprocess {
|
devs.push(VirtioDeviceStub {
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("net_device.policy");
|
dev: net_box,
|
||||||
|
jail: simple_jail(&cfg, "net_device.policy")?,
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
});
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
devs.push(VirtioDeviceStub { dev: net_box, jail });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(host_ip) = cfg.host_ip {
|
if let Some(host_ip) = cfg.host_ip {
|
||||||
|
@ -480,19 +440,16 @@ fn create_virtio_devs(
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let jail = if cfg.multiprocess {
|
let policy = if cfg.vhost_net {
|
||||||
let policy_path: PathBuf = if cfg.vhost_net {
|
"vhost_net_device.policy"
|
||||||
cfg.seccomp_policy_dir.join("vhost_net_device.policy")
|
|
||||||
} else {
|
|
||||||
cfg.seccomp_policy_dir.join("net_device.policy")
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
"net_device.policy"
|
||||||
};
|
};
|
||||||
|
|
||||||
devs.push(VirtioDeviceStub { dev: net_box, jail });
|
devs.push(VirtioDeviceStub {
|
||||||
|
dev: net_box,
|
||||||
|
jail: simple_jail(&cfg, policy)?,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -520,70 +477,67 @@ fn create_virtio_devs(
|
||||||
wayland_socket_path.as_path()
|
wayland_socket_path.as_path()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
let jail = match simple_jail(&cfg, "gpu_device.policy")? {
|
||||||
let jail = if cfg.multiprocess {
|
Some(mut jail) => {
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("gpu_device.policy");
|
// Create a tmpfs in the device's root directory so that we can bind mount the
|
||||||
let mut jail = create_base_minijail(empty_root_path, &policy_path)?;
|
// dri directory into it. The size=67108864 is size=64*1024*1024 or size=64MB.
|
||||||
|
jail.mount_with_data(
|
||||||
// Create a tmpfs in the device's root directory so that we can bind mount the
|
Path::new("none"),
|
||||||
// dri directory into it. The size=67108864 is size=64*1024*1024 or size=64MB.
|
Path::new("/"),
|
||||||
jail.mount_with_data(
|
"tmpfs",
|
||||||
Path::new("none"),
|
(libc::MS_NOSUID | libc::MS_NODEV | libc::MS_NOEXEC) as usize,
|
||||||
Path::new("/"),
|
"size=67108864",
|
||||||
"tmpfs",
|
)
|
||||||
(libc::MS_NOSUID | libc::MS_NODEV | libc::MS_NOEXEC) as usize,
|
|
||||||
"size=67108864",
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Device nodes required for DRM.
|
|
||||||
let sys_dev_char_path = Path::new("/sys/dev/char");
|
|
||||||
jail.mount_bind(sys_dev_char_path, sys_dev_char_path, false)
|
|
||||||
.unwrap();
|
|
||||||
let sys_devices_path = Path::new("/sys/devices");
|
|
||||||
jail.mount_bind(sys_devices_path, sys_devices_path, false)
|
|
||||||
.unwrap();
|
|
||||||
let drm_dri_path = Path::new("/dev/dri");
|
|
||||||
jail.mount_bind(drm_dri_path, drm_dri_path, false).unwrap();
|
|
||||||
|
|
||||||
// Libraries that are required when mesa drivers are dynamically loaded.
|
|
||||||
let lib_path = Path::new("/lib64");
|
|
||||||
jail.mount_bind(lib_path, lib_path, false).unwrap();
|
|
||||||
let usr_lib_path = Path::new("/usr/lib64");
|
|
||||||
jail.mount_bind(usr_lib_path, usr_lib_path, false).unwrap();
|
|
||||||
|
|
||||||
// Bind mount the wayland socket into jail's root. This is necessary since each
|
|
||||||
// new wayland context must open() the socket.
|
|
||||||
jail.mount_bind(wayland_socket_path.as_path(), jailed_wayland_path, true)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Set the uid/gid for the jailed process, and give a basic id map. This
|
// Device nodes required for DRM.
|
||||||
// is required for the above bind mount to work.
|
let sys_dev_char_path = Path::new("/sys/dev/char");
|
||||||
let crosvm_user_group = CStr::from_bytes_with_nul(b"crosvm\0").unwrap();
|
jail.mount_bind(sys_dev_char_path, sys_dev_char_path, false)
|
||||||
let crosvm_uid = match get_user_id(&crosvm_user_group) {
|
.unwrap();
|
||||||
Ok(u) => u,
|
let sys_devices_path = Path::new("/sys/devices");
|
||||||
Err(e) => {
|
jail.mount_bind(sys_devices_path, sys_devices_path, false)
|
||||||
warn!("falling back to current user id for gpu: {}", e);
|
.unwrap();
|
||||||
geteuid()
|
let drm_dri_path = Path::new("/dev/dri");
|
||||||
}
|
jail.mount_bind(drm_dri_path, drm_dri_path, false).unwrap();
|
||||||
};
|
|
||||||
let crosvm_gid = match get_group_id(&crosvm_user_group) {
|
|
||||||
Ok(u) => u,
|
|
||||||
Err(e) => {
|
|
||||||
warn!("falling back to current group id for gpu: {}", e);
|
|
||||||
getegid()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
jail.change_uid(crosvm_uid);
|
|
||||||
jail.change_gid(crosvm_gid);
|
|
||||||
jail.uidmap(&format!("{0} {0} 1", crosvm_uid))
|
|
||||||
.map_err(Error::SettingUidMap)?;
|
|
||||||
jail.gidmap(&format!("{0} {0} 1", crosvm_gid))
|
|
||||||
.map_err(Error::SettingGidMap)?;
|
|
||||||
|
|
||||||
Some(jail)
|
// Libraries that are required when mesa drivers are dynamically loaded.
|
||||||
} else {
|
let lib_path = Path::new("/lib64");
|
||||||
None
|
jail.mount_bind(lib_path, lib_path, false).unwrap();
|
||||||
|
let usr_lib_path = Path::new("/usr/lib64");
|
||||||
|
jail.mount_bind(usr_lib_path, usr_lib_path, false).unwrap();
|
||||||
|
|
||||||
|
// Bind mount the wayland socket into jail's root. This is necessary since each
|
||||||
|
// new wayland context must open() the socket.
|
||||||
|
jail.mount_bind(wayland_socket_path.as_path(), jailed_wayland_path, true)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Set the uid/gid for the jailed process, and give a basic id map. This
|
||||||
|
// is required for the above bind mount to work.
|
||||||
|
let crosvm_user_group = CStr::from_bytes_with_nul(b"crosvm\0").unwrap();
|
||||||
|
let crosvm_uid = match get_user_id(&crosvm_user_group) {
|
||||||
|
Ok(u) => u,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("falling back to current user id for gpu: {}", e);
|
||||||
|
geteuid()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let crosvm_gid = match get_group_id(&crosvm_user_group) {
|
||||||
|
Ok(u) => u,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("falling back to current group id for gpu: {}", e);
|
||||||
|
getegid()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
jail.change_uid(crosvm_uid);
|
||||||
|
jail.change_gid(crosvm_gid);
|
||||||
|
jail.uidmap(&format!("{0} {0} 1", crosvm_uid))
|
||||||
|
.map_err(Error::SettingUidMap)?;
|
||||||
|
jail.gidmap(&format!("{0} {0} 1", crosvm_gid))
|
||||||
|
.map_err(Error::SettingGidMap)?;
|
||||||
|
|
||||||
|
Some(jail)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
};
|
};
|
||||||
devs.push(VirtioDeviceStub { dev: gpu_box, jail });
|
devs.push(VirtioDeviceStub { dev: gpu_box, jail });
|
||||||
}
|
}
|
||||||
|
@ -613,55 +567,53 @@ fn create_virtio_devs(
|
||||||
.map_err(Error::WaylandDeviceNew)?,
|
.map_err(Error::WaylandDeviceNew)?,
|
||||||
);
|
);
|
||||||
|
|
||||||
let jail = if cfg.multiprocess {
|
let jail = match simple_jail(&cfg, "wl_device.policy")? {
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("wl_device.policy");
|
Some(mut jail) => {
|
||||||
let mut jail = create_base_minijail(empty_root_path, &policy_path)?;
|
// Create a tmpfs in the device's root directory so that we can bind mount the wayland
|
||||||
|
// socket directory into it. The size=67108864 is size=64*1024*1024 or size=64MB.
|
||||||
// Create a tmpfs in the device's root directory so that we can bind mount the wayland
|
jail.mount_with_data(
|
||||||
// socket directory into it. The size=67108864 is size=64*1024*1024 or size=64MB.
|
Path::new("none"),
|
||||||
jail.mount_with_data(
|
Path::new("/"),
|
||||||
Path::new("none"),
|
"tmpfs",
|
||||||
Path::new("/"),
|
(libc::MS_NOSUID | libc::MS_NODEV | libc::MS_NOEXEC) as usize,
|
||||||
"tmpfs",
|
"size=67108864",
|
||||||
(libc::MS_NOSUID | libc::MS_NODEV | libc::MS_NOEXEC) as usize,
|
)
|
||||||
"size=67108864",
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Bind mount the wayland socket's directory into jail's root. This is necessary since
|
|
||||||
// each new wayland context must open() the socket. If the wayland socket is ever
|
|
||||||
// destroyed and remade in the same host directory, new connections will be possible
|
|
||||||
// without restarting the wayland device.
|
|
||||||
jail.mount_bind(wayland_socket_dir, jailed_wayland_dir, true)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Set the uid/gid for the jailed process, and give a basic id map. This
|
// Bind mount the wayland socket's directory into jail's root. This is necessary since
|
||||||
// is required for the above bind mount to work.
|
// each new wayland context must open() the socket. If the wayland socket is ever
|
||||||
let crosvm_user_group = CStr::from_bytes_with_nul(b"crosvm\0").unwrap();
|
// destroyed and remade in the same host directory, new connections will be possible
|
||||||
let crosvm_uid = match get_user_id(&crosvm_user_group) {
|
// without restarting the wayland device.
|
||||||
Ok(u) => u,
|
jail.mount_bind(wayland_socket_dir, jailed_wayland_dir, true)
|
||||||
Err(e) => {
|
.unwrap();
|
||||||
warn!("falling back to current user id for Wayland: {}", e);
|
|
||||||
geteuid()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let crosvm_gid = match get_group_id(&crosvm_user_group) {
|
|
||||||
Ok(u) => u,
|
|
||||||
Err(e) => {
|
|
||||||
warn!("falling back to current group id for Wayland: {}", e);
|
|
||||||
getegid()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
jail.change_uid(crosvm_uid);
|
|
||||||
jail.change_gid(crosvm_gid);
|
|
||||||
jail.uidmap(&format!("{0} {0} 1", crosvm_uid))
|
|
||||||
.map_err(Error::SettingUidMap)?;
|
|
||||||
jail.gidmap(&format!("{0} {0} 1", crosvm_gid))
|
|
||||||
.map_err(Error::SettingGidMap)?;
|
|
||||||
|
|
||||||
Some(jail)
|
// Set the uid/gid for the jailed process, and give a basic id map. This
|
||||||
} else {
|
// is required for the above bind mount to work.
|
||||||
None
|
let crosvm_user_group = CStr::from_bytes_with_nul(b"crosvm\0").unwrap();
|
||||||
|
let crosvm_uid = match get_user_id(&crosvm_user_group) {
|
||||||
|
Ok(u) => u,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("falling back to current user id for Wayland: {}", e);
|
||||||
|
geteuid()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let crosvm_gid = match get_group_id(&crosvm_user_group) {
|
||||||
|
Ok(u) => u,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("falling back to current group id for Wayland: {}", e);
|
||||||
|
getegid()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
jail.change_uid(crosvm_uid);
|
||||||
|
jail.change_gid(crosvm_gid);
|
||||||
|
jail.uidmap(&format!("{0} {0} 1", crosvm_uid))
|
||||||
|
.map_err(Error::SettingUidMap)?;
|
||||||
|
jail.gidmap(&format!("{0} {0} 1", crosvm_gid))
|
||||||
|
.map_err(Error::SettingGidMap)?;
|
||||||
|
|
||||||
|
Some(jail)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
};
|
};
|
||||||
devs.push(VirtioDeviceStub { dev: wl_box, jail });
|
devs.push(VirtioDeviceStub { dev: wl_box, jail });
|
||||||
}
|
}
|
||||||
|
@ -671,17 +623,9 @@ fn create_virtio_devs(
|
||||||
devices::virtio::vhost::Vsock::new(cid, &mem).map_err(Error::VhostVsockDeviceNew)?,
|
devices::virtio::vhost::Vsock::new(cid, &mem).map_err(Error::VhostVsockDeviceNew)?,
|
||||||
);
|
);
|
||||||
|
|
||||||
let jail = if cfg.multiprocess {
|
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("vhost_vsock_device.policy");
|
|
||||||
|
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
devs.push(VirtioDeviceStub {
|
devs.push(VirtioDeviceStub {
|
||||||
dev: vsock_box,
|
dev: vsock_box,
|
||||||
jail,
|
jail: simple_jail(&cfg, "vhost_vsock_device.policy")?,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,28 +646,28 @@ fn create_virtio_devs(
|
||||||
};
|
};
|
||||||
|
|
||||||
for &(ref src, ref tag) in &cfg.shared_dirs {
|
for &(ref src, ref tag) in &cfg.shared_dirs {
|
||||||
let (jail, root) = if cfg.multiprocess {
|
let (jail, root) = match simple_jail(&cfg, "9p_device.policy")? {
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("9p_device.policy");
|
Some(mut jail) => {
|
||||||
let mut jail = create_base_minijail(empty_root_path, &policy_path)?;
|
// The shared directory becomes the root of the device's file system.
|
||||||
|
let root = Path::new("/");
|
||||||
|
jail.mount_bind(&src, root, true).unwrap();
|
||||||
|
|
||||||
// The shared directory becomes the root of the device's file system.
|
// Set the uid/gid for the jailed process, and give a basic id map. This
|
||||||
let root = Path::new("/");
|
// is required for the above bind mount to work.
|
||||||
jail.mount_bind(&src, root, true).unwrap();
|
jail.change_uid(chronos_uid);
|
||||||
|
jail.change_gid(chronos_gid);
|
||||||
|
jail.uidmap(&format!("{0} {0} 1", chronos_uid))
|
||||||
|
.map_err(Error::SettingUidMap)?;
|
||||||
|
jail.gidmap(&format!("{0} {0} 1", chronos_gid))
|
||||||
|
.map_err(Error::SettingGidMap)?;
|
||||||
|
|
||||||
// Set the uid/gid for the jailed process, and give a basic id map. This
|
(Some(jail), root)
|
||||||
// is required for the above bind mount to work.
|
}
|
||||||
jail.change_uid(chronos_uid);
|
None => {
|
||||||
jail.change_gid(chronos_gid);
|
// There's no bind mount so we tell the server to treat the source directory as the
|
||||||
jail.uidmap(&format!("{0} {0} 1", chronos_uid))
|
// root. The double deref here converts |src| from a &PathBuf into a &Path.
|
||||||
.map_err(Error::SettingUidMap)?;
|
(None, &**src)
|
||||||
jail.gidmap(&format!("{0} {0} 1", chronos_gid))
|
}
|
||||||
.map_err(Error::SettingGidMap)?;
|
|
||||||
|
|
||||||
(Some(jail), root)
|
|
||||||
} else {
|
|
||||||
// There's no bind mount so we tell the server to treat the source directory as the
|
|
||||||
// root. The double deref here converts |src| from a &PathBuf into a &Path.
|
|
||||||
(None, &**src)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let p9_box = Box::new(devices::virtio::P9::new(root, tag).map_err(Error::P9DeviceNew)?);
|
let p9_box = Box::new(devices::virtio::P9::new(root, tag).map_err(Error::P9DeviceNew)?);
|
||||||
|
@ -743,13 +687,11 @@ fn create_virtio_devs(
|
||||||
(*mem).clone(),
|
(*mem).clone(),
|
||||||
Box::new(CrasClient::new()?),
|
Box::new(CrasClient::new()?),
|
||||||
));
|
));
|
||||||
let cras_audio_jail = if cfg.multiprocess {
|
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("cras_audio_device.policy");
|
pci_devices.push((
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
cras_audio_box,
|
||||||
} else {
|
simple_jail(&cfg, "cras_audio_device.policy")?,
|
||||||
None
|
));
|
||||||
};
|
|
||||||
pci_devices.push((cras_audio_box, cras_audio_jail));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.null_audio {
|
if cfg.null_audio {
|
||||||
|
@ -757,13 +699,11 @@ fn create_virtio_devs(
|
||||||
(*mem).clone(),
|
(*mem).clone(),
|
||||||
Box::new(DummyStreamSource::new()),
|
Box::new(DummyStreamSource::new()),
|
||||||
));
|
));
|
||||||
let null_audio_jail = if cfg.multiprocess {
|
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join("null_audio_device.policy");
|
pci_devices.push((
|
||||||
Some(create_base_minijail(empty_root_path, &policy_path)?)
|
null_audio_box,
|
||||||
} else {
|
simple_jail(&cfg, "null_audio_device.policy")?,
|
||||||
None
|
));
|
||||||
};
|
|
||||||
pci_devices.push((null_audio_box, null_audio_jail));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(pci_devices)
|
Ok(pci_devices)
|
||||||
|
|
Loading…
Reference in a new issue