Commit 1e1c167a authored by Dave Kleikamp's avatar Dave Kleikamp

JFS: add posix acls

The posix acls are implemented as extended attributes and are compatible
with ext2/ext3 posix acls.
parent 19d973f0
......@@ -655,6 +655,18 @@ config JFS_FS
If you do not intend to use the JFS filesystem, say N.
config JFS_POSIX_ACL
bool "JFS POSIX Access Control Lists"
depends on JFS_FS
---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_DEBUG
bool "JFS debugging"
depends on JFS_FS
......@@ -1464,10 +1476,10 @@ config FS_MBCACHE
default m if EXT2_FS=m || EXT3_FS=m
default y if EXT2_FS=y || EXT3_FS=y
# Posix ACL utility routines (for now, only ext2/ext3)
# Posix ACL utility routines (for now, only ext2/ext3/jfs)
config FS_POSIX_ACL
bool
depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL
depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL
default y
menu "Partition Types"
......
......@@ -10,6 +10,10 @@ jfs-objs := super.o file.o inode.o namei.o jfs_mount.o jfs_umount.o \
jfs_extent.o symlink.o jfs_metapage.o \
jfs_logmgr.o jfs_txnmgr.o jfs_uniupr.o resize.o xattr.o
ifeq ($(CONFIG_JFS_POSIX_ACL),y)
jfs-objs += acl.o
endif
EXTRA_CFLAGS += -D_JFS_4K
include $(TOPDIR)/Rules.make
......@@ -22,6 +22,7 @@
#include "jfs_dmap.h"
#include "jfs_txnmgr.h"
#include "jfs_xattr.h"
#include "jfs_acl.h"
#include "jfs_debug.h"
......@@ -142,6 +143,10 @@ struct inode_operations jfs_file_inode_operations = {
.getxattr = jfs_getxattr,
.listxattr = jfs_listxattr,
.removexattr = jfs_removexattr,
#ifdef CONFIG_JFS_POSIX_ACL
.setattr = jfs_setattr,
.permission = jfs_permission,
#endif
};
struct file_operations jfs_file_operations = {
......
......@@ -69,6 +69,10 @@ struct jfs_inode_info {
*/
struct semaphore commit_sem;
lid_t xtlid; /* lid of xtree lock on directory */
#ifdef CONFIG_JFS_POSIX_ACL
struct posix_acl *i_acl;
struct posix_acl *i_default_acl;
#endif
union {
struct {
xtpage_t _xtroot; /* 288: xtree root */
......@@ -97,6 +101,7 @@ struct jfs_inode_info {
#define i_inline u.link._inline
#define i_inline_ea u.link._inline_ea
#define JFS_ACL_NOT_CACHED ((void *)-1)
#define IREAD_LOCK(ip) down_read(&JFS_IP(ip)->rdwrlock)
#define IREAD_UNLOCK(ip) up_read(&JFS_IP(ip)->rdwrlock)
......
......@@ -25,6 +25,7 @@
#include "jfs_unicode.h"
#include "jfs_metapage.h"
#include "jfs_xattr.h"
#include "jfs_acl.h"
#include "jfs_debug.h"
extern struct inode_operations jfs_file_inode_operations;
......@@ -35,6 +36,7 @@ extern struct address_space_operations jfs_aops;
extern int jfs_fsync(struct file *, struct dentry *, int);
extern void jfs_truncate_nolock(struct inode *, loff_t);
extern struct inode *jfs_iget(struct super_block *, ino_t);
extern int jfs_init_acl(struct inode *, struct inode *);
/*
* forward references
......@@ -150,6 +152,11 @@ int jfs_create(struct inode *dip, struct dentry *dentry, int mode)
out2:
free_UCSname(&dname);
#ifdef CONFIG_JFS_POSIX_ACL
if (rc == 0)
jfs_init_acl(ip, dip);
#endif
out1:
jFYI(1, ("jfs_create: rc:%d\n", -rc));
......@@ -275,6 +282,11 @@ int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
out2:
free_UCSname(&dname);
#ifdef CONFIG_JFS_POSIX_ACL
if (rc == 0)
jfs_init_acl(ip, dip);
#endif
out1:
jFYI(1, ("jfs_mkdir: rc:%d\n", -rc));
......@@ -1016,6 +1028,11 @@ int jfs_symlink(struct inode *dip, struct dentry *dentry, const char *name)
out2:
free_UCSname(&dname);
#ifdef CONFIG_JFS_POSIX_ACL
if (rc == 0)
jfs_init_acl(ip, dip);
#endif
out1:
jFYI(1, ("jfs_symlink: rc:%d\n", -rc));
return -rc;
......@@ -1364,6 +1381,11 @@ int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
out1:
free_UCSname(&dname);
#ifdef CONFIG_JFS_POSIX_ACL
if (rc == 0)
jfs_init_acl(ip, dir);
#endif
out:
jFYI(1, ("jfs_mknod: returning %d\n", rc));
return -rc;
......@@ -1445,6 +1467,10 @@ struct inode_operations jfs_dir_inode_operations = {
.getxattr = jfs_getxattr,
.listxattr = jfs_listxattr,
.removexattr = jfs_removexattr,
#ifdef CONFIG_JFS_POSIX_ACL
.setattr = jfs_setattr,
.permission = jfs_permission,
#endif
};
struct file_operations jfs_dir_operations = {
......
......@@ -28,6 +28,7 @@
#include "jfs_superblock.h"
#include "jfs_dmap.h"
#include "jfs_imap.h"
#include "jfs_acl.h"
#include "jfs_debug.h"
MODULE_DESCRIPTION("The Journaled Filesystem (JFS)");
......@@ -94,7 +95,16 @@ static struct inode *jfs_alloc_inode(struct super_block *sb)
static void jfs_destroy_inode(struct inode *inode)
{
kmem_cache_free(jfs_inode_cachep, JFS_IP(inode));
struct jfs_inode_info *ji = JFS_IP(inode);
#ifdef CONFIG_JFS_POSIX_ACL
if (ji->i_acl && (ji->i_acl != JFS_ACL_NOT_CACHED))
posix_acl_release(ji->i_acl);
if (ji->i_default_acl && (ji->i_default_acl != JFS_ACL_NOT_CACHED))
posix_acl_release(ji->i_default_acl);
#endif
kmem_cache_free(jfs_inode_cachep, ji);
}
static int jfs_statfs(struct super_block *sb, struct statfs *buf)
......@@ -407,6 +417,10 @@ static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
init_MUTEX(&jfs_ip->commit_sem);
jfs_ip->atlhead = 0;
jfs_ip->active_ag = -1;
#ifdef CONFIG_JFS_POSIX_ACL
jfs_ip->i_acl = JFS_ACL_NOT_CACHED;
jfs_ip->i_default_acl = JFS_ACL_NOT_CACHED;
#endif
inode_init_once(&jfs_ip->vfs_inode);
}
}
......
......@@ -26,6 +26,7 @@
#include "jfs_extent.h"
#include "jfs_metapage.h"
#include "jfs_xattr.h"
#include "jfs_acl.h"
/*
* jfs_xattr.c: extended attribute service
......@@ -201,7 +202,6 @@ static int ea_write_inline(struct inode *ip, struct jfs_ea_list *ealist,
ji->mode2 |= INLINEEA;
}
mark_inode_dirty(ip);
return 0;
}
......@@ -640,6 +640,71 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
return rc;
}
/*
* can_set_system_xattr
*
* This code is specific to the system.* namespace. It contains policy
* which doesn't belong in the main xattr codepath.
*/
static int can_set_system_xattr(struct inode *inode, const char *name,
const void *value, size_t value_len)
{
#ifdef CONFIG_JFS_POSIX_ACL
struct posix_acl *acl;
int rc;
if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
return -EPERM;
/*
* XATTR_NAME_ACL_ACCESS is tied to i_mode
*/
if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) {
acl = posix_acl_from_xattr(value, value_len);
if (acl < 0) {
printk(KERN_ERR "posix_acl_from_xattr returned %d\n",
rc);
return rc;
}
if (acl > 0) {
mode_t mode = inode->i_mode;
rc = posix_acl_equiv_mode(acl, &mode);
posix_acl_release(acl);
if (rc < 0) {
printk(KERN_ERR
"posix_acl_equiv_mode returned %d\n",
rc);
return rc;
}
inode->i_mode = mode;
mark_inode_dirty(inode);
if (rc == 0)
value = NULL;
}
/*
* We're changing the ACL. Get rid of the cached one
*/
acl =JFS_IP(inode)->i_acl;
if (acl && (acl != JFS_ACL_NOT_CACHED))
posix_acl_release(acl);
JFS_IP(inode)->i_acl = JFS_ACL_NOT_CACHED;
} else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) {
/*
* We're changing the default ACL. Get rid of the cached one
*/
acl =JFS_IP(inode)->i_default_acl;
if (acl && (acl != JFS_ACL_NOT_CACHED))
posix_acl_release(acl);
JFS_IP(inode)->i_default_acl = JFS_ACL_NOT_CACHED;
} else
/* Invalid xattr name */
return -EINVAL;
return 0;
#else /* CONFIG_JFS_POSIX_ACL */
return -EOPNOTSUPP;
#endif /* CONFIG_JFS_POSIX_ACL */
}
static int can_set_xattr(struct inode *inode, const char *name,
void *value, size_t value_len)
{
......@@ -649,6 +714,12 @@ static int can_set_xattr(struct inode *inode, const char *name,
if (IS_IMMUTABLE(inode) || IS_APPEND(inode) || S_ISLNK(inode->i_mode))
return -EPERM;
if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0)
/*
* "system.*"
*/
return can_set_system_xattr(inode, name, value, value_len);
if((strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) != 0) &&
(strncmp(name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) != 0))
return -EOPNOTSUPP;
......@@ -657,7 +728,11 @@ static int can_set_xattr(struct inode *inode, const char *name,
(!S_ISDIR(inode->i_mode) || inode->i_mode &S_ISVTX))
return -EPERM;
#ifdef CONFIG_JFS_POSIX_ACL
return jfs_permission_have_sem(inode, MAY_WRITE);
#else
return permission(inode, MAY_WRITE);
#endif
}
int __jfs_setxattr(struct inode *inode, const char *name, void *value,
......@@ -810,9 +885,16 @@ int jfs_setxattr(struct dentry *dentry, const char *name, void *value,
return __jfs_setxattr(dentry->d_inode, name, value, value_len, flags);
}
static inline int can_get_xattr(struct inode *inode, const char *name)
static int can_get_xattr(struct inode *inode, const char *name)
{
#ifdef CONFIG_JFS_POSIX_ACL
if(strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) == 0)
return 0;
else
return jfs_permission_have_sem(inode, MAY_READ);
#else
return permission(inode, MAY_READ);
#endif
}
ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
......
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