Fix some mount-related bugs
This commit is contained in:
parent
8096249765
commit
6df2af2e17
|
|
@ -101,16 +101,18 @@ impl Dentry {
|
|||
DentryFlags::from_bits(flags).unwrap()
|
||||
}
|
||||
|
||||
/// Checks if this dentry is a descendant (child, grandchild, or
|
||||
/// great-grandchild, etc.) of another dentry.
|
||||
pub(super) fn is_descendant_of(&self, ancestor: &Arc<Self>) -> bool {
|
||||
let mut parent = self.parent();
|
||||
while let Some(p) = parent {
|
||||
if Arc::ptr_eq(&p, ancestor) {
|
||||
/// Checks if this dentry is a descendant of or the same as the given
|
||||
/// ancestor dentry.
|
||||
pub(super) fn is_equal_or_descendant_of(&self, ancestor: &Arc<Self>) -> bool {
|
||||
let mut current = Some(self.this());
|
||||
|
||||
while let Some(node) = current {
|
||||
if Arc::ptr_eq(&node, ancestor) {
|
||||
return true;
|
||||
}
|
||||
parent = p.parent();
|
||||
current = node.parent();
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ impl Mount {
|
|||
let old_children = old_mount.children.read();
|
||||
for old_child_mount in old_children.values() {
|
||||
let mountpoint = old_child_mount.mountpoint().unwrap();
|
||||
if !mountpoint.is_descendant_of(root_dentry) {
|
||||
if !mountpoint.is_equal_or_descendant_of(old_mount.root_dentry()) {
|
||||
continue;
|
||||
}
|
||||
let new_child_mount =
|
||||
|
|
|
|||
|
|
@ -190,3 +190,71 @@ FN_TEST(setns_newns)
|
|||
TEST_SUCC(rmdir(SETNS_MNT));
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
#define COMPLEX_BASE "/test0"
|
||||
#define COMPLEX_CONTENT "/test0/content"
|
||||
#define COMPLEX_FILE "/test0/content/hello.txt"
|
||||
|
||||
FN_TEST(complex_mount_tree_unshare)
|
||||
{
|
||||
// Setup: Create directory structure
|
||||
CHECK_WITH(mkdir(COMPLEX_BASE, 0755), _ret >= 0 || errno == EEXIST);
|
||||
|
||||
// Mount tmpfs on test0 (first layer)
|
||||
TEST_SUCC(mount("none", COMPLEX_BASE, "tmpfs", 0, ""));
|
||||
|
||||
// Mount tmpfs on test0 again (second layer, stacked mount)
|
||||
TEST_SUCC(mount("none", COMPLEX_BASE, "tmpfs", 0, ""));
|
||||
|
||||
// Recreate content directory on the new mount
|
||||
TEST_SUCC(mkdir(COMPLEX_CONTENT, 0755));
|
||||
|
||||
// Mount tmpfs on test0/content (third layer)
|
||||
TEST_SUCC(mount("none", COMPLEX_CONTENT, "tmpfs", 0, ""));
|
||||
|
||||
// Create file with content
|
||||
int fd = TEST_SUCC(open(COMPLEX_FILE, O_CREAT | O_WRONLY, 0644));
|
||||
TEST_SUCC(write(fd, "hello world\n", 12));
|
||||
TEST_SUCC(close(fd));
|
||||
|
||||
// Verify file exists in parent
|
||||
TEST_SUCC(access(COMPLEX_FILE, F_OK));
|
||||
|
||||
// Fork and unshare in child
|
||||
pid_t pid = TEST_SUCC(fork());
|
||||
|
||||
if (pid == 0) {
|
||||
TEST_SUCC(unshare(CLONE_NEWNS));
|
||||
|
||||
// Try to read the file created in the parent's mount tree
|
||||
int fd = CHECK(open(COMPLEX_FILE, O_RDONLY));
|
||||
|
||||
char buf[32] = { 0 };
|
||||
TEST_SUCC(read(fd, buf, sizeof(buf) - 1));
|
||||
TEST_SUCC(close(fd));
|
||||
|
||||
// Verify the content
|
||||
CHECK_WITH(strcmp(buf, "hello world\n"), _ret == 0);
|
||||
|
||||
// Verify we can still access the nested mount structure
|
||||
TEST_SUCC(access(COMPLEX_CONTENT, F_OK));
|
||||
TEST_SUCC(access(COMPLEX_BASE, F_OK));
|
||||
|
||||
exit(0);
|
||||
} else {
|
||||
int status;
|
||||
TEST_SUCC(waitpid(pid, &status, 0));
|
||||
TEST_RES(WIFEXITED(status) && WEXITSTATUS(status), _ret == 0);
|
||||
|
||||
// Verify parent's mount tree is unchanged
|
||||
TEST_SUCC(access(COMPLEX_FILE, F_OK));
|
||||
|
||||
// Teardown: Unmount in reverse order
|
||||
TEST_SUCC(umount(COMPLEX_CONTENT));
|
||||
TEST_SUCC(rmdir(COMPLEX_CONTENT));
|
||||
TEST_SUCC(umount(COMPLEX_BASE));
|
||||
TEST_SUCC(umount(COMPLEX_BASE));
|
||||
TEST_SUCC(rmdir(COMPLEX_BASE));
|
||||
}
|
||||
}
|
||||
END_TEST()
|
||||
Loading…
Reference in New Issue