diff --git a/headers/os/drivers/fs_interface.h b/headers/os/drivers/fs_interface.h index 1b3f0be8f7..2aa195d357 100644 --- a/headers/os/drivers/fs_interface.h +++ b/headers/os/drivers/fs_interface.h @@ -1,10 +1,11 @@ /* - * Copyright 2004-2010, Haiku Inc. All Rights Reserved. + * Copyright 2004-2014, Haiku Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _FS_INTERFACE_H #define _FS_INTERFACE_H + /*! File System Interface Layer Definition */ @@ -330,6 +331,8 @@ extern status_t unremove_vnode(fs_volume* volume, ino_t vnodeID); extern status_t get_vnode_removed(fs_volume* volume, ino_t vnodeID, bool* _removed); extern fs_volume* volume_for_vnode(fs_vnode* vnode); +extern status_t check_access_permissions(int accessMode, mode_t mode, + gid_t nodeGroupID, uid_t nodeUserID); extern status_t read_pages(int fd, off_t pos, const struct iovec* vecs, size_t count, size_t* _numBytes); diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index 4bab2972c3..db2d98ffd0 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -506,37 +506,8 @@ Inode::CheckPermissions(int accessMode) const if ((accessMode & W_OK) != 0 && fVolume->IsReadOnly()) return B_READ_ONLY_DEVICE; - // get node permissions - mode_t mode = Mode(); - int userPermissions = (mode & S_IRWXU) >> 6; - int groupPermissions = (mode & S_IRWXG) >> 3; - int otherPermissions = mode & S_IRWXO; - - // get the node permissions for this uid/gid - int permissions = 0; - uid_t uid = geteuid(); - gid_t gid = getegid(); - - if (uid == 0) { - // user is root - // root has always read/write permission, but at least one of the - // X bits must be set for execute permission - permissions = userPermissions | groupPermissions | otherPermissions - | R_OK | W_OK; - if (IsDirectory()) - permissions |= X_OK; - } else if (uid == (uid_t)fNode.UserID()) { - // user is node owner - permissions = userPermissions; - } else if (gid == (gid_t)fNode.GroupID()) { - // user is in owning group - permissions = groupPermissions; - } else { - // user is one of the others - permissions = otherPermissions; - } - - return (accessMode & ~permissions) == 0 ? B_OK : B_NOT_ALLOWED; + return check_access_permissions(accessMode, Mode(), (gid_t)fNode.GroupID(), + (uid_t)fNode.UserID()); } diff --git a/src/add-ons/kernel/file_systems/btrfs/Inode.cpp b/src/add-ons/kernel/file_systems/btrfs/Inode.cpp index 757353f2a0..742f6d567d 100644 --- a/src/add-ons/kernel/file_systems/btrfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/btrfs/Inode.cpp @@ -1,6 +1,6 @@ /* * Copyright 2011, Jérôme Duval, korli@users.berlios.de. - * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2008-2014, Axel Dörfler, axeld@pinc-software.de. * Copyright 2005-2007, Ingo Weinhold, bonefish@cs.tu-berlin.de. * This file may be used under the terms of the MIT License. */ @@ -104,35 +104,8 @@ Inode::CheckPermissions(int accessMode) const if ((accessMode & W_OK) != 0 && fVolume->IsReadOnly()) return B_READ_ONLY_DEVICE; - // get node permissions - mode_t mode = Mode(); - int userPermissions = (mode & S_IRWXU) >> 6; - int groupPermissions = (mode & S_IRWXG) >> 3; - int otherPermissions = mode & S_IRWXO; - - // get the node permissions for this uid/gid - int permissions = 0; - uid_t uid = geteuid(); - gid_t gid = getegid(); - - if (uid == 0) { - // user is root - // root has always read/write permission, but at least one of the - // X bits must be set for execute permission - permissions = userPermissions | groupPermissions | otherPermissions - | R_OK | W_OK; - } else if (uid == (uid_t)fNode.UserID()) { - // user is node owner - permissions = userPermissions; - } else if (gid == (gid_t)fNode.GroupID()) { - // user is in owning group - permissions = groupPermissions; - } else { - // user is one of the others - permissions = otherPermissions; - } - - return (accessMode & ~permissions) == 0 ? B_OK : B_NOT_ALLOWED; + return check_access_permissions(accessMode, Mode(), (gid_t)fNode.GroupID(), + (uid_t)fNode.UserID()); } @@ -162,12 +135,12 @@ Inode::FindBlock(off_t pos, off_t& physical, off_t *_length) logical = diff + extent_data->disk_offset; else panic("unknown extent type; %d\n", extent_data->Type()); - status = fVolume->FindBlock(logical, physical); + status = fVolume->FindBlock(logical, physical); if (_length != NULL) *_length = extent_data->Size() - diff; TRACE("Inode::FindBlock(%" B_PRIdINO ") %" B_PRIdOFF " physical %" B_PRIdOFF "\n", ID(), pos, physical); - + free(extent_data); return status; } @@ -180,7 +153,7 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length) // set/check boundaries for pos/length if (pos < 0) { - ERROR("inode %" B_PRIdINO ": ReadAt failed(pos %" B_PRIdOFF + ERROR("inode %" B_PRIdINO ": ReadAt failed(pos %" B_PRIdOFF ", length %lu)\n", ID(), pos, length); return B_BAD_VALUE; } @@ -212,7 +185,7 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length) uint8 compression = extent_data->Compression(); if (FileCache() != NULL && extent_data->Type() == BTRFS_EXTENT_DATA_REGULAR) { - TRACE("inode %" B_PRIdINO ": ReadAt cache (pos %" B_PRIdOFF ", length %lu)\n", + TRACE("inode %" B_PRIdINO ": ReadAt cache (pos %" B_PRIdOFF ", length %lu)\n", ID(), pos, length); free(extent_data); if (compression == BTRFS_EXTENT_COMPRESS_NONE) @@ -313,7 +286,7 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length) panic("unknown extent compression; %d\n", compression); free(extent_data); return B_OK; - + } @@ -336,7 +309,7 @@ Inode::FindParent(ino_t *id) *id = search_key.Offset(); TRACE("Inode::FindParent() for %" B_PRIdINO ": %" B_PRIdINO "\n", fID, *id); - + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/exfat/Inode.cpp b/src/add-ons/kernel/file_systems/exfat/Inode.cpp index c2548437de..f7c1d405af 100644 --- a/src/add-ons/kernel/file_systems/exfat/Inode.cpp +++ b/src/add-ons/kernel/file_systems/exfat/Inode.cpp @@ -1,6 +1,6 @@ /* * Copyright 2011, Jérôme Duval, korli@users.berlios.de. - * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2008-2014, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ @@ -157,36 +157,8 @@ Inode::CheckPermissions(int accessMode) const if ((accessMode & W_OK) != 0 && fVolume->IsReadOnly()) return B_READ_ONLY_DEVICE; - // get node permissions - mode_t mode = Mode(); - int userPermissions = (mode & S_IRWXU) >> 6; - int groupPermissions = (mode & S_IRWXG) >> 3; - int otherPermissions = mode & S_IRWXO; - - // get the node permissions for this uid/gid - int permissions = 0; - uid_t uid = geteuid(); - gid_t gid = getegid(); - - if (uid == 0) { - // user is root - // root has always read/write permission, but at least one of the - // X bits must be set for execute permission - permissions = userPermissions | groupPermissions | otherPermissions - | R_OK | W_OK; - } else if (uid == (uid_t)UserID()) { - // user is node owner - permissions = userPermissions; - } else if (gid == (gid_t)GroupID()) { - // user is in owning group - permissions = groupPermissions; - } else { - // user is one of the others - permissions = otherPermissions; - } - - return (accessMode & ~permissions) == 0 ? B_OK : B_NOT_ALLOWED; - return B_OK; + return check_access_permissions(accessMode, Mode(), (gid_t)GroupID(), + (uid_t)UserID()); } @@ -217,7 +189,7 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length) return B_NO_ERROR; } - return file_cache_read(FileCache(), NULL, pos, buffer, _length); + return file_cache_read(FileCache(), NULL, pos, buffer, _length); } diff --git a/src/add-ons/kernel/file_systems/ext2/Inode.cpp b/src/add-ons/kernel/file_systems/ext2/Inode.cpp index 7f84af7875..19d0251240 100644 --- a/src/add-ons/kernel/file_systems/ext2/Inode.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Inode.cpp @@ -1,6 +1,6 @@ /* * Copyright 2011, Jérôme Duval, korli@users.berlios.de. - * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2008-2014, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ @@ -186,35 +186,8 @@ Inode::CheckPermissions(int accessMode) const if ((accessMode & W_OK) != 0 && fVolume->IsReadOnly()) return B_READ_ONLY_DEVICE; - // get node permissions - mode_t mode = Mode(); - int userPermissions = (mode & S_IRWXU) >> 6; - int groupPermissions = (mode & S_IRWXG) >> 3; - int otherPermissions = mode & S_IRWXO; - - // get the node permissions for this uid/gid - int permissions = 0; - uid_t uid = geteuid(); - gid_t gid = getegid(); - - if (uid == 0) { - // user is root - // root has always read/write permission, but at least one of the - // X bits must be set for execute permission - permissions = userPermissions | groupPermissions | otherPermissions - | R_OK | W_OK; - } else if (uid == (uid_t)fNode.UserID()) { - // user is node owner - permissions = userPermissions; - } else if (gid == (gid_t)fNode.GroupID()) { - // user is in owning group - permissions = groupPermissions; - } else { - // user is one of the others - permissions = otherPermissions; - } - - return (accessMode & ~permissions) == 0 ? B_OK : B_NOT_ALLOWED; + return check_access_permissions(accessMode, Mode(), (gid_t)fNode.GroupID(), + (uid_t)fNode.UserID()); } 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 bafc1ec3c5..00f19246c7 100644 --- a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp @@ -36,20 +36,6 @@ static const uint32 kOptimalIOSize = 64 * 1024; // #pragma mark - helper functions -static bool -is_user_in_group(gid_t gid) -{ - gid_t groups[NGROUPS_MAX]; - int groupCount = getgroups(NGROUPS_MAX, groups); - for (int i = 0; i < groupCount; i++) { - if (gid == groups[i]) - return true; - } - - return (gid == getegid()); -} - - static status_t check_access(Node* node, int mode) { @@ -57,33 +43,8 @@ check_access(Node* node, int mode) if (mode & W_OK) return B_READ_ONLY_DEVICE; - // get node permissions - int userPermissions = (node->Mode() & S_IRWXU) >> 6; - int groupPermissions = (node->Mode() & S_IRWXG) >> 3; - int otherPermissions = node->Mode() & S_IRWXO; - - // get the permissions for this uid/gid - int permissions = 0; - uid_t uid = geteuid(); - - if (uid == 0) { - // user is root - // root has always read/write permission, but at least one of the - // X bits must be set for execute permission - permissions = userPermissions | groupPermissions | otherPermissions - | S_IROTH | S_IWOTH; - } else if (uid == node->UserID()) { - // user is node owner - permissions = userPermissions; - } else if (is_user_in_group(node->GroupID())) { - // user is in owning group - permissions = groupPermissions; - } else { - // user is one of the others - permissions = otherPermissions; - } - - return (mode & ~permissions) == 0 ? B_OK : B_NOT_ALLOWED; + return check_access_permissions(mode, node->Mode(), node->GroupID(), + node->UserID()); } diff --git a/src/add-ons/kernel/file_systems/reiserfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/reiserfs/kernel_interface.cpp index 0c50e85bc3..4152a55322 100644 --- a/src/add-ons/kernel/file_systems/reiserfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/reiserfs/kernel_interface.cpp @@ -54,9 +54,6 @@ extern fs_volume_ops gReiserFSVolumeOps; extern fs_vnode_ops gReiserFSVnodeOps; -inline static bool is_user_in_group(gid_t gid); - - // #pragma mark - FS @@ -307,41 +304,19 @@ static status_t reiserfs_access(fs_volume *fs, fs_vnode *_node, int mode) { TOUCH(fs); -// FUNCTION_START(); -// Volume *volume = (Volume*)fs->private_volume; VNode *node = (VNode*)_node->private_node; -FUNCTION(("node: (%Ld: %lu, %lu)\n", node->GetID(), node->GetDirID(), + FUNCTION(("node: (%Ld: %lu, %lu)\n", node->GetID(), node->GetDirID(), node->GetObjectID())); + // write access requested? if (mode & W_OK) return B_READ_ONLY_DEVICE; + // get node permissions StatData *statData = node->GetStatData(); - int userPermissions = (statData->GetMode() & S_IRWXU) >> 6; - int groupPermissions = (statData->GetMode() & S_IRWXG) >> 3; - int otherPermissions = statData->GetMode() & S_IRWXO; - // get the permissions for this uid/gid - int permissions = 0; - uid_t uid = geteuid(); - // user is root - if (uid == 0) { - // root has always read/write permission, but at least one of the - // X bits must be set for execute permission - permissions = userPermissions | groupPermissions | otherPermissions - | S_IROTH | S_IWOTH; - // user is node owner - } else if (uid == statData->GetUID()) - permissions = userPermissions; - // user is in owning group - else if (is_user_in_group(statData->GetGID())) - permissions = groupPermissions; - // user is one of the others - else - permissions = otherPermissions; - // do the check - if (mode & ~permissions) - return B_NOT_ALLOWED; - return B_OK; + + return check_access_permissions(mode, statData->GetMode(), + statData->GetGID(), statData->GetUID()); } // reiserfs_read_stat @@ -465,23 +440,7 @@ reiserfs_read(fs_volume *fs, fs_vnode *_node, void *cookie, off_t pos, RETURN_ERROR(error); } -// is_user_in_group -inline static bool -is_user_in_group(gid_t gid) -{ -// Either I miss something, or we don't have getgroups() in the kernel. :-( -/* - gid_t groups[NGROUPS_MAX]; - int groupCount = getgroups(NGROUPS_MAX, groups); - for (int i = 0; i < groupCount; i++) { - if (gid == groups[i]) - return true; - } -*/ - return (gid == getegid()); -} -// DirectoryCookie class DirectoryCookie : public DirEntryIterator { public: DirectoryCookie(Tree *tree, uint32 dirID, uint32 objectID, diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 0a0a7ebe12..fa67829a6a 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -1,6 +1,6 @@ /* * Copyright 2005-2013, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2002-2011, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002-2014, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -3591,6 +3591,23 @@ common_file_io_vec_pages(struct vnode* vnode, void* cookie, } +static bool +is_user_in_group(gid_t gid) +{ + if (gid == getegid()) + return true; + + gid_t groups[NGROUPS_MAX]; + int groupCount = getgroups(NGROUPS_MAX, groups); + for (int i = 0; i < groupCount; i++) { + if (gid == groups[i]) + return true; + } + + return false; +} + + // #pragma mark - public API for file systems @@ -3876,6 +3893,42 @@ volume_for_vnode(fs_vnode* _vnode) } +extern "C" status_t +check_access_permissions(int accessMode, mode_t mode, gid_t nodeGroupID, + uid_t nodeUserID) +{ + // get node permissions + int userPermissions = (mode & S_IRWXU) >> 6; + int groupPermissions = (mode & S_IRWXG) >> 3; + int otherPermissions = mode & S_IRWXO; + + // get the node permissions for this uid/gid + int permissions = 0; + uid_t uid = geteuid(); + + if (uid == 0) { + // user is root + // root has always read/write permission, but at least one of the + // X bits must be set for execute permission + permissions = userPermissions | groupPermissions | otherPermissions + | S_IROTH | S_IWOTH; + if (S_ISDIR(mode)) + permissions |= S_IXOTH; + } else if (uid == nodeUserID) { + // user is node owner + permissions = userPermissions; + } else if (is_user_in_group(nodeGroupID)) { + // user is in owning group + permissions = groupPermissions; + } else { + // user is one of the others + permissions = otherPermissions; + } + + return (accessMode & ~permissions) == 0 ? B_OK : B_NOT_ALLOWED; +} + + #if 0 extern "C" status_t read_pages(int fd, off_t pos, const iovec* vecs, size_t count,