int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int error; struct iattr iattr; int rc; if (type == ACL_TYPE_ACCESS && acl) { /* * posix_acl_update_mode checks to see if the permissions * described by the ACL can be encoded into the * object's mode. If so, it sets "acl" to NULL * and "mode" to the new desired value. It is up to * us to propagate the new mode back to the server... */ error = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); if (error) { gossip_err("%s: posix_acl_update_mode err: %d\n", __func__, error); return error; } if (acl) { rc = __orangefs_set_acl(inode, acl, type); } else { iattr.ia_valid = ATTR_MODE; rc = orangefs_inode_setattr(inode, &iattr); } return rc; } else { return -EINVAL; } }
static int xfs_xattr_acl_set(struct dentry *dentry, const char *name, const void *value, size_t size, int flags, int type) { struct inode *inode = dentry->d_inode; struct posix_acl *acl = NULL; int error = 0; 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 (!value) goto set_acl; acl = posix_acl_from_xattr(&init_user_ns, 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); if (error) goto out_release; error = -EINVAL; if (acl->a_count > XFS_ACL_MAX_ENTRIES(XFS_M(inode->i_sb))) goto out_release; if (type == ACL_TYPE_ACCESS) { umode_t mode = inode->i_mode; struct posix_acl *old_acl = acl; error = posix_acl_update_mode(inode, &mode, &acl); if (!acl) posix_acl_release(old_acl); if (error) goto out_release; error = xfs_set_mode(inode, mode); if (error) goto out_release; } set_acl: error = xfs_set_acl(inode, type, acl); out_release: posix_acl_release(acl); out: return error; }
/* * Set the access or default ACL of an inode. */ int ocfs2_set_acl(handle_t *handle, struct inode *inode, struct buffer_head *di_bh, int type, struct posix_acl *acl, struct ocfs2_alloc_context *meta_ac, struct ocfs2_alloc_context *data_ac) { int name_index; void *value = NULL; size_t size = 0; int ret; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; switch (type) { case ACL_TYPE_ACCESS: name_index = OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { umode_t mode; ret = posix_acl_update_mode(inode, &mode, &acl); if (ret) return ret; ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode); if (ret) return ret; } break; case ACL_TYPE_DEFAULT: name_index = OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; default: return -EINVAL; } if (acl) { value = ocfs2_acl_to_xattr(acl, &size); if (IS_ERR(value)) return (int)PTR_ERR(value); } if (handle) ret = ocfs2_xattr_set_handle(handle, inode, di_bh, name_index, "", value, size, 0, meta_ac, data_ac); else ret = ocfs2_xattr_set(inode, name_index, "", value, size, 0); kfree(value); return ret; }
int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, int type) { int err; char *xattr_name; size_t size = 0; char *value = NULL; hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino); switch (type) { case ACL_TYPE_ACCESS: xattr_name = POSIX_ACL_XATTR_ACCESS; if (acl) { err = posix_acl_update_mode(inode, &inode->i_mode, &acl); if (err) return err; } err = 0; break; case ACL_TYPE_DEFAULT: xattr_name = POSIX_ACL_XATTR_DEFAULT; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; default: return -EINVAL; } if (acl) { size = posix_acl_xattr_size(acl->a_count); if (unlikely(size > HFSPLUS_MAX_INLINE_DATA_SIZE)) return -ENOMEM; value = (char *)hfsplus_alloc_attr_entry(); if (unlikely(!value)) return -ENOMEM; err = posix_acl_to_xattr(&init_user_ns, acl, value, size); if (unlikely(err < 0)) goto end_set_acl; } err = __hfsplus_setxattr(inode, xattr_name, value, size, 0); end_set_acl: hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value); if (!err) set_cached_acl(inode, type, acl); return err; }
int btrfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int ret; umode_t old_mode = inode->i_mode; if (type == ACL_TYPE_ACCESS && acl) { ret = posix_acl_update_mode(inode, &inode->i_mode, &acl); if (ret) return ret; } ret = __btrfs_set_acl(NULL, inode, acl, type); if (ret) inode->i_mode = old_mode; return ret; }
/* * Needs to be called with fs_mutex held */ static int __btrfs_set_acl(struct btrfs_trans_handle *trans, struct inode *inode, struct posix_acl *acl, int type) { int ret, size = 0; const char *name; char *value = NULL; switch (type) { case ACL_TYPE_ACCESS: name = XATTR_NAME_POSIX_ACL_ACCESS; if (acl) { ret = posix_acl_update_mode(inode, &inode->i_mode, &acl); if (ret) return ret; } ret = 0; break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) return acl ? -EINVAL : 0; name = XATTR_NAME_POSIX_ACL_DEFAULT; break; default: return -EINVAL; } if (acl) { size = posix_acl_xattr_size(acl->a_count); value = kmalloc(size, GFP_KERNEL); if (!value) { ret = -ENOMEM; goto out; } ret = posix_acl_to_xattr(&init_user_ns, acl, value, size); if (ret < 0) goto out; } ret = __btrfs_setxattr(trans, inode, name, value, size, 0); out: kfree(value); if (!ret) set_cached_acl(inode, type, acl); return ret; }
static int __f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl, struct page *ipage) { int name_index; void *value = NULL; size_t size = 0; int error; umode_t mode = inode->i_mode; switch (type) { case ACL_TYPE_ACCESS: name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl && !ipage) { error = posix_acl_update_mode(inode, &mode, &acl); if (error) return error; set_acl_inode(inode, mode); } break; case ACL_TYPE_DEFAULT: name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; default: return -EINVAL; } if (acl) { value = f2fs_acl_to_disk(F2FS_I_SB(inode), acl, &size); if (IS_ERR(value)) { clear_inode_flag(inode, FI_ACL_MODE); return PTR_ERR(value); } } error = f2fs_setxattr(inode, name_index, "", value, size, ipage, 0); kfree(value); if (!error) set_cached_acl(inode, type, acl); clear_inode_flag(inode, FI_ACL_MODE); return error; }
/* * inode->i_mutex: down */ static int ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl) { int name_index; void *value = NULL; size_t size = 0; int error; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (!test_opt(inode->i_sb, POSIX_ACL)) return 0; switch(type) { case ACL_TYPE_ACCESS: name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { error = posix_acl_update_mode(inode, &inode->i_mode, &acl); if (error) return error; inode->i_ctime = CURRENT_TIME_SEC; mark_inode_dirty(inode); } break; case ACL_TYPE_DEFAULT: name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; default: return -EINVAL; } if (acl) { value = ext2_acl_to_disk(acl, &size); if (IS_ERR(value)) return (int)PTR_ERR(value); } error = ext2_xattr_set(inode, name_index, "", value, size, 0); kfree(value); if (!error) set_cached_acl(inode, type, acl); return error; }
/* * Set the access or default ACL of an inode. * * inode->i_mutex: down unless called from ext4_new_inode */ static int __ext4_set_acl(handle_t *handle, struct inode *inode, int type, struct posix_acl *acl) { int name_index; void *value = NULL; size_t size = 0; int error; switch (type) { case ACL_TYPE_ACCESS: name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS; if (acl) { error = posix_acl_update_mode(inode, &inode->i_mode, &acl); if (error) return error; inode->i_ctime = ext4_current_time(inode); ext4_mark_inode_dirty(handle, inode); } break; case ACL_TYPE_DEFAULT: name_index = EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; default: return -EINVAL; } if (acl) { value = ext4_acl_to_disk(acl, &size); if (IS_ERR(value)) return (int)PTR_ERR(value); } error = ext4_xattr_set_handle(handle, inode, name_index, "", value, size, 0); kfree(value); if (!error) set_cached_acl(inode, type, acl); return error; }
static int __jfs_set_acl(tid_t tid, struct inode *inode, int type, struct posix_acl *acl) { char *ea_name; int rc; int size = 0; char *value = NULL; switch (type) { case ACL_TYPE_ACCESS: ea_name = XATTR_NAME_POSIX_ACL_ACCESS; if (acl) { rc = posix_acl_update_mode(inode, &inode->i_mode, &acl); if (rc) return rc; inode->i_ctime = current_time(inode); mark_inode_dirty(inode); } break; case ACL_TYPE_DEFAULT: ea_name = XATTR_NAME_POSIX_ACL_DEFAULT; break; default: return -EINVAL; } if (acl) { size = posix_acl_xattr_size(acl->a_count); value = kmalloc(size, GFP_KERNEL); if (!value) return -ENOMEM; rc = posix_acl_to_xattr(&init_user_ns, acl, value, size); if (rc < 0) goto out; } rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0); out: kfree(value); if (!rc) set_cached_acl(inode, type, acl); return rc; }
int reiserfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int error, error2; struct reiserfs_transaction_handle th; size_t jcreate_blocks; int size = acl ? posix_acl_xattr_size(acl->a_count) : 0; int update_mode = 0; umode_t mode = inode->i_mode; /* * Pessimism: We can't assume that anything from the xattr root up * has been created. */ jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) + reiserfs_xattr_nblocks(inode, size) * 2; reiserfs_write_lock(inode->i_sb); error = journal_begin(&th, inode->i_sb, jcreate_blocks); reiserfs_write_unlock(inode->i_sb); if (error == 0) { if (type == ACL_TYPE_ACCESS && acl) { error = posix_acl_update_mode(inode, &mode, &acl); if (error) goto unlock; update_mode = 1; } error = __reiserfs_set_acl(&th, inode, type, acl); if (!error && update_mode) inode->i_mode = mode; unlock: reiserfs_write_lock(inode->i_sb); error2 = journal_end(&th); reiserfs_write_unlock(inode->i_sb); if (error2) error = error2; } return error; }
int jffs2_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int rc, xprefix; switch (type) { case ACL_TYPE_ACCESS: xprefix = JFFS2_XPREFIX_ACL_ACCESS; if (acl) { umode_t mode; rc = posix_acl_update_mode(inode, &mode, &acl); if (rc) return rc; if (inode->i_mode != mode) { struct iattr attr; attr.ia_valid = ATTR_MODE | ATTR_CTIME; attr.ia_mode = mode; attr.ia_ctime = CURRENT_TIME_SEC; rc = jffs2_do_setattr(inode, &attr); if (rc < 0) return rc; } } break; case ACL_TYPE_DEFAULT: xprefix = JFFS2_XPREFIX_ACL_DEFAULT; if (!S_ISDIR(inode->i_mode)) return acl ? -EACCES : 0; break; default: return -EINVAL; } rc = __jffs2_set_acl(inode, xprefix, acl); if (!rc) set_cached_acl(inode, type, acl); return rc; }
int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type) { int ret = 0, size = 0; const char *name = NULL; char *value = NULL; struct iattr newattrs; umode_t new_mode = inode->i_mode, old_mode = inode->i_mode; switch (type) { case ACL_TYPE_ACCESS: name = XATTR_NAME_POSIX_ACL_ACCESS; if (acl) { ret = posix_acl_update_mode(inode, &new_mode, &acl); if (ret) goto out; } break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) { ret = acl ? -EINVAL : 0; goto out; } name = XATTR_NAME_POSIX_ACL_DEFAULT; break; default: ret = -EINVAL; goto out; } if (acl) { size = posix_acl_xattr_size(acl->a_count); value = kmalloc(size, GFP_NOFS); if (!value) { ret = -ENOMEM; goto out; } ret = posix_acl_to_xattr(&init_user_ns, acl, value, size); if (ret < 0) goto out_free; } if (new_mode != old_mode) { newattrs.ia_mode = new_mode; newattrs.ia_valid = ATTR_MODE; ret = __ceph_setattr(inode, &newattrs); if (ret) goto out_free; } ret = __ceph_setxattr(inode, name, value, size, 0); if (ret) { if (new_mode != old_mode) { newattrs.ia_mode = old_mode; newattrs.ia_valid = ATTR_MODE; __ceph_setattr(inode, &newattrs); } goto out_free; } ceph_set_cached_acl(inode, type, acl); out_free: kfree(value); out: return ret; }
static int v9fs_xattr_set_acl(const struct xattr_handler *handler, struct dentry *dentry, struct inode *inode, const char *name, const void *value, size_t size, int flags) { int retval; struct posix_acl *acl; struct v9fs_session_info *v9ses; v9ses = v9fs_dentry2v9ses(dentry); /* * set the attribute on the remote. Without even looking at the * xattr value. We leave it to the server to validate */ if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) return v9fs_xattr_set(dentry, handler->name, value, size, flags); if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { /* update the cached acl value */ acl = posix_acl_from_xattr(&init_user_ns, value, size); if (IS_ERR(acl)) return PTR_ERR(acl); else if (acl) { retval = posix_acl_valid(inode->i_sb->s_user_ns, acl); if (retval) goto err_out; } } else acl = NULL; switch (handler->flags) { case ACL_TYPE_ACCESS: if (acl) { struct iattr iattr; retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); if (retval) goto err_out; if (!acl) { /* * ACL can be represented * by the mode bits. So don't * update ACL. */ value = NULL; size = 0; } iattr.ia_valid = ATTR_MODE; /* FIXME should we update ctime ? * What is the following setxattr update the * mode ? */ v9fs_vfs_setattr_dotl(dentry, &iattr); } break; case ACL_TYPE_DEFAULT: if (!S_ISDIR(inode->i_mode)) { retval = acl ? -EINVAL : 0; goto err_out; } break; default: BUG(); } retval = v9fs_xattr_set(dentry, handler->name, value, size, flags); if (!retval) set_cached_acl(inode, handler->flags, acl); err_out: posix_acl_release(acl); return retval; }
int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); int error = 0; void *value = NULL; size_t size = 0; const char *name = NULL; switch (type) { case ACL_TYPE_ACCESS: name = XATTR_NAME_POSIX_ACL_ACCESS; if (acl) { umode_t mode; error = posix_acl_update_mode(inode, &mode, &acl); if (error) { gossip_err("%s: posix_acl_update_mode err: %d\n", __func__, error); return error; } if (inode->i_mode != mode) SetModeFlag(orangefs_inode); inode->i_mode = mode; mark_inode_dirty_sync(inode); } break; case ACL_TYPE_DEFAULT: name = XATTR_NAME_POSIX_ACL_DEFAULT; break; default: gossip_err("%s: invalid type %d!\n", __func__, type); return -EINVAL; } gossip_debug(GOSSIP_ACL_DEBUG, "%s: inode %pU, key %s type %d\n", __func__, get_khandle_from_ino(inode), name, type); if (acl) { size = posix_acl_xattr_size(acl->a_count); value = kmalloc(size, GFP_KERNEL); if (!value) return -ENOMEM; error = posix_acl_to_xattr(&init_user_ns, acl, value, size); if (error < 0) goto out; } gossip_debug(GOSSIP_ACL_DEBUG, "%s: name %s, value %p, size %zd, acl %p\n", __func__, name, value, size, acl); /* * Go ahead and set the extended attribute now. NOTE: Suppose acl * was NULL, then value will be NULL and size will be 0 and that * will xlate to a removexattr. However, we don't want removexattr * complain if attributes does not exist. */ error = orangefs_inode_setxattr(inode, name, value, size, 0); out: kfree(value); if (!error) set_cached_acl(inode, type, acl); return error; }