vfs: dir_vnode_to_path(): Fix bug with chroot on mount

Simplify the code, which also fixes the bug that the I/O context's root
was ignored when it was a mount point, thus resulting in globally rooted
paths in this case.
This commit is contained in:
Ingo Weinhold
2013-11-10 15:43:43 +01:00
parent faf4ddb291
commit 18640f25d9
+22 -38
View File
@@ -2585,50 +2585,40 @@ dir_vnode_to_path(struct vnode* vnode, char* buffer, size_t bufferSize,
// efficient and does all we need from get_vnode()
inc_vnode_ref_count(vnode);
if (vnode != ioContext->root) {
// we don't hit the IO context root
// resolve a vnode to its covered vnode
if (Vnode* coveredVnode = get_covered_vnode(vnode)) {
put_vnode(vnode);
vnode = coveredVnode;
}
}
path[--insert] = '\0';
// the path is filled right to left
while (true) {
// the name buffer is also used for fs_read_dir()
char nameBuffer[sizeof(struct dirent) + B_FILE_NAME_LENGTH];
char* name = &((struct dirent*)nameBuffer)->d_name[0];
struct vnode* parentVnode;
// If the node is the context's root, bail out. Otherwise resolve mount
// points.
if (vnode == ioContext->root)
break;
if (Vnode* coveredVnode = get_covered_vnode(vnode)) {
put_vnode(vnode);
vnode = coveredVnode;
}
// lookup the parent vnode
if (vnode == ioContext->root) {
// we hit the IO context root
parentVnode = vnode;
inc_vnode_ref_count(vnode);
} else {
status = lookup_dir_entry(vnode, "..", &parentVnode);
if (status != B_OK)
goto out;
struct vnode* parentVnode;
status = lookup_dir_entry(vnode, "..", &parentVnode);
if (status != B_OK)
goto out;
if (parentVnode == vnode) {
// The caller apparently got their hands on a node outside of their
// context's root. Now we've hit the global root.
put_vnode(parentVnode);
break;
}
// get the node's name
char nameBuffer[sizeof(struct dirent) + B_FILE_NAME_LENGTH];
// also used for fs_read_dir()
char* name = &((struct dirent*)nameBuffer)->d_name[0];
status = get_vnode_name(vnode, parentVnode, (struct dirent*)nameBuffer,
sizeof(nameBuffer), ioContext);
if (vnode != ioContext->root) {
// we don't hit the IO context root
// resolve a vnode to its covered vnode
if (Vnode* coveredVnode = get_covered_vnode(parentVnode)) {
put_vnode(parentVnode);
parentVnode = coveredVnode;
}
}
bool hitRoot = (parentVnode == vnode);
// release the current vnode, we only need its parent from now on
put_vnode(vnode);
vnode = parentVnode;
@@ -2636,12 +2626,6 @@ dir_vnode_to_path(struct vnode* vnode, char* buffer, size_t bufferSize,
if (status != B_OK)
goto out;
if (hitRoot) {
// we have reached "/", which means we have constructed the full
// path
break;
}
// TODO: add an explicit check for loops in about 10 levels to do
// real loop detection