[haiku-commits] haiku: hrev48092 - in src: add-ons/kernel/file_systems/reiserfs system/kernel/fs add-ons/kernel/file_systems/btrfs add-ons/kernel/file_systems/packagefs add-ons/kernel/file_systems/ext2

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 25 Oct 2014 18:47:51 +0200 (CEST)

hrev48092 adds 1 changeset to branch 'master'
old head: 2ce0d69a7e6cba33d0022ec274076177707091c8
new head: 5a95af70a2c45a103b96046b5dae5c2b5a303dfa
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=5a95af7+%5E2ce0d69

----------------------------------------------------------------------------

5a95af7: vfs/{b|btr|package|b}fs/ext2/exfat: common access check.
  
  * Added VFS helper function check_access_permissions() that combines
    several partially correct versions to the one true version (tm).
  * All but BFS (since recently) missed the S_IXOTH for root on directories,
    and all but packagefs missed proper group handling.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev48092
Commit:      5a95af70a2c45a103b96046b5dae5c2b5a303dfa
URL:         http://cgit.haiku-os.org/haiku/commit/?id=5a95af7
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sat Oct 25 14:50:48 2014 UTC

----------------------------------------------------------------------------

8 files changed, 84 insertions(+), 219 deletions(-)
headers/os/drivers/fs_interface.h                |  5 +-
src/add-ons/kernel/file_systems/bfs/Inode.cpp    | 33 +-----------
src/add-ons/kernel/file_systems/btrfs/Inode.cpp  | 45 ++++------------
src/add-ons/kernel/file_systems/exfat/Inode.cpp  | 36 ++-----------
src/add-ons/kernel/file_systems/ext2/Inode.cpp   | 33 ++----------
.../file_systems/packagefs/kernel_interface.cpp  | 43 +--------------
.../file_systems/reiserfs/kernel_interface.cpp   | 53 +++----------------
src/system/kernel/fs/vfs.cpp                     | 55 +++++++++++++++++++-

----------------------------------------------------------------------------

diff --git a/headers/os/drivers/fs_interface.h 
b/headers/os/drivers/fs_interface.h
index 1b3f0be..2aa195d 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 4bab297..db2d98f 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 757353f..742f6d5 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@xxxxxxxxxxxxxxxx.
- * Copyright 2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2008-2014, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * Copyright 2005-2007, Ingo Weinhold, bonefish@xxxxxxxxxxxxxxx.
  * 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 c254843..f7c1d40 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@xxxxxxxxxxxxxxxx.
- * Copyright 2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2008-2014, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * 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 7f84af7..19d0251 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@xxxxxxxxxxxxxxxx.
- * Copyright 2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2008-2014, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * 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 bafc1ec..00f1924 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 0c50e85..4152a55 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 0a0a7eb..fa67829 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@xxxxxx.
- * Copyright 2002-2011, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2002-2014, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * 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,


Other related posts:

  • » [haiku-commits] haiku: hrev48092 - in src: add-ons/kernel/file_systems/reiserfs system/kernel/fs add-ons/kernel/file_systems/btrfs add-ons/kernel/file_systems/packagefs add-ons/kernel/file_systems/ext2 - axeld