From 4827dbe47a1ae3d3153ca6ec5bfe86b7febd1506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 18 Apr 2006 17:40:27 +0000 Subject: [PATCH] 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 --- src/system/kernel/fs/vfs.cpp | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 6c93ca9e84..8aeac98a01 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -836,10 +836,9 @@ restart: mutex_unlock(&sVnodeMutex); 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_NO_ERROR) - status = B_BAD_VALUE; - } + if (status == B_OK && vnode->private_node == NULL) + status = B_BAD_VALUE; + mutex_lock(&sVnodeMutex); if (status < B_OK) @@ -3992,8 +3991,30 @@ dir_remove(int fd, char *path, bool kernel) struct vnode *directory; 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); - if (status < 0) + if (status < B_OK) return status; if (FS_CALL(directory, remove_dir)) {