X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fext2%2Facl.c;h=da52b4a5db64005173124575e63161ed1d6c3d35;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=89d1df91411f6e9a35655c6a8feda7578c0d41db;hpb=70790a4b5cd6c0291e5b1a2836e2832d46036ac6;p=linux-2.6.git diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 89d1df914..da52b4a5d 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -4,6 +4,7 @@ * Copyright (C) 2001-2003 Andreas Gruenbacher, */ +#include #include #include #include @@ -149,7 +150,7 @@ ext2_iset_acl(struct inode *inode, struct posix_acl **i_acl, } /* - * inode->i_sem: don't care + * inode->i_mutex: don't care */ static struct posix_acl * ext2_get_acl(struct inode *inode, int type) @@ -194,8 +195,7 @@ ext2_get_acl(struct inode *inode, int type) acl = NULL; else acl = ERR_PTR(retval); - if (value) - kfree(value); + kfree(value); if (!IS_ERR(acl)) { switch(type) { @@ -212,7 +212,7 @@ ext2_get_acl(struct inode *inode, int type) } /* - * inode->i_sem: down + * inode->i_mutex: down */ static int ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) @@ -220,7 +220,7 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) struct ext2_inode_info *ei = EXT2_I(inode); int name_index; void *value = NULL; - size_t size; + size_t size = 0; int error; if (S_ISLNK(inode->i_mode)) @@ -255,8 +255,6 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) return -EINVAL; } if (acl) { - if (acl->a_count > EXT2_ACL_MAX_ENTRIES) - return -EINVAL; value = ext2_acl_to_disk(acl, &size); if (IS_ERR(value)) return (int)PTR_ERR(value); @@ -264,8 +262,7 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) error = ext2_xattr_set(inode, name_index, "", value, size, 0); - if (value) - kfree(value); + kfree(value); if (!error) { switch(type) { case ACL_TYPE_ACCESS: @@ -280,67 +277,33 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) return error; } -/* - * Inode operation permission(). - * - * inode->i_sem: don't care - */ -int -ext2_permission(struct inode *inode, int mask, struct nameidata *nd) +static int +ext2_check_acl(struct inode *inode, int mask) { - int mode = inode->i_mode; - - /* Nobody gets write access to a read-only fs */ - if ((mask & MAY_WRITE) && IS_RDONLY(inode) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; - /* Nobody gets write access to an immutable file */ - if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode)) - return -EACCES; - if (current->fsuid == inode->i_uid) { - mode >>= 6; - } else if (test_opt(inode->i_sb, POSIX_ACL)) { - struct posix_acl *acl; - - /* The access ACL cannot grant access if the group class - permission bits don't contain all requested permissions. */ - if (((mode >> 3) & mask & S_IRWXO) != mask) - goto check_groups; - acl = ext2_get_acl(inode, ACL_TYPE_ACCESS); - if (acl) { - int error = posix_acl_permission(inode, acl, mask); - posix_acl_release(acl); - if (error == -EACCES) - goto check_capabilities; - return error; - } else - goto check_groups; - } else { -check_groups: - if (in_group_p(inode->i_gid)) - mode >>= 3; + struct posix_acl *acl = ext2_get_acl(inode, ACL_TYPE_ACCESS); + + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl) { + int error = posix_acl_permission(inode, acl, mask); + posix_acl_release(acl); + return error; } - if ((mode & mask & S_IRWXO) == mask) - return 0; -check_capabilities: - /* Allowed to override Discretionary Access Control? */ - if (!(mask & MAY_EXEC) || - (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode)) - if (capable(CAP_DAC_OVERRIDE)) - return 0; - /* Read and search granted if capable(CAP_DAC_READ_SEARCH) */ - if (capable(CAP_DAC_READ_SEARCH) && ((mask == MAY_READ) || - (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))) - return 0; - return -EACCES; + return -EAGAIN; +} + +int +ext2_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + return generic_permission(inode, mask, ext2_check_acl); } /* * Initialize the ACLs of a new inode. Called from ext2_new_inode. * - * dir->i_sem: down - * inode->i_sem: up (access to inode is still exclusive) + * dir->i_mutex: down + * inode->i_mutex: up (access to inode is still exclusive) */ int ext2_init_acl(struct inode *inode, struct inode *dir) @@ -399,7 +362,7 @@ cleanup: * for directories) are added. There are no more bits available in the * file mode. * - * inode->i_sem: down + * inode->i_mutex: down */ int ext2_acl_chmod(struct inode *inode) @@ -429,28 +392,28 @@ ext2_acl_chmod(struct inode *inode) * Extended attribut handlers */ static size_t -ext2_xattr_list_acl_access(char *list, struct inode *inode, - const char *name, int name_len) +ext2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_size, + const char *name, size_t name_len) { - const size_t size = sizeof(XATTR_NAME_ACL_ACCESS); + const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS); if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; - if (list) - memcpy(list, XATTR_NAME_ACL_ACCESS, size); + if (list && size <= list_size) + memcpy(list, POSIX_ACL_XATTR_ACCESS, size); return size; } static size_t -ext2_xattr_list_acl_default(char *list, struct inode *inode, - const char *name, int name_len) +ext2_xattr_list_acl_default(struct inode *inode, char *list, size_t list_size, + const char *name, size_t name_len) { - const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT); + const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT); if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; - if (list) - memcpy(list, XATTR_NAME_ACL_DEFAULT, size); + if (list && size <= list_size) + memcpy(list, POSIX_ACL_XATTR_DEFAULT, size); return size; } @@ -541,45 +504,16 @@ ext2_xattr_set_acl_default(struct inode *inode, const char *name, return ext2_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size); } -struct ext2_xattr_handler ext2_xattr_acl_access_handler = { - .prefix = XATTR_NAME_ACL_ACCESS, +struct xattr_handler ext2_xattr_acl_access_handler = { + .prefix = POSIX_ACL_XATTR_ACCESS, .list = ext2_xattr_list_acl_access, .get = ext2_xattr_get_acl_access, .set = ext2_xattr_set_acl_access, }; -struct ext2_xattr_handler ext2_xattr_acl_default_handler = { - .prefix = XATTR_NAME_ACL_DEFAULT, +struct xattr_handler ext2_xattr_acl_default_handler = { + .prefix = POSIX_ACL_XATTR_DEFAULT, .list = ext2_xattr_list_acl_default, .get = ext2_xattr_get_acl_default, .set = ext2_xattr_set_acl_default, }; - -void -exit_ext2_acl(void) -{ - ext2_xattr_unregister(EXT2_XATTR_INDEX_POSIX_ACL_ACCESS, - &ext2_xattr_acl_access_handler); - ext2_xattr_unregister(EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT, - &ext2_xattr_acl_default_handler); -} - -int __init -init_ext2_acl(void) -{ - int error; - - error = ext2_xattr_register(EXT2_XATTR_INDEX_POSIX_ACL_ACCESS, - &ext2_xattr_acl_access_handler); - if (error) - goto fail; - error = ext2_xattr_register(EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT, - &ext2_xattr_acl_default_handler); - if (error) - goto fail; - return 0; - -fail: - exit_ext2_acl(); - return error; -}