1) Work correctly if HOME is not /home/user. 2) Support read-write rootfs correctly.

This commit is contained in:
Bruce Leidl 2019-09-23 15:22:47 -04:00
parent 6c25ccb226
commit df1c6a3cb3
2 changed files with 47 additions and 27 deletions

View File

@ -10,6 +10,7 @@ use std::io::Read;
pub struct InitServer { pub struct InitServer {
hostname: String, hostname: String,
homedir: String,
cmdline: CmdLine, cmdline: CmdLine,
rootfs: RootFS, rootfs: RootFS,
services: BTreeMap<u32, Service>, services: BTreeMap<u32, Service>,
@ -20,11 +21,14 @@ impl InitServer {
Self::check_pid1()?; Self::check_pid1()?;
let hostname = hostname.to_string(); let hostname = hostname.to_string();
let cmdline = CmdLine::load()?; let cmdline = CmdLine::load()?;
let homedir = cmdline.lookup("phinit.home")
.unwrap_or("/home/user".to_string());
let rootfs = RootFS::load(&cmdline)?; let rootfs = RootFS::load(&cmdline)?;
let services = BTreeMap::new(); let services = BTreeMap::new();
Ok(InitServer { Ok(InitServer {
hostname, hostname,
homedir,
cmdline, cmdline,
rootfs, rootfs,
services, services,
@ -54,6 +58,11 @@ impl InitServer {
} }
} }
fn homedir(&self) -> &str {
&self.homedir
}
pub fn set_loglevel(&self) { pub fn set_loglevel(&self) {
if self.cmdline.has_var("phinit.verbose") { if self.cmdline.has_var("phinit.verbose") {
Logger::set_log_level(LogLevel::Verbose); Logger::set_log_level(LogLevel::Verbose);
@ -90,10 +99,6 @@ impl InitServer {
mkdir("/run/user/1000")?; mkdir("/run/user/1000")?;
chown("/run/user/1000", 1000,1000)?; chown("/run/user/1000", 1000,1000)?;
if Path::new("/dev/wl0").exists() {
chmod("/dev/wl0", 0o666)?;
mkdir_mode("/tmp/.X11-unix", 0o1777)?;
}
self.mount_home_if_exists()?; self.mount_home_if_exists()?;
Logger::set_file_output("/run/phinit.log") Logger::set_file_output("/run/phinit.log")
.map_err(Error::OpenLogFailed)?; .map_err(Error::OpenLogFailed)?;
@ -150,11 +155,11 @@ impl InitServer {
pub fn mount_home_if_exists(&self) -> Result<()> { pub fn mount_home_if_exists(&self) -> Result<()> {
if self.has_9p_home() { if self.has_9p_home() {
let homedir = Path::new("/home/user"); let homedir = Path::new(self.homedir());
if !homedir.exists() { if !homedir.exists() {
mkdir(homedir)?; mkdir(homedir)?;
} }
mount_9p("home", "/home/user")?; mount_9p("home", self.homedir())?;
} }
Ok(()) Ok(())
} }
@ -169,7 +174,7 @@ impl InitServer {
let dbus = ServiceLaunch::new("dbus-daemon", "/usr/bin/dbus-daemon") let dbus = ServiceLaunch::new("dbus-daemon", "/usr/bin/dbus-daemon")
.base_environment() .base_environment()
.uidgid(1000,1000) .uidgid(1000,1000)
.env("HOME", "/home/user") .env("HOME", self.homedir())
.env("NO_AT_BRIDGE", "1") .env("NO_AT_BRIDGE", "1")
.env("QT_ACCESSIBILITY", "1") .env("QT_ACCESSIBILITY", "1")
.env("SHELL", "/bin/bash") .env("SHELL", "/bin/bash")
@ -215,7 +220,7 @@ impl InitServer {
.arg("-X") .arg("-X")
.arg("--x-display=0") .arg("--x-display=0")
.arg("--no-exit-with-child") .arg("--no-exit-with-child")
.arg("--x-auth=/home/user/.Xauthority") .arg(format!("--x-auth={}/.Xauthority", self.homedir()))
.arg("/bin/true") .arg("/bin/true")
.pipe_output() .pipe_output()
.launch()?; .launch()?;
@ -226,8 +231,8 @@ impl InitServer {
Ok(()) Ok(())
} }
fn write_xauth() -> io::Result<()> { fn write_xauth(&self) -> io::Result<()> {
let xauth_path = "/home/user/.Xauthority"; let xauth_path = format!("{}/.Xauthority", self.homedir());
let mut randbuf = [0; 16]; let mut randbuf = [0; 16];
let mut file = fs::File::open("/dev/urandom")?; let mut file = fs::File::open("/dev/urandom")?;
@ -250,20 +255,20 @@ impl InitServer {
v.extend_from_slice(&[0x00, 0x10]); v.extend_from_slice(&[0x00, 0x10]);
v.extend_from_slice(&randbuf); v.extend_from_slice(&randbuf);
fs::write("/home/user/.Xauthority", v)?; fs::write(&xauth_path, v)?;
_chown(xauth_path, 1000, 1000)?; _chown(&xauth_path, 1000, 1000)?;
Ok(()) Ok(())
} }
pub fn launch_console_shell(&mut self, splash: &'static str) -> Result<()> { pub fn launch_console_shell(&mut self, splash: &'static str) -> Result<()> {
let root = self.cmdline.has_var("phinit.rootshell"); let root = self.cmdline.has_var("phinit.rootshell");
let realm = self.cmdline.lookup("phinit.realm"); let realm = self.cmdline.lookup("phinit.realm");
let home = if root { "/" } else { "/home/user" }; let home = if root { "/".to_string() } else { self.homedir().to_string() };
let shell = ServiceLaunch::new_shell(root, home, realm) let shell = ServiceLaunch::new_shell(root, &home, realm)
.launch_with_preexec(move || { .launch_with_preexec(move || {
// set_controlling_tty(0, true)?; // set_controlling_tty(0, true)?;
env::set_current_dir(home)?; env::set_current_dir(&home)?;
println!("{}", splash); println!("{}", splash);
Ok(()) Ok(())
})?; })?;
@ -335,7 +340,10 @@ impl RootFS {
fn mount(&self, target: &str) -> Result<()> { fn mount(&self, target: &str) -> Result<()> {
let options = self.rootflags.as_ref().map(|s| s.as_str()); let options = self.rootflags.as_ref().map(|s| s.as_str());
let flags = libc::MS_RDONLY; let mut flags = libc::MS_NOATIME;
if self.readonly {
flags |= libc::MS_RDONLY;
}
mount(&self.root, target, &self.fstype, flags, options) mount(&self.root, target, &self.fstype, flags, options)
.map_err(|e| Error::RootFsMount(self.root.clone(), e)) .map_err(|e| Error::RootFsMount(self.root.clone(), e))

View File

@ -30,6 +30,7 @@ use std::sync::Arc;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use termios::Termios; use termios::Termios;
use crate::devices::SyntheticFS; use crate::devices::SyntheticFS;
use crate::disk::DiskImage;
pub struct Vm { pub struct Vm {
_config: VmConfig, _config: VmConfig,
@ -84,20 +85,34 @@ impl Vm {
devices::VirtioWayland::create(virtio)?; devices::VirtioWayland::create(virtio)?;
} }
let mut block_root = false; let homedir = config.homedir();
devices::VirtioP9::create(virtio, "home", homedir, false, false)?;
if homedir != "/home/user" {
cmdline.push_set_val("phinit.home", homedir);
}
let mut block_root = None;
for mut disk in config.get_realmfs_images() { for mut disk in config.get_realmfs_images() {
disk.open().map_err(ErrorKind::DiskImageOpen)?; disk.open().map_err(ErrorKind::DiskImageOpen)?;
if block_root == None {
block_root = Some(disk.read_only());
}
devices::VirtioBlock::create(virtio, disk)?; devices::VirtioBlock::create(virtio, disk)?;
block_root = true;
}
for mut disk in config.get_raw_disk_images() {
disk.open().map_err(ErrorKind::DiskImageOpen)?;
devices::VirtioBlock::create(virtio, disk)?;
block_root = true;
} }
if block_root { for mut disk in config.get_raw_disk_images() {
disk.open().map_err(ErrorKind::DiskImageOpen)?;
if block_root == None {
block_root = Some(disk.read_only());
}
devices::VirtioBlock::create(virtio, disk)?;
}
if let Some(read_only) = block_root {
if !read_only {
cmdline.push("phinit.root_rw");
}
cmdline.push("phinit.root=/dev/vda"); cmdline.push("phinit.root=/dev/vda");
cmdline.push("phinit.rootfstype=ext4"); cmdline.push("phinit.rootfstype=ext4");
} else { } else {
@ -171,9 +186,6 @@ impl Vm {
let mut virtio = VirtioBus::new(memory.clone(), io_dispatch.clone(), memory.kvm().clone()); let mut virtio = VirtioBus::new(memory.clone(), io_dispatch.clone(), memory.kvm().clone());
Self::setup_virtio(&mut config, &mut cmdline, &mut virtio)?; Self::setup_virtio(&mut config, &mut cmdline, &mut virtio)?;
if config.launch_systemd() {
cmdline.push("phinit.run_systemd");
}
if let Some(init_cmd) = config.get_init_cmdline() { if let Some(init_cmd) = config.get_init_cmdline() {
cmdline.push_set_val("init", init_cmd); cmdline.push_set_val("init", init_cmd);
} }