[starnix] Allow specifying ext4 or remotefs as the root in the cml
Change-Id: I397da01c63fab0b657692bad00cdb2ca5b0f7855
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/558968
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
Fuchsia-Auto-Submit: Theodore Dubois <tbodt@google.com>
Reviewed-by: Adam Barth <abarth@google.com>
diff --git a/src/proc/bin/starnix/runner.rs b/src/proc/bin/starnix/runner.rs
index 5d822e7..c939168 100644
--- a/src/proc/bin/starnix/runner.rs
+++ b/src/proc/bin/starnix/runner.rs
@@ -32,6 +32,7 @@
use crate::auth::Credentials;
use crate::fs::devfs::DevFs;
+use crate::fs::ext4::ExtFilesystem;
use crate::fs::fuchsia::{create_file_from_handle, RemoteFs};
use crate::fs::tmpfs::TmpFs;
use crate::fs::*;
@@ -41,7 +42,6 @@
use crate::syscalls::table::dispatch_syscall;
use crate::syscalls::*;
use crate::task::*;
-use crate::types::*;
// TODO: Should we move this code into fuchsia_zircon? It seems like part of a better abstraction
// for exception channels.
@@ -205,7 +205,37 @@
Ok(files)
}
-async fn start_component(
+fn create_filesystem_from_spec<'a>(
+ pkg: &fio::DirectorySynchronousProxy,
+ spec: &'a str,
+) -> Result<(&'a [u8], FileSystemHandle), Error> {
+ let mut iter = spec.splitn(3, ':');
+ let mount_point =
+ iter.next().ok_or_else(|| anyhow!("mount point is missing from {:?}", spec))?;
+ let fs_type = iter.next().ok_or_else(|| anyhow!("fs type is missing from {:?}", spec))?;
+ let fs_path = iter.next();
+ let fs = match fs_type {
+ "tmpfs" => TmpFs::new(),
+ "devfs" => DevFs::new(),
+ "remotefs" => {
+ let fs_path = fs_path.ok_or_else(|| anyhow!("remotefs requires specifying a path"))?;
+ let rights = fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_EXECUTABLE;
+ let root = syncio::directory_open_directory_async(&pkg, &fs_path, rights)
+ .map_err(|e| anyhow!("Failed to open root: {}", e))?;
+ RemoteFs::new(root.into_channel(), rights)
+ }
+ "ext4" => {
+ let fs_path = fs_path.ok_or_else(|| anyhow!("ext4 requires specifying a path"))?;
+ let vmo =
+ syncio::directory_open_vmo(&pkg, &fs_path, fio::VMO_FLAG_READ, zx::Time::INFINITE)?;
+ ExtFilesystem::new(vmo)?
+ }
+ _ => anyhow::bail!("invalid fs type {:?}", fs_type),
+ };
+ Ok((mount_point.as_bytes(), fs))
+}
+
+fn start_component(
kernel: Arc<Kernel>,
start_info: ComponentStartInfo,
controller: ServerEnd<ComponentControllerMarker>,
@@ -216,33 +246,22 @@
start_info.numbered_handles,
);
- let root_path = runner::get_program_string(&start_info, "root")
- .ok_or_else(|| anyhow!("No root in component manifest"))?
- .to_owned();
+ let mounts =
+ runner::get_program_strvec(&start_info, "mounts").map(|a| a.clone()).unwrap_or(vec![]);
let binary_path = CString::new(runner::get_program_binary(&start_info)?)?;
-
let args = runner::get_program_strvec(&start_info, "args")
.map(|args| {
args.iter().map(|arg| CString::new(arg.clone())).collect::<Result<Vec<CString>, _>>()
})
.unwrap_or(Ok(vec![]))?;
- let mount = runner::get_program_strvec(&start_info, "mount")
- .map(|mounts| {
- mounts
- .iter()
- .map(|mount| CString::new(mount.clone()))
- .collect::<Result<Vec<CString>, _>>()
- })
- .unwrap_or(Ok(vec![]))?;
-
- let user_passwd = runner::get_program_string(&start_info, "user").unwrap_or("fuchsia:x:42:42");
- let credentials = Credentials::from_passwd(user_passwd)?;
-
let environ = runner::get_program_strvec(&start_info, "environ")
.map(|args| {
args.iter().map(|arg| CString::new(arg.clone())).collect::<Result<Vec<CString>, _>>()
})
.unwrap_or(Ok(vec![]))?;
+ let user_passwd = runner::get_program_string(&start_info, "user").unwrap_or("fuchsia:x:42:42");
+ let credentials = Credentials::from_passwd(user_passwd)?;
+
info!("start_component environment: {:?}", environ);
let ns = start_info.ns.ok_or_else(|| anyhow!("Missing namespace"))?;
@@ -255,37 +274,26 @@
.ok_or_else(|| anyhow!("Missing directory handlee in pkg namespace entry"))?
.into_channel(),
);
- let root = syncio::directory_open_directory_async(
+
+ // The mounts are appplied in the order listed. Mounting will fail if the designated mount
+ // point doesn't exist in a previous mount. The root must be first so other mounts can be
+ // applied on top of it.
+ let mut mounts_iter = mounts.iter();
+ let (root_point, root_fs) = create_filesystem_from_spec(
&pkg,
- &root_path,
- fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_EXECUTABLE,
- )
- .map_err(|e| anyhow!("Failed to open root: {}", e))?;
-
- let files = files_from_numbered_handles(start_info.numbered_handles, &kernel)?;
-
- let remotefs =
- RemoteFs::new(root.into_channel(), fio::OPEN_RIGHT_READABLE | fio::OPEN_RIGHT_EXECUTABLE);
-
- let fs = FsContext::new(remotefs);
- for mnt in mount {
- let mut field_iter = mnt.as_bytes().splitn(2, |c| *c == b':');
- let mut mount_point =
- field_iter.next().ok_or_else(|| anyhow!("mount point is missing from {:?}", mnt))?;
- if mount_point.len() > 0 && mount_point[0] == b'/' {
- mount_point = &mount_point[1..];
- }
- let fs_type =
- field_iter.next().ok_or_else(|| anyhow!("fs type is missing from {:?}", mnt))?;
- let child_fs = match fs_type {
- b"tmpfs" => Ok(TmpFs::new()),
- b"devfs" => Ok(DevFs::new()),
- _ => Err(EINVAL),
- }?;
-
+ mounts_iter.next().ok_or_else(|| anyhow!("Mounts list is empty"))?,
+ )?;
+ if root_point != b"/" {
+ anyhow::bail!("First mount in mounts list is not the root");
+ }
+ let fs = FsContext::new(root_fs);
+ for mount_spec in mounts_iter {
+ let (mount_point, child_fs) = create_filesystem_from_spec(&pkg, mount_spec)?;
fs.lookup_node(fs.root.clone(), mount_point)?.mount(child_fs)?;
}
+ let files = files_from_numbered_handles(start_info.numbered_handles, &kernel)?;
+
let task_owner = Task::create_process(&kernel, &binary_path, 0, files, fs, credentials, None)?;
let mut argv = vec![binary_path];
@@ -319,7 +327,7 @@
fcrunner::ComponentRunnerRequest::Start { start_info, controller, .. } => {
let kernel = kernel.clone();
fasync::Task::local(async move {
- if let Err(e) = start_component(kernel, start_info, controller).await {
+ if let Err(e) = start_component(kernel, start_info, controller) {
error!("failed to start component: {}", e);
}
})
diff --git a/src/proc/tests/android/BUILD.gn b/src/proc/tests/android/BUILD.gn
index bfa8eac..89328a2 100644
--- a/src/proc/tests/android/BUILD.gn
+++ b/src/proc/tests/android/BUILD.gn
@@ -60,6 +60,11 @@
subdir = "root"
}
+resource("android_system_image_ext") {
+ sources = [ "//prebuilt/starnix/android-image-amd64/system.img" ]
+ outputs = [ "data/system.img" ]
+}
+
fuchsia_component("init") {
manifest = "meta/init.cml"
}
@@ -187,6 +192,7 @@
fuchsia_test_package("test_android_distro") {
deps = [
":android_system_image",
+ ":android_system_image_ext",
":init",
":sh",
":syscalls_test",
diff --git a/src/proc/tests/android/meta/access_test.cml b/src/proc/tests/android/meta/access_test.cml
index 6de9185..aa9d0f1 100644
--- a/src/proc/tests/android/meta/access_test.cml
+++ b/src/proc/tests/android/meta/access_test.cml
@@ -3,7 +3,9 @@
program: {
binary: "system/bin/access_test",
args: [ "--gunit_filter=*.RelativeFile:*.RelativeDir:*.AbsFile:*.AbsDir:*.RelDoesNotExist:*.AbsDoesNotExist:*.InvalidMode:*.InvalidName:*.UsrReadWrite:*.UsrReadWriteExec" ],
- root: "root",
- mount: [ "/tmp:tmpfs" ],
+ mounts: [
+ "/:remotefs:root",
+ "/tmp:tmpfs",
+ ],
},
}
diff --git a/src/proc/tests/android/meta/brk_test.cml b/src/proc/tests/android/meta/brk_test.cml
index 8490ca1..72fa6a0 100644
--- a/src/proc/tests/android/meta/brk_test.cml
+++ b/src/proc/tests/android/meta/brk_test.cml
@@ -2,6 +2,6 @@
include: [ "//src/sys/test_runners/starnix/default.shard.cml" ],
program: {
binary: "system/bin/brk_test",
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/clock_getres_test.cml b/src/proc/tests/android/meta/clock_getres_test.cml
index 711acdb..bf1b79f 100644
--- a/src/proc/tests/android/meta/clock_getres_test.cml
+++ b/src/proc/tests/android/meta/clock_getres_test.cml
@@ -3,6 +3,6 @@
program: {
binary: "system/bin/clock_getres_test",
environ: [ "TEST_ON_GVISOR=1" ],
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/clock_gettime_test.cml b/src/proc/tests/android/meta/clock_gettime_test.cml
index 053e082..1886795 100644
--- a/src/proc/tests/android/meta/clock_gettime_test.cml
+++ b/src/proc/tests/android/meta/clock_gettime_test.cml
@@ -4,6 +4,6 @@
binary: "system/bin/clock_gettime_test",
args: [ "--gunit_filter=-ClockGettime.JavaThreadTime:ClockGettime/MonotonicClockTest.IsMonotonic*" ],
environ: [ "TEST_ON_GVISOR=1" ],
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/exit_test.cml b/src/proc/tests/android/meta/exit_test.cml
index ec9cff7..696d904c 100644
--- a/src/proc/tests/android/meta/exit_test.cml
+++ b/src/proc/tests/android/meta/exit_test.cml
@@ -2,6 +2,6 @@
include: [ "//src/sys/test_runners/starnix/default.shard.cml" ],
program: {
binary: "system/bin/exit_test",
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/fork_test.cml b/src/proc/tests/android/meta/fork_test.cml
index dfcd50c..6f9e4a6 100644
--- a/src/proc/tests/android/meta/fork_test.cml
+++ b/src/proc/tests/android/meta/fork_test.cml
@@ -3,6 +3,6 @@
program: {
binary: "system/bin/fork_test",
args: [ "--gunit_filter=ForkTest.*:-*.Alarm" ],
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/getrandom_test.cml b/src/proc/tests/android/meta/getrandom_test.cml
index 906263e..7635321 100644
--- a/src/proc/tests/android/meta/getrandom_test.cml
+++ b/src/proc/tests/android/meta/getrandom_test.cml
@@ -2,6 +2,6 @@
include: [ "//src/sys/test_runners/starnix/default.shard.cml" ],
program: {
binary: "system/bin/getrandom_test",
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/init.cml b/src/proc/tests/android/meta/init.cml
index 1cb3287..ace0f8c 100644
--- a/src/proc/tests/android/meta/init.cml
+++ b/src/proc/tests/android/meta/init.cml
@@ -1,7 +1,10 @@
{
program: {
runner: "starnix",
- binary: "system/bin/hello_world",
- root: "root",
+ binary: "system/bin/init",
+ mounts: [
+ "/:ext4:data/system.img",
+ "/dev:tmpfs",
+ ],
},
}
diff --git a/src/proc/tests/android/meta/kill_test.cml b/src/proc/tests/android/meta/kill_test.cml
index 8c0f927..b65b09c 100644
--- a/src/proc/tests/android/meta/kill_test.cml
+++ b/src/proc/tests/android/meta/kill_test.cml
@@ -4,6 +4,6 @@
binary: "system/bin/kill_test",
args: [ "--gunit_filter=KillTest.CanKillAllPIDs:KillTest.CannotKillInvalidPID:KillTest.CannotKillTid" ],
environ: [ "TEST_ON_GVISOR=1" ],
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/lseek_test.cml b/src/proc/tests/android/meta/lseek_test.cml
index da51a85..92916d3 100644
--- a/src/proc/tests/android/meta/lseek_test.cml
+++ b/src/proc/tests/android/meta/lseek_test.cml
@@ -3,7 +3,10 @@
program: {
binary: "system/bin/lseek_test",
args: [ "--gunit_filter=-*.DirCurEnd:*.Proc*:*.SysDir:*.SeekCurrentDir:*.EtcPasswdDup" ],
- root: "root",
- mount: [ "/tmp:tmpfs" ],
+ args: [ "--gunit_filter=-*.Overflow:*.DirCurEnd:*.Proc*:*.SysDir:*.SeekCurrentDir:*.EtcPasswdDup" ],
+ mounts: [
+ "/:remotefs:root",
+ "/tmp:tmpfs",
+ ],
},
}
diff --git a/src/proc/tests/android/meta/munmap_test.cml b/src/proc/tests/android/meta/munmap_test.cml
index 83b56e6..31dc7bb 100644
--- a/src/proc/tests/android/meta/munmap_test.cml
+++ b/src/proc/tests/android/meta/munmap_test.cml
@@ -2,6 +2,6 @@
include: [ "//src/sys/test_runners/starnix/default.shard.cml" ],
program: {
binary: "system/bin/munmap_test",
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/pipe_test.cml b/src/proc/tests/android/meta/pipe_test.cml
index 552fbb8..324a864 100644
--- a/src/proc/tests/android/meta/pipe_test.cml
+++ b/src/proc/tests/android/meta/pipe_test.cml
@@ -3,7 +3,9 @@
program: {
binary: "system/bin/pipe_test",
args: [ "--gunit_filter=-*Proc*:*StatFS*:*.Flags/named*" ],
- root: "root",
- mount: [ "/tmp:tmpfs" ],
+ mounts: [
+ "/:remotefs:root",
+ "/tmp:tmpfs",
+ ],
},
}
diff --git a/src/proc/tests/android/meta/sh.cml b/src/proc/tests/android/meta/sh.cml
index 0ec7628..68111b7 100644
--- a/src/proc/tests/android/meta/sh.cml
+++ b/src/proc/tests/android/meta/sh.cml
@@ -3,6 +3,6 @@
runner: "starnix",
binary: "system/bin/sh",
args: [ "-i" ],
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/sh_test.cml b/src/proc/tests/android/meta/sh_test.cml
index 6e8889b..0755284 100644
--- a/src/proc/tests/android/meta/sh_test.cml
+++ b/src/proc/tests/android/meta/sh_test.cml
@@ -2,6 +2,6 @@
include: [ "//src/sys/test_runners/starnix/default.shard.cml" ],
program: {
binary: "system/bin/sh",
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/sigaction_test.cml b/src/proc/tests/android/meta/sigaction_test.cml
index 499dc48..9e7657d 100644
--- a/src/proc/tests/android/meta/sigaction_test.cml
+++ b/src/proc/tests/android/meta/sigaction_test.cml
@@ -2,6 +2,6 @@
include: [ "//src/sys/test_runners/starnix/default.shard.cml" ],
program: {
binary: "system/bin/sigaction_test",
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/sigaltstack_test.cml b/src/proc/tests/android/meta/sigaltstack_test.cml
index bfe59c6..5eaa113 100644
--- a/src/proc/tests/android/meta/sigaltstack_test.cml
+++ b/src/proc/tests/android/meta/sigaltstack_test.cml
@@ -3,6 +3,6 @@
program: {
binary: "system/bin/sigaltstack_test",
args: [ "--gunit_filter=SigaltstackTest.Success" ],
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/sigprocmask_test.cml b/src/proc/tests/android/meta/sigprocmask_test.cml
index ef9db1e..990a841 100644
--- a/src/proc/tests/android/meta/sigprocmask_test.cml
+++ b/src/proc/tests/android/meta/sigprocmask_test.cml
@@ -2,6 +2,6 @@
include: [ "//src/sys/test_runners/starnix/default.shard.cml" ],
program: {
binary: "system/bin/sigprocmask_test",
- root: "root",
+ mounts: [ "/:remotefs:root" ],
},
}
diff --git a/src/proc/tests/android/meta/symlink_test.cml b/src/proc/tests/android/meta/symlink_test.cml
index 4b1c21c..ba1ff6c 100644
--- a/src/proc/tests/android/meta/symlink_test.cml
+++ b/src/proc/tests/android/meta/symlink_test.cml
@@ -3,7 +3,9 @@
program: {
binary: "system/bin/symlink_test",
args: [ "--gunit_filter=-SymlinkTest.CannotCreateSymlinkInReadOnlyDir:SymlinkTest.SymlinkAtDegradedPermissions:SymlinkTest.ReadlinkAtDegradedPermissions:AbsAndRelTarget/ParamSymlinkTest*" ],
- root: "root",
- mount: [ "/tmp:tmpfs" ],
+ mounts: [
+ "/:remotefs:root",
+ "/tmp:tmpfs",
+ ],
},
}
diff --git a/src/proc/tests/android/meta/syscalls_test.cml b/src/proc/tests/android/meta/syscalls_test.cml
index d7e8845..7f13c3f 100644
--- a/src/proc/tests/android/meta/syscalls_test.cml
+++ b/src/proc/tests/android/meta/syscalls_test.cml
@@ -2,8 +2,8 @@
include: [ "//src/sys/test_runners/starnix/default.shard.cml" ],
program: {
binary: "system/bin/syscalls_test",
- root: "root",
- mount: [
+ mounts: [
+ "/:remotefs:root",
"/data:tmpfs",
"/tmp:tmpfs",
],
diff --git a/src/proc/tests/hello_starnix/meta/hello_starnix.cml b/src/proc/tests/hello_starnix/meta/hello_starnix.cml
index 7881d45..69c9e5b 100644
--- a/src/proc/tests/hello_starnix/meta/hello_starnix.cml
+++ b/src/proc/tests/hello_starnix/meta/hello_starnix.cml
@@ -2,6 +2,6 @@
program: {
runner: "starnix",
binary: "hello_starnix",
- root: "bin",
+ mounts: [ "/:remotefs:bin" ],
},
}
diff --git a/src/proc/tests/hello_starnix/meta/hello_starnix_test.cml b/src/proc/tests/hello_starnix/meta/hello_starnix_test.cml
index 4300ba4..87c3c68 100644
--- a/src/proc/tests/hello_starnix/meta/hello_starnix_test.cml
+++ b/src/proc/tests/hello_starnix/meta/hello_starnix_test.cml
@@ -2,6 +2,6 @@
include: [ "//src/sys/test_runners/starnix/default.shard.cml" ],
program: {
binary: "bin/hello_starnix",
- root: "",
+ mounts: [ "/:remotefs:/" ],
},
}