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.
This commit is contained in:
parent
2ce0d69a7e
commit
5a95af70a2
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user