Fixed a bug in the VFS that could cause BFS to corrupt an inode:
dir_remove() did not normalize the path, and thus, could forward a "." as name for the removed directory - which BFS didn't catch because it assumed our VFS would work correctly... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17165 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -836,10 +836,9 @@ restart:
|
|||||||
mutex_unlock(&sVnodeMutex);
|
mutex_unlock(&sVnodeMutex);
|
||||||
|
|
||||||
status = FS_CALL(vnode, get_vnode)(vnode->mount->cookie, vnodeID, &vnode->private_node, reenter);
|
status = FS_CALL(vnode, get_vnode)(vnode->mount->cookie, vnodeID, &vnode->private_node, reenter);
|
||||||
if (status < B_OK || vnode->private_node == NULL) {
|
if (status == B_OK && vnode->private_node == NULL)
|
||||||
if (status == B_NO_ERROR)
|
status = B_BAD_VALUE;
|
||||||
status = B_BAD_VALUE;
|
|
||||||
}
|
|
||||||
mutex_lock(&sVnodeMutex);
|
mutex_lock(&sVnodeMutex);
|
||||||
|
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
@@ -3992,8 +3991,30 @@ dir_remove(int fd, char *path, bool kernel)
|
|||||||
struct vnode *directory;
|
struct vnode *directory;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
|
if (path != NULL) {
|
||||||
|
// we need to make sure our path name doesn't stop with "/", ".", or ".."
|
||||||
|
char *lastSlash = strrchr(path, '/');
|
||||||
|
if (lastSlash != NULL) {
|
||||||
|
char *leaf = lastSlash + 1;
|
||||||
|
if (!strcmp(leaf, ".."))
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
|
||||||
|
// omit multiple slashes
|
||||||
|
while (lastSlash > path && lastSlash[-1] == '/') {
|
||||||
|
lastSlash--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!leaf[0]
|
||||||
|
|| !strcmp(leaf, ".")) {
|
||||||
|
// "name/" -> "name", or "name/." -> "name"
|
||||||
|
lastSlash[0] = '\0';
|
||||||
|
}
|
||||||
|
} else if (!strcmp(path, ".."))
|
||||||
|
return B_NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
status = fd_and_path_to_dir_vnode(fd, path, &directory, name, kernel);
|
status = fd_and_path_to_dir_vnode(fd, path, &directory, name, kernel);
|
||||||
if (status < 0)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (FS_CALL(directory, remove_dir)) {
|
if (FS_CALL(directory, remove_dir)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user