Commit 0acef032 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] reiserfs: ACL support

From: Chris Mason <mason@suse.com>

From: jeffm@suse.com

reiserfs acl support
parent 0b1a6a8c
...@@ -254,6 +254,18 @@ config REISERFS_FS_XATTR ...@@ -254,6 +254,18 @@ config REISERFS_FS_XATTR
If unsure, say N. If unsure, say N.
config REISERFS_FS_POSIX_ACL
bool "ReiserFS POSIX Access Control Lists"
depends on REISERFS_FS_XATTR
help
Posix Access Control Lists (ACLs) support permissions for users and
groups beyond the owner/group/world scheme.
To learn more about Access Control Lists, visit the Posix ACLs for
Linux website <http://acl.bestbits.at/>.
If you don't know what Access Control Lists are, say N
config JFS_FS config JFS_FS
tristate "JFS filesystem support" tristate "JFS filesystem support"
select NLS select NLS
...@@ -292,13 +304,13 @@ config JFS_STATISTICS ...@@ -292,13 +304,13 @@ config JFS_STATISTICS
to be made available to the user in the /proc/fs/jfs/ directory. to be made available to the user in the /proc/fs/jfs/ directory.
config FS_POSIX_ACL config FS_POSIX_ACL
# Posix ACL utility routines (for now, only ext2/ext3/jfs) # Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs)
# #
# NOTE: you can implement Posix ACLs without these helpers (XFS does). # NOTE: you can implement Posix ACLs without these helpers (XFS does).
# Never use this symbol for ifdefs. # Never use this symbol for ifdefs.
# #
bool bool
depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL || REISERFS_FS_POSIX_ACL
default y default y
config XFS_FS config XFS_FS
......
...@@ -13,6 +13,10 @@ ifeq ($(CONFIG_REISERFS_FS_XATTR),y) ...@@ -13,6 +13,10 @@ ifeq ($(CONFIG_REISERFS_FS_XATTR),y)
reiserfs-objs += xattr.o xattr_user.o reiserfs-objs += xattr.o xattr_user.o
endif endif
ifeq ($(CONFIG_REISERFS_FS_POSIX_ACL),y)
reiserfs-objs += xattr_acl.o
endif
# gcc -O2 (the kernel default) is overaggressive on ppc32 when many inline # gcc -O2 (the kernel default) is overaggressive on ppc32 when many inline
# functions are used. This causes the compiler to advance the stack # functions are used. This causes the compiler to advance the stack
# pointer out of the available stack space, corrupting kernel space, # pointer out of the available stack space, corrupting kernel space,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/reiserfs_fs.h> #include <linux/reiserfs_fs.h>
#include <linux/reiserfs_acl.h>
#include <linux/reiserfs_xattr.h> #include <linux/reiserfs_xattr.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/reiserfs_fs.h> #include <linux/reiserfs_fs.h>
#include <linux/reiserfs_acl.h>
#include <linux/reiserfs_xattr.h> #include <linux/reiserfs_xattr.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
...@@ -976,6 +977,8 @@ static void init_inode (struct inode * inode, struct path * path) ...@@ -976,6 +977,8 @@ static void init_inode (struct inode * inode, struct path * path)
REISERFS_I(inode)->i_prealloc_count = 0; REISERFS_I(inode)->i_prealloc_count = 0;
REISERFS_I(inode)->i_trans_id = 0; REISERFS_I(inode)->i_trans_id = 0;
REISERFS_I(inode)->i_jl = NULL; REISERFS_I(inode)->i_jl = NULL;
REISERFS_I(inode)->i_acl_access = NULL;
REISERFS_I(inode)->i_acl_default = NULL;
if (stat_data_v1 (ih)) { if (stat_data_v1 (ih)) {
struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); struct stat_data_v1 * sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
...@@ -1637,6 +1640,8 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th, ...@@ -1637,6 +1640,8 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
REISERFS_I(inode)->i_attrs = REISERFS_I(inode)->i_attrs =
REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK; REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
sd_attrs_to_i_attrs( REISERFS_I(inode) -> i_attrs, inode ); sd_attrs_to_i_attrs( REISERFS_I(inode) -> i_attrs, inode );
REISERFS_I(inode)->i_acl_access = NULL;
REISERFS_I(inode)->i_acl_default = NULL;
if (old_format_only (sb)) if (old_format_only (sb))
make_le_item_head (&ih, 0, KEY_FORMAT_3_5, SD_OFFSET, TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT); make_le_item_head (&ih, 0, KEY_FORMAT_3_5, SD_OFFSET, TYPE_STAT_DATA, SD_V1_SIZE, MAX_US_INT);
...@@ -1721,6 +1726,19 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th, ...@@ -1721,6 +1726,19 @@ int reiserfs_new_inode (struct reiserfs_transaction_handle *th,
goto out_inserted_sd; goto out_inserted_sd;
} }
/* XXX CHECK THIS */
if (reiserfs_posixacl (inode->i_sb)) {
retval = reiserfs_inherit_default_acl (dir, dentry, inode);
if (retval) {
err = retval;
reiserfs_check_path(&path_to_key) ;
journal_end(th, th->t_super, th->t_blocks_allocated);
goto out_inserted_sd;
}
} else if (inode->i_sb->s_flags & MS_POSIXACL) {
reiserfs_warning ("ACLs aren't enabled in the fs, but vfs thinks they are!\n");
}
insert_inode_hash (inode); insert_inode_hash (inode);
reiserfs_update_sd(th, inode); reiserfs_update_sd(th, inode);
reiserfs_check_path(&path_to_key) ; reiserfs_check_path(&path_to_key) ;
...@@ -2565,6 +2583,11 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) { ...@@ -2565,6 +2583,11 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
} }
if (!error && reiserfs_posixacl (inode->i_sb)) {
if (attr->ia_valid & ATTR_MODE)
error = reiserfs_acl_chmod (inode);
}
out: out:
reiserfs_write_unlock(inode->i_sb); reiserfs_write_unlock(inode->i_sb);
return error ; return error ;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/reiserfs_fs.h> #include <linux/reiserfs_fs.h>
#include <linux/reiserfs_acl.h>
#include <linux/reiserfs_xattr.h> #include <linux/reiserfs_xattr.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
...@@ -579,6 +580,7 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode, ...@@ -579,6 +580,7 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode,
struct inode * inode; struct inode * inode;
int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 ;
struct reiserfs_transaction_handle th ; struct reiserfs_transaction_handle th ;
int locked;
if (!(inode = new_inode(dir->i_sb))) { if (!(inode = new_inode(dir->i_sb))) {
return -ENOMEM ; return -ENOMEM ;
...@@ -587,9 +589,19 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode, ...@@ -587,9 +589,19 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode,
if (retval) if (retval)
return retval; return retval;
locked = reiserfs_cache_default_acl (dir);
reiserfs_write_lock(dir->i_sb); reiserfs_write_lock(dir->i_sb);
if (locked)
reiserfs_write_lock_xattrs (dir->i_sb);
journal_begin(&th, dir->i_sb, jbegin_count) ; journal_begin(&th, dir->i_sb, jbegin_count) ;
retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode); retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode);
if (locked)
reiserfs_write_unlock_xattrs (dir->i_sb);
if (retval) { if (retval) {
goto out_failed; goto out_failed;
} }
...@@ -625,6 +637,7 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, ...@@ -625,6 +637,7 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode,
struct inode * inode; struct inode * inode;
struct reiserfs_transaction_handle th ; struct reiserfs_transaction_handle th ;
int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3;
int locked;
if (!new_valid_dev(rdev)) if (!new_valid_dev(rdev))
return -EINVAL; return -EINVAL;
...@@ -636,10 +649,20 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, ...@@ -636,10 +649,20 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode,
if (retval) if (retval)
return retval; return retval;
locked = reiserfs_cache_default_acl (dir);
reiserfs_write_lock(dir->i_sb); reiserfs_write_lock(dir->i_sb);
if (locked)
reiserfs_write_lock_xattrs (dir->i_sb);
journal_begin(&th, dir->i_sb, jbegin_count) ; journal_begin(&th, dir->i_sb, jbegin_count) ;
retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode); retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode);
if (locked)
reiserfs_write_unlock_xattrs (dir->i_sb);
if (retval) { if (retval) {
goto out_failed; goto out_failed;
} }
...@@ -678,6 +701,7 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode) ...@@ -678,6 +701,7 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode)
struct inode * inode; struct inode * inode;
struct reiserfs_transaction_handle th ; struct reiserfs_transaction_handle th ;
int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3;
int locked;
#ifdef DISPLACE_NEW_PACKING_LOCALITIES #ifdef DISPLACE_NEW_PACKING_LOCALITIES
/* set flag that new packing locality created and new blocks for the content * of that directory are not displaced yet */ /* set flag that new packing locality created and new blocks for the content * of that directory are not displaced yet */
...@@ -691,7 +715,11 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode) ...@@ -691,7 +715,11 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode)
if (retval) if (retval)
return retval; return retval;
locked = reiserfs_cache_default_acl (dir);
reiserfs_write_lock(dir->i_sb); reiserfs_write_lock(dir->i_sb);
if (locked)
reiserfs_write_lock_xattrs (dir->i_sb);
journal_begin(&th, dir->i_sb, jbegin_count) ; journal_begin(&th, dir->i_sb, jbegin_count) ;
/* inc the link count now, so another writer doesn't overflow it while /* inc the link count now, so another writer doesn't overflow it while
...@@ -703,6 +731,9 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode) ...@@ -703,6 +731,9 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode)
old_format_only (dir->i_sb) ? old_format_only (dir->i_sb) ?
EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE, EMPTY_DIR_SIZE_V1 : EMPTY_DIR_SIZE,
dentry, inode); dentry, inode);
if (locked)
reiserfs_write_unlock_xattrs (dir->i_sb);
if (retval) { if (retval) {
dir->i_nlink-- ; dir->i_nlink-- ;
goto out_failed; goto out_failed;
...@@ -945,6 +976,8 @@ static int reiserfs_symlink (struct inode * parent_dir, ...@@ -945,6 +976,8 @@ static int reiserfs_symlink (struct inode * parent_dir,
memcpy (name, symname, strlen (symname)); memcpy (name, symname, strlen (symname));
padd_item (name, item_len, strlen (symname)); padd_item (name, item_len, strlen (symname));
/* We would inherit the default ACL here, but symlinks don't get ACLs */
journal_begin(&th, parent_dir->i_sb, jbegin_count) ; journal_begin(&th, parent_dir->i_sb, jbegin_count) ;
retval = reiserfs_new_inode (&th, parent_dir, mode, name, strlen (symname), retval = reiserfs_new_inode (&th, parent_dir, mode, name, strlen (symname),
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/time.h> #include <linux/time.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/reiserfs_fs.h> #include <linux/reiserfs_fs.h>
#include <linux/reiserfs_acl.h>
#include <linux/reiserfs_xattr.h> #include <linux/reiserfs_xattr.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -433,6 +434,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) ...@@ -433,6 +434,8 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
SLAB_CTOR_CONSTRUCTOR) { SLAB_CTOR_CONSTRUCTOR) {
INIT_LIST_HEAD(&ei->i_prealloc_list) ; INIT_LIST_HEAD(&ei->i_prealloc_list) ;
inode_init_once(&ei->vfs_inode); inode_init_once(&ei->vfs_inode);
ei->i_acl_access = NULL;
ei->i_acl_default = NULL;
} }
} }
...@@ -473,6 +476,22 @@ static void reiserfs_dirty_inode (struct inode * inode) { ...@@ -473,6 +476,22 @@ static void reiserfs_dirty_inode (struct inode * inode) {
reiserfs_write_unlock(inode->i_sb); reiserfs_write_unlock(inode->i_sb);
} }
static void reiserfs_clear_inode (struct inode *inode)
{
struct posix_acl *acl;
acl = REISERFS_I(inode)->i_acl_access;
if (acl && !IS_ERR (acl))
posix_acl_release (acl);
REISERFS_I(inode)->i_acl_access = NULL;
acl = REISERFS_I(inode)->i_acl_default;
if (acl && !IS_ERR (acl))
posix_acl_release (acl);
REISERFS_I(inode)->i_acl_default = NULL;
}
struct super_operations reiserfs_sops = struct super_operations reiserfs_sops =
{ {
.alloc_inode = reiserfs_alloc_inode, .alloc_inode = reiserfs_alloc_inode,
...@@ -480,6 +499,7 @@ struct super_operations reiserfs_sops = ...@@ -480,6 +499,7 @@ struct super_operations reiserfs_sops =
.write_inode = reiserfs_write_inode, .write_inode = reiserfs_write_inode,
.dirty_inode = reiserfs_dirty_inode, .dirty_inode = reiserfs_dirty_inode,
.delete_inode = reiserfs_delete_inode, .delete_inode = reiserfs_delete_inode,
.clear_inode = reiserfs_clear_inode,
.put_super = reiserfs_put_super, .put_super = reiserfs_put_super,
.write_super = reiserfs_write_super, .write_super = reiserfs_write_super,
.write_super_lockfs = reiserfs_write_super_lockfs, .write_super_lockfs = reiserfs_write_super_lockfs,
...@@ -682,6 +702,10 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st ...@@ -682,6 +702,10 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
{"noattrs", 0, 0, 0, 1<<REISERFS_ATTRS}, {"noattrs", 0, 0, 0, 1<<REISERFS_ATTRS},
{"user_xattr", 0, 0, 1<<REISERFS_XATTRS_USER, 0}, {"user_xattr", 0, 0, 1<<REISERFS_XATTRS_USER, 0},
{"nouser_xattr", 0, 0, 0, 1<<REISERFS_XATTRS_USER}, {"nouser_xattr", 0, 0, 0, 1<<REISERFS_XATTRS_USER},
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
{"acl", 0, 0, 1<<REISERFS_POSIXACL, 0},
{"noacl", 0, 0, 0, 1<<REISERFS_POSIXACL},
#endif
{"nolog", 0, 0, 0, 0}, /* This is unsupported */ {"nolog", 0, 0, 0, 0}, /* This is unsupported */
{"replayonly", 0, 0, 1<<REPLAYONLY, 0}, {"replayonly", 0, 0, 1<<REPLAYONLY, 0},
{"block-allocator", 'a', balloc, 0, 0}, {"block-allocator", 'a', balloc, 0, 0},
...@@ -827,6 +851,7 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a ...@@ -827,6 +851,7 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a
safe_mask |= 1 << REISERFS_TEST4; safe_mask |= 1 << REISERFS_TEST4;
safe_mask |= 1 << REISERFS_ATTRS; safe_mask |= 1 << REISERFS_ATTRS;
safe_mask |= 1 << REISERFS_XATTRS_USER; safe_mask |= 1 << REISERFS_XATTRS_USER;
safe_mask |= 1 << REISERFS_POSIXACL;
/* Update the bitmask, taking care to keep /* Update the bitmask, taking care to keep
* the bits we're not allowed to change here */ * the bits we're not allowed to change here */
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
*/ */
/* /*
* In order to implement EAs in a clean, backwards compatible manner, * In order to implement EA/ACLs in a clean, backwards compatible manner,
* they are implemented as files in a "private" directory. * they are implemented as files in a "private" directory.
* Each EA is in it's own file, with the directory layout like so (/ is assumed * Each EA is in it's own file, with the directory layout like so (/ is assumed
* to be relative to fs root). Inside the /.reiserfs_priv/xattrs directory, * to be relative to fs root). Inside the /.reiserfs_priv/xattrs directory,
...@@ -15,12 +15,18 @@ ...@@ -15,12 +15,18 @@
* named with the name of the extended attribute. * named with the name of the extended attribute.
* *
* So, for objectid 12648430, we could have: * So, for objectid 12648430, we could have:
* /.reiserfs_priv/xattrs/C0FFEE.0/system.posix_acl_access
* /.reiserfs_priv/xattrs/C0FFEE.0/system.posix_acl_default
* /.reiserfs_priv/xattrs/C0FFEE.0/user.Content-Type * /.reiserfs_priv/xattrs/C0FFEE.0/user.Content-Type
* .. or similar. * .. or similar.
* *
* The file contents are the text of the EA. The size is known based on the * The file contents are the text of the EA. The size is known based on the
* stat data describing the file. * stat data describing the file.
* *
* In the case of system.posix_acl_access and system.posix_acl_default, since
* these are special cases for filesystem ACLs, they are interpreted by the
* kernel, in addition, they are negatively and positively cached and attached
* to the inode so that unnecessary lookups are avoided.
*/ */
#include <linux/reiserfs_fs.h> #include <linux/reiserfs_fs.h>
...@@ -32,6 +38,7 @@ ...@@ -32,6 +38,7 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/xattr.h> #include <linux/xattr.h>
#include <linux/reiserfs_xattr.h> #include <linux/reiserfs_xattr.h>
#include <linux/reiserfs_acl.h>
#include <linux/mbcache.h> #include <linux/mbcache.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/checksum.h> #include <asm/checksum.h>
...@@ -1169,6 +1176,10 @@ reiserfs_xattr_register_handlers (void) ...@@ -1169,6 +1176,10 @@ reiserfs_xattr_register_handlers (void)
/* Add the handlers */ /* Add the handlers */
list_add_tail (&user_handler.handlers, &xattr_handlers); list_add_tail (&user_handler.handlers, &xattr_handlers);
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
list_add_tail (&posix_acl_access_handler.handlers, &xattr_handlers);
list_add_tail (&posix_acl_default_handler.handlers, &xattr_handlers);
#endif
/* Run initializers, if available */ /* Run initializers, if available */
list_for_each (p, &xattr_handlers) { list_for_each (p, &xattr_handlers) {
...@@ -1231,7 +1242,7 @@ reiserfs_xattr_init (struct super_block *s, int mount_flags) ...@@ -1231,7 +1242,7 @@ reiserfs_xattr_init (struct super_block *s, int mount_flags)
} else if (reiserfs_xattrs_optional (s)) { } else if (reiserfs_xattrs_optional (s)) {
/* Old format filesystem, but optional xattrs have been enabled /* Old format filesystem, but optional xattrs have been enabled
* at mount time. Error out. */ * at mount time. Error out. */
reiserfs_warning ("reiserfs: xattrs not supported on pre v3.6 " reiserfs_warning ("reiserfs: xattrs/ACLs not supported on pre v3.6 "
"format filesystem. Failing mount.\n"); "format filesystem. Failing mount.\n");
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
goto error; goto error;
...@@ -1276,7 +1287,7 @@ reiserfs_xattr_init (struct super_block *s, int mount_flags) ...@@ -1276,7 +1287,7 @@ reiserfs_xattr_init (struct super_block *s, int mount_flags)
/* If we're read-only it just means that the dir hasn't been /* If we're read-only it just means that the dir hasn't been
* created. Not an error -- just no xattrs on the fs. We'll * created. Not an error -- just no xattrs on the fs. We'll
* check again if we go read-write */ * check again if we go read-write */
reiserfs_warning ("reiserfs: xattrs enabled and couldn't " reiserfs_warning ("reiserfs: xattrs/ACLs enabled and couldn't "
"find/create .reiserfs_priv. Failing mount.\n"); "find/create .reiserfs_priv. Failing mount.\n");
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
} }
...@@ -1288,12 +1299,20 @@ reiserfs_xattr_init (struct super_block *s, int mount_flags) ...@@ -1288,12 +1299,20 @@ reiserfs_xattr_init (struct super_block *s, int mount_flags)
if (err) { if (err) {
clear_bit (REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt)); clear_bit (REISERFS_XATTRS, &(REISERFS_SB(s)->s_mount_opt));
clear_bit (REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt)); clear_bit (REISERFS_XATTRS_USER, &(REISERFS_SB(s)->s_mount_opt));
clear_bit (REISERFS_POSIXACL, &(REISERFS_SB(s)->s_mount_opt));
} }
/* The super_block MS_POSIXACL must mirror the (no)acl mount option. */
s->s_flags = s->s_flags & ~MS_POSIXACL;
if (reiserfs_posixacl (s))
s->s_flags |= MS_POSIXACL;
return err; return err;
} }
int static int
reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd) __reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd,
int need_lock)
{ {
umode_t mode = inode->i_mode; umode_t mode = inode->i_mode;
...@@ -1317,10 +1336,45 @@ reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd) ...@@ -1317,10 +1336,45 @@ reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd)
if (is_reiserfs_priv_object (inode)) if (is_reiserfs_priv_object (inode))
return 0; return 0;
if (current->fsuid == inode->i_uid) if (current->fsuid == inode->i_uid) {
mode >>= 6; mode >>= 6;
else if (in_group_p(inode->i_gid)) #ifdef CONFIG_REISERFS_FS_POSIX_ACL
mode >>= 3; } else if (reiserfs_posixacl(inode->i_sb) &&
get_inode_sd_version (inode) != STAT_DATA_V1) {
struct posix_acl *acl;
/* ACL can't contain additional permissions if
the ACL_MASK entry is 0 */
if (!(mode & S_IRWXG))
goto check_groups;
if (need_lock)
reiserfs_read_lock_xattrs (inode->i_sb);
acl = reiserfs_get_acl (inode, ACL_TYPE_ACCESS);
if (need_lock)
reiserfs_read_unlock_xattrs (inode->i_sb);
if (IS_ERR (acl)) {
if (PTR_ERR (acl) == -ENODATA)
goto check_groups;
return PTR_ERR (acl);
}
if (acl) {
int err = posix_acl_permission (inode, acl, mask);
posix_acl_release (acl);
if (err == -EACCES) {
goto check_capabilities;
}
return err;
} else {
goto check_groups;
}
#endif
} else {
check_groups:
if (in_group_p(inode->i_gid))
mode >>= 3;
}
/* /*
* If the DACs are ok we don't need any capability check. * If the DACs are ok we don't need any capability check.
...@@ -1328,6 +1382,7 @@ reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd) ...@@ -1328,6 +1382,7 @@ reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd)
if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)) if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
return 0; return 0;
check_capabilities:
/* /*
* Read/write DACs are always overridable. * Read/write DACs are always overridable.
* Executable DACs are overridable if at least one exec bit is set. * Executable DACs are overridable if at least one exec bit is set.
...@@ -1344,5 +1399,16 @@ reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd) ...@@ -1344,5 +1399,16 @@ reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd)
return 0; return 0;
return -EACCES; return -EACCES;
}
int
reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd)
{
return __reiserfs_permission (inode, mask, nd, 1);
}
int
reiserfs_permission_locked (struct inode *inode, int mask, struct nameidata *nd)
{
return __reiserfs_permission (inode, mask, nd, 0);
} }
This diff is collapsed.
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
#include <linux/reiserfs_xattr.h> #include <linux/reiserfs_xattr.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
# include <linux/reiserfs_acl.h>
#endif
#define XATTR_USER_PREFIX "user." #define XATTR_USER_PREFIX "user."
static int static int
...@@ -20,7 +24,7 @@ user_get (struct inode *inode, const char *name, void *buffer, size_t size) ...@@ -20,7 +24,7 @@ user_get (struct inode *inode, const char *name, void *buffer, size_t size)
if (!reiserfs_xattrs_user (inode->i_sb)) if (!reiserfs_xattrs_user (inode->i_sb))
return -EOPNOTSUPP; return -EOPNOTSUPP;
error = permission (inode, MAY_READ, NULL); error = reiserfs_permission_locked (inode, MAY_READ, NULL);
if (error) if (error)
return error; return error;
...@@ -44,7 +48,7 @@ user_set (struct inode *inode, const char *name, const void *buffer, ...@@ -44,7 +48,7 @@ user_set (struct inode *inode, const char *name, const void *buffer,
(!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX)) (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX))
return -EPERM; return -EPERM;
error = permission (inode, MAY_WRITE, NULL); error = reiserfs_permission_locked (inode, MAY_WRITE, NULL);
if (error) if (error)
return error; return error;
...@@ -66,7 +70,7 @@ user_del (struct inode *inode, const char *name) ...@@ -66,7 +70,7 @@ user_del (struct inode *inode, const char *name)
(!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX)) (!S_ISDIR (inode->i_mode) || inode->i_mode & S_ISVTX))
return -EPERM; return -EPERM;
error = permission (inode, MAY_WRITE, NULL); error = reiserfs_permission_locked (inode, MAY_WRITE, NULL);
if (error) if (error)
return error; return error;
......
#include <linux/init.h>
#include <linux/posix_acl.h>
#include <linux/xattr_acl.h>
#define REISERFS_ACL_VERSION 0x0001
typedef struct {
__u16 e_tag;
__u16 e_perm;
__u32 e_id;
} reiserfs_acl_entry;
typedef struct {
__u16 e_tag;
__u16 e_perm;
} reiserfs_acl_entry_short;
typedef struct {
__u32 a_version;
} reiserfs_acl_header;
static inline size_t reiserfs_acl_size(int count)
{
if (count <= 4) {
return sizeof(reiserfs_acl_header) +
count * sizeof(reiserfs_acl_entry_short);
} else {
return sizeof(reiserfs_acl_header) +
4 * sizeof(reiserfs_acl_entry_short) +
(count - 4) * sizeof(reiserfs_acl_entry);
}
}
static inline int reiserfs_acl_count(size_t size)
{
ssize_t s;
size -= sizeof(reiserfs_acl_header);
s = size - 4 * sizeof(reiserfs_acl_entry_short);
if (s < 0) {
if (size % sizeof(reiserfs_acl_entry_short))
return -1;
return size / sizeof(reiserfs_acl_entry_short);
} else {
if (s % sizeof(reiserfs_acl_entry))
return -1;
return s / sizeof(reiserfs_acl_entry) + 4;
}
}
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
struct posix_acl * reiserfs_get_acl(struct inode *inode, int type);
int reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl);
int reiserfs_acl_chmod (struct inode *inode);
int reiserfs_inherit_default_acl (struct inode *dir, struct dentry *dentry, struct inode *inode);
int reiserfs_cache_default_acl (struct inode *dir);
extern int reiserfs_xattr_posix_acl_init (void) __init;
extern int reiserfs_xattr_posix_acl_exit (void);
extern struct reiserfs_xattr_handler posix_acl_default_handler;
extern struct reiserfs_xattr_handler posix_acl_access_handler;
#else
#define reiserfs_set_acl NULL
#define reiserfs_get_acl NULL
#define reiserfs_cache_default_acl(inode) 0
static inline int
reiserfs_xattr_posix_acl_init (void)
{
return 0;
}
static inline int
reiserfs_xattr_posix_acl_exit (void)
{
return 0;
}
static inline int
reiserfs_acl_chmod (struct inode *inode)
{
return 0;
}
static inline int
reiserfs_inherit_default_acl (const struct inode *dir, struct dentry *dentry, struct inode *inode)
{
return 0;
}
#endif
...@@ -52,6 +52,9 @@ struct reiserfs_inode_info { ...@@ -52,6 +52,9 @@ struct reiserfs_inode_info {
** flushed */ ** flushed */
unsigned long i_trans_id ; unsigned long i_trans_id ;
struct reiserfs_journal_list *i_jl; struct reiserfs_journal_list *i_jl;
struct posix_acl *i_acl_access;
struct posix_acl *i_acl_default;
struct inode vfs_inode; struct inode vfs_inode;
}; };
......
...@@ -443,6 +443,7 @@ enum reiserfs_mount_options { ...@@ -443,6 +443,7 @@ enum reiserfs_mount_options {
REISERFS_ATTRS, REISERFS_ATTRS,
REISERFS_XATTRS, REISERFS_XATTRS,
REISERFS_XATTRS_USER, REISERFS_XATTRS_USER,
REISERFS_POSIXACL,
REISERFS_TEST1, REISERFS_TEST1,
REISERFS_TEST2, REISERFS_TEST2,
...@@ -470,7 +471,8 @@ enum reiserfs_mount_options { ...@@ -470,7 +471,8 @@ enum reiserfs_mount_options {
#define reiserfs_data_writeback(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_WRITEBACK)) #define reiserfs_data_writeback(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_WRITEBACK))
#define reiserfs_xattrs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS)) #define reiserfs_xattrs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS))
#define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER)) #define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER))
#define reiserfs_xattrs_optional(s) reiserfs_xattrs_user(s) #define reiserfs_posixacl(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_POSIXACL))
#define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s))
void reiserfs_file_buffer (struct buffer_head * bh, int list); void reiserfs_file_buffer (struct buffer_head * bh, int list);
extern struct file_system_type reiserfs_fs_type; extern struct file_system_type reiserfs_fs_type;
......
...@@ -42,6 +42,7 @@ int reiserfs_delete_xattrs (struct inode *inode); ...@@ -42,6 +42,7 @@ int reiserfs_delete_xattrs (struct inode *inode);
int reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs); int reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs);
int reiserfs_xattr_init (struct super_block *sb, int mount_flags); int reiserfs_xattr_init (struct super_block *sb, int mount_flags);
int reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd); int reiserfs_permission (struct inode *inode, int mask, struct nameidata *nd);
int reiserfs_permission_locked (struct inode *inode, int mask, struct nameidata *nd);
int reiserfs_xattr_del (struct inode *, const char *); int reiserfs_xattr_del (struct inode *, const char *);
int reiserfs_xattr_get (const struct inode *, const char *, void *, size_t); int reiserfs_xattr_get (const struct inode *, const char *, void *, size_t);
...@@ -94,7 +95,11 @@ reiserfs_read_unlock_xattrs(struct super_block *sb) ...@@ -94,7 +95,11 @@ reiserfs_read_unlock_xattrs(struct super_block *sb)
static inline int reiserfs_delete_xattrs (struct inode *inode) { return 0; }; static inline int reiserfs_delete_xattrs (struct inode *inode) { return 0; };
static inline int reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs) { return 0; }; static inline int reiserfs_chown_xattrs (struct inode *inode, struct iattr *attrs) { return 0; };
static inline int reiserfs_xattr_init (struct super_block *sb, int mount_flags) { return 0; }; static inline int reiserfs_xattr_init (struct super_block *sb, int mount_flags)
{
sb->s_flags = (sb->s_flags & ~MS_POSIXACL); /* to be sure */
return 0;
};
#endif #endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment