diff --git a/kernel/src/fs/fs_resolver.rs b/kernel/src/fs/fs_resolver.rs index 987cec1f4..5db9f5df5 100644 --- a/kernel/src/fs/fs_resolver.rs +++ b/kernel/src/fs/fs_resolver.rs @@ -56,6 +56,9 @@ impl FsResolver { /// /// Otherwise, the method will change both the `cwd` and `root` to their corresponding /// `Path`s within the new `MountNamespace`. + // + // FIXME: This cannot fail if we clone mount namespaces and update resolvers in an atomic way. + // We currently leak this error to userspace, which is not a correct behavior. pub fn switch_to_mnt_ns(&mut self, mnt_ns: &Arc) -> Result<()> { if mnt_ns.owns(self.root.mount_node()) && mnt_ns.owns(self.cwd.mount_node()) { return Ok(()); diff --git a/kernel/src/process/namespace/nsproxy.rs b/kernel/src/process/namespace/nsproxy.rs index d55c2d8d3..5c1504e34 100644 --- a/kernel/src/process/namespace/nsproxy.rs +++ b/kernel/src/process/namespace/nsproxy.rs @@ -169,7 +169,9 @@ impl ContextSetNsAdminApi for Context<'_> { // TODO: When setting a specific namespace, // other dependent fields of a posix thread may also need to be updated. - *self.thread_local.borrow_fs().resolver().write() = ns_proxy.mnt_ns.new_fs_resolver(); + if !Arc::ptr_eq(&thread_local_ns_proxy.unwrap().mnt_ns, &ns_proxy.mnt_ns) { + *self.thread_local.borrow_fs().resolver().write() = ns_proxy.mnt_ns.new_fs_resolver(); + } *pthread_ns_proxy = Some(ns_proxy.clone()); thread_local_ns_proxy.replace(Some(ns_proxy)); diff --git a/kernel/src/process/namespace/unshare.rs b/kernel/src/process/namespace/unshare.rs index beaca65b2..366013fa0 100644 --- a/kernel/src/process/namespace/unshare.rs +++ b/kernel/src/process/namespace/unshare.rs @@ -63,8 +63,7 @@ impl ContextUnshareAdminApi for Context<'_> { .borrow_fs() .resolver() .write() - .switch_to_mnt_ns(new_ns_proxy.mnt_ns()) - .unwrap(); + .switch_to_mnt_ns(new_ns_proxy.mnt_ns())?; } *pthread_ns_proxy = Some(new_ns_proxy.clone()); diff --git a/test/src/apps/namespace/mnt_ns.c b/test/src/apps/namespace/mnt_ns.c index 4cd0e8945..329824244 100644 --- a/test/src/apps/namespace/mnt_ns.c +++ b/test/src/apps/namespace/mnt_ns.c @@ -2,15 +2,9 @@ #define _GNU_SOURCE #include -#include -#include #include -#include #include -#include #include -#include -#include #include #include "../test.h" @@ -168,14 +162,21 @@ FN_TEST(setns_newns) close(pipefd[1]); - char buf; + char buf[10]; TEST_SUCC(read(pipefd[0], &buf, 1)); close(pipefd[0]); int pid_fd = TEST_SUCC(syscall(SYS_pidfd_open, child_pid, 0)); - // Switch into the child's mount namespace using the pidfd. + // Switching into the child's UTS namespace will not change the CWD. + TEST_SUCC(chdir("/mnt")); + TEST_SUCC(setns(pid_fd, CLONE_NEWUTS)); + TEST_RES(getcwd(buf, sizeof(buf)), strcmp(buf, "/mnt") == 0); + + // Switching into the child's mount namespace will reset the CWD. TEST_SUCC(setns(pid_fd, CLONE_NEWNS)); + TEST_RES(getcwd(buf, sizeof(buf)), strcmp(buf, "/") == 0); + TEST_SUCC(close(pid_fd)); // Check if we can see the file created by the child in its namespace. @@ -188,4 +189,4 @@ FN_TEST(setns_newns) TEST_SUCC(umount(SETNS_MNT)); TEST_SUCC(rmdir(SETNS_MNT)); } -END_TEST() \ No newline at end of file +END_TEST() diff --git a/test/src/apps/scripts/process.sh b/test/src/apps/scripts/process.sh index 3792eec89..408a799b2 100755 --- a/test/src/apps/scripts/process.sh +++ b/test/src/apps/scripts/process.sh @@ -34,7 +34,7 @@ mmap/mmap_beyond_the_file mmap/mmap_shared_filebacked mmap/mmap_readahead mmap/mmap_vmrss -namepsace/mnt_ns +namespace/mnt_ns namespace/setns namespace/unshare process/group_session