From ed5c4d8a2d2a437d9001cdebdf09ad1246e930eb Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 10 Mar 2025 23:30:07 -0400 Subject: [PATCH] file_systems: Add O_DIRECTORY checks to many filesystems that were missing them. This doesn't get all the filesystems that were missing these checks (e.g. I didn't adjust the more "WIP" filesystems like XFS and BTRFS) but it does get most of them. --- src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp | 4 +++- src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp | 2 ++ src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp | 5 +++++ src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp | 5 +++++ .../kernel/file_systems/packagefs/kernel_interface.cpp | 2 ++ src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp | 4 +++- 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp b/src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp index c5e3c95765..fdb52bb041 100644 --- a/src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/exfat/kernel_interface.cpp @@ -461,8 +461,10 @@ exfat_open(fs_volume* /*_volume*/, fs_vnode* _node, int openMode, // any data from it. if (inode->IsDirectory() && (openMode & O_RWMASK) != 0) return B_IS_A_DIRECTORY; + if ((openMode & O_DIRECTORY) != 0 && !inode->IsDirectory()) + return B_NOT_A_DIRECTORY; - status_t status = inode->CheckPermissions(open_mode_to_access(openMode)); + status_t status = inode->CheckPermissions(open_mode_to_access(openMode)); if (status != B_OK) return status; diff --git a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp index 6454357797..57819e933c 100644 --- a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp @@ -1147,6 +1147,8 @@ ext2_open(fs_volume* _volume, fs_vnode* _node, int openMode, void** _cookie) // any data from it. if (inode->IsDirectory() && (openMode & O_RWMASK) != 0) return B_IS_A_DIRECTORY; + if ((openMode & O_DIRECTORY) != 0 && !inode->IsDirectory()) + return B_NOT_A_DIRECTORY; status_t status = inode->CheckPermissions(open_mode_to_access(openMode)); if (status != B_OK) diff --git a/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp b/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp index 4d740bbfb1..a33c0f88ba 100644 --- a/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/iso9660/kernel_interface.cpp @@ -511,11 +511,16 @@ fs_read_stat(fs_volume* _volume, fs_vnode* _node, struct stat* st) static status_t fs_open(fs_volume* /*_volume*/, fs_vnode* _node, int openMode, void** /*cookie*/) { + iso9660_inode* node = (iso9660_inode*)_node->private_node; + // Do not allow any of the write-like open modes to get by if ((openMode & O_RWMASK) == O_WRONLY || (openMode & O_RWMASK) == O_RDWR || (openMode & O_TRUNC) != 0 || (openMode & O_CREAT) != 0) return EROFS; + if ((openMode & O_DIRECTORY) != 0 && (node->flags & ISO_IS_DIR) == 0) + return B_NOT_A_DIRECTORY; + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp index 0668c0920c..f0d71d47fd 100644 --- a/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/kernel_interface.cpp @@ -838,6 +838,11 @@ nfs4_open(fs_volume* volume, fs_vnode* vnode, int openMode, void** _cookie) if (inode == NULL) return B_ENTRY_NOT_FOUND; + if (inode->Type() == S_IFDIR && (openMode & O_RWMASK) != O_RDONLY) + return B_IS_A_DIRECTORY; + if ((openMode & O_DIRECTORY) != 0 && inode->Type() != S_IFDIR) + return B_NOT_A_DIRECTORY; + if (inode->Type() == S_IFDIR || inode->Type() == S_IFLNK) { *_cookie = NULL; return B_OK; diff --git a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp index 946c29b1b7..b4b0f68583 100644 --- a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp @@ -423,6 +423,8 @@ packagefs_open(fs_volume* fsVolume, fs_vnode* fsNode, int openMode, // check the open mode and permissions if (S_ISDIR(node->Mode()) && (openMode & O_RWMASK) != O_RDONLY) return B_IS_A_DIRECTORY; + if ((openMode & O_DIRECTORY) != 0 && !S_ISDIR(node->Mode())) + return B_NOT_A_DIRECTORY; if ((openMode & O_RWMASK) != O_RDONLY) return B_NOT_ALLOWED; diff --git a/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp index c44460f05b..bd18e7337d 100644 --- a/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ufs2/kernel_interface.cpp @@ -263,8 +263,10 @@ ufs2_open(fs_volume * _volume, fs_vnode *_node, int openMode, // opening a directory read-only is allowed, although you can't read // any data from it. - if (inode->IsDirectory() && (openMode & O_RWMASK) != 0) + if (inode->IsDirectory() && (openMode & O_RWMASK) != O_RDONLY) return B_IS_A_DIRECTORY; + if ((openMode & O_DIRECTORY) != 0 && !inode->IsDirectory()) + return B_NOT_A_DIRECTORY; status_t status = inode->CheckPermissions(open_mode_to_access(openMode) | (openMode & O_TRUNC ? W_OK : 0));