aboutsummaryrefslogtreecommitdiff
path: root/fs/gfs2/acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/acl.c')
-rw-r--r--fs/gfs2/acl.c297
1 files changed, 35 insertions, 262 deletions
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 48171f4c943..3088e2a38e3 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -38,8 +38,9 @@ static const char *gfs2_acl_name(int type)
return NULL;
}
-static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
+struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
{
+ struct gfs2_inode *ip = GFS2_I(inode);
struct posix_acl *acl;
const char *name;
char *data;
@@ -48,10 +49,6 @@ static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
if (!ip->i_eattr)
return NULL;
- acl = get_cached_acl(&ip->i_inode, type);
- if (acl != ACL_NOT_CACHED)
- return acl;
-
name = gfs2_acl_name(type);
if (name == NULL)
return ERR_PTR(-EINVAL);
@@ -62,54 +59,12 @@ static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)
if (len == 0)
return NULL;
- acl = posix_acl_from_xattr(data, len);
+ acl = posix_acl_from_xattr(&init_user_ns, data, len);
kfree(data);
return acl;
}
-/**
- * gfs2_check_acl - Check an ACL to see if we're allowed to do something
- * @inode: the file we want to do something to
- * @mask: what we want to do
- *
- * Returns: errno
- */
-
-int gfs2_check_acl(struct inode *inode, int mask)
-{
- struct posix_acl *acl;
- int error;
-
- acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
-
- if (acl) {
- error = posix_acl_permission(inode, acl, mask);
- posix_acl_release(acl);
- return error;
- }
-
- return -EAGAIN;
-}
-
-static int gfs2_set_mode(struct inode *inode, mode_t mode)
-{
- int error = 0;
-
- if (mode != inode->i_mode) {
- struct iattr iattr;
-
- iattr.ia_valid = ATTR_MODE;
- iattr.ia_mode = mode;
-
- error = gfs2_setattr_simple(GFS2_I(inode), &iattr);
- }
-
- return error;
-}
-
-static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
+int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
int error;
int len;
@@ -117,232 +72,50 @@ static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl)
const char *name = gfs2_acl_name(type);
BUG_ON(name == NULL);
- len = posix_acl_to_xattr(acl, NULL, 0);
- if (len == 0)
- return 0;
- data = kmalloc(len, GFP_NOFS);
- if (data == NULL)
- return -ENOMEM;
- error = posix_acl_to_xattr(acl, data, len);
- if (error < 0)
- goto out;
- error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
- if (!error)
- set_cached_acl(inode, type, acl);
-out:
- kfree(data);
- return error;
-}
-
-int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)
-{
- struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
- struct posix_acl *acl, *clone;
- mode_t mode = inode->i_mode;
- int error = 0;
- if (!sdp->sd_args.ar_posix_acl)
- return 0;
- if (S_ISLNK(inode->i_mode))
- return 0;
+ if (acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
+ return -E2BIG;
- acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (!acl) {
- mode &= ~current_umask();
- if (mode != inode->i_mode)
- error = gfs2_set_mode(inode, mode);
- return error;
- }
-
- if (S_ISDIR(inode->i_mode)) {
- error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl);
- if (error)
- goto out;
- }
-
- clone = posix_acl_clone(acl, GFP_NOFS);
- error = -ENOMEM;
- if (!clone)
- goto out;
- posix_acl_release(acl);
- acl = clone;
-
- error = posix_acl_create_masq(acl, &mode);
- if (error < 0)
- goto out;
- if (error == 0)
- goto munge;
-
- error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl);
- if (error)
- goto out;
-munge:
- error = gfs2_set_mode(inode, mode);
-out:
- posix_acl_release(acl);
- return error;
-}
+ if (type == ACL_TYPE_ACCESS) {
+ umode_t mode = inode->i_mode;
-int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)
-{
- struct posix_acl *acl, *clone;
- char *data;
- unsigned int len;
- int error;
+ error = posix_acl_equiv_mode(acl, &mode);
+ if (error < 0)
+ return error;
- acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (!acl)
- return gfs2_setattr_simple(ip, attr);
+ if (error == 0)
+ acl = NULL;
- clone = posix_acl_clone(acl, GFP_NOFS);
- error = -ENOMEM;
- if (!clone)
- goto out;
- posix_acl_release(acl);
- acl = clone;
+ if (mode != inode->i_mode) {
+ inode->i_mode = mode;
+ mark_inode_dirty(inode);
+ }
+ }
- error = posix_acl_chmod_masq(acl, attr->ia_mode);
- if (!error) {
- len = posix_acl_to_xattr(acl, NULL, 0);
+ if (acl) {
+ len = posix_acl_to_xattr(&init_user_ns, acl, NULL, 0);
+ if (len == 0)
+ return 0;
data = kmalloc(len, GFP_NOFS);
- error = -ENOMEM;
if (data == NULL)
+ return -ENOMEM;
+ error = posix_acl_to_xattr(&init_user_ns, acl, data, len);
+ if (error < 0)
goto out;
- posix_acl_to_xattr(acl, data, len);
- error = gfs2_xattr_acl_chmod(ip, attr, data);
- kfree(data);
- set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);
+ } else {
+ data = NULL;
+ len = 0;
}
-out:
- posix_acl_release(acl);
- return error;
-}
-
-static int gfs2_acl_type(const char *name)
-{
- if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0)
- return ACL_TYPE_ACCESS;
- if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0)
- return ACL_TYPE_DEFAULT;
- return -EINVAL;
-}
-
-static int gfs2_xattr_system_get(struct dentry *dentry, const char *name,
- void *buffer, size_t size, int xtype)
-{
- struct inode *inode = dentry->d_inode;
- struct gfs2_sbd *sdp = GFS2_SB(inode);
- struct posix_acl *acl;
- int type;
- int error;
-
- if (!sdp->sd_args.ar_posix_acl)
- return -EOPNOTSUPP;
-
- type = gfs2_acl_type(name);
- if (type < 0)
- return type;
-
- acl = gfs2_acl_get(GFS2_I(inode), type);
- if (IS_ERR(acl))
- return PTR_ERR(acl);
- if (acl == NULL)
- return -ENODATA;
-
- error = posix_acl_to_xattr(acl, buffer, size);
- posix_acl_release(acl);
-
- return error;
-}
-
-static int gfs2_xattr_system_set(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags,
- int xtype)
-{
- struct inode *inode = dentry->d_inode;
- struct gfs2_sbd *sdp = GFS2_SB(inode);
- struct posix_acl *acl = NULL;
- int error = 0, type;
-
- if (!sdp->sd_args.ar_posix_acl)
- return -EOPNOTSUPP;
-
- type = gfs2_acl_type(name);
- if (type < 0)
- return type;
- if (flags & XATTR_CREATE)
- return -EINVAL;
- if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
- return value ? -EACCES : 0;
- if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER))
- return -EPERM;
- if (S_ISLNK(inode->i_mode))
- return -EOPNOTSUPP;
-
- if (!value)
- goto set_acl;
-
- acl = posix_acl_from_xattr(value, size);
- if (!acl) {
- /*
- * acl_set_file(3) may request that we set default ACLs with
- * zero length -- defend (gracefully) against that here.
- */
- goto out;
- }
- if (IS_ERR(acl)) {
- error = PTR_ERR(acl);
- goto out;
- }
-
- error = posix_acl_valid(acl);
+ error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
if (error)
- goto out_release;
-
- error = -EINVAL;
- if (acl->a_count > GFS2_ACL_MAX_ENTRIES)
- goto out_release;
-
- if (type == ACL_TYPE_ACCESS) {
- mode_t mode = inode->i_mode;
- error = posix_acl_equiv_mode(acl, &mode);
-
- if (error <= 0) {
- posix_acl_release(acl);
- acl = NULL;
-
- if (error < 0)
- return error;
- }
-
- error = gfs2_set_mode(inode, mode);
- if (error)
- goto out_release;
- }
+ goto out;
-set_acl:
- error = __gfs2_xattr_set(inode, name, value, size, 0, GFS2_EATYPE_SYS);
- if (!error) {
- if (acl)
- set_cached_acl(inode, type, acl);
- else
- forget_cached_acl(inode, type);
- }
-out_release:
- posix_acl_release(acl);
+ if (acl)
+ set_cached_acl(inode, type, acl);
+ else
+ forget_cached_acl(inode, type);
out:
+ kfree(data);
return error;
}
-
-const struct xattr_handler gfs2_xattr_system_handler = {
- .prefix = XATTR_SYSTEM_PREFIX,
- .flags = GFS2_EATYPE_SYS,
- .get = gfs2_xattr_system_get,
- .set = gfs2_xattr_system_set,
-};
-