Merge branch 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs xattr updates from Al Viro: "xattr stuff from Andreas This completes the switch to xattr_handler ->get()/->set() from ->getxattr/->setxattr/->removexattr" * 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: vfs: Remove {get,set,remove}xattr inode operations xattr: Stop calling {get,set,remove}xattr inode operations vfs: Check for the IOP_XATTR flag in listxattr xattr: Add __vfs_{get,set,remove}xattr helpers libfs: Use IOP_XATTR flag for empty directory handling vfs: Use IOP_XATTR flag for bad-inode handling vfs: Add IOP_XATTR inode operations flag vfs: Move xattr_resolve_name to the front of fs/xattr.c ecryptfs: Switch to generic xattr handlers sockfs: Get rid of getxattr iop sockfs: getxattr: Fail with -EOPNOTSUPP for invalid attribute names kernfs: Switch to generic xattr handlers hfs: Switch to generic xattr handlers jffs2: Remove jffs2_{get,set,remove}xattr macros xattr: Remove unnecessary NULL attribute name check
This commit is contained in:
@@ -967,9 +967,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
|
||||
.rename = v9fs_vfs_rename,
|
||||
.getattr = v9fs_vfs_getattr_dotl,
|
||||
.setattr = v9fs_vfs_setattr_dotl,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = v9fs_listxattr,
|
||||
.get_acl = v9fs_iop_get_acl,
|
||||
};
|
||||
@@ -977,9 +974,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
|
||||
const struct inode_operations v9fs_file_inode_operations_dotl = {
|
||||
.getattr = v9fs_vfs_getattr_dotl,
|
||||
.setattr = v9fs_vfs_setattr_dotl,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = v9fs_listxattr,
|
||||
.get_acl = v9fs_iop_get_acl,
|
||||
};
|
||||
@@ -989,8 +983,5 @@ const struct inode_operations v9fs_symlink_inode_operations_dotl = {
|
||||
.get_link = v9fs_vfs_get_link_dotl,
|
||||
.getattr = v9fs_vfs_getattr_dotl,
|
||||
.setattr = v9fs_vfs_setattr_dotl,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = v9fs_listxattr,
|
||||
};
|
||||
|
@@ -100,29 +100,12 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int bad_inode_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value, size_t size, int flags)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static ssize_t bad_inode_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *buffer, size_t size)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int bad_inode_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static const struct inode_operations bad_inode_ops =
|
||||
{
|
||||
.create = bad_inode_create,
|
||||
@@ -142,10 +125,7 @@ static const struct inode_operations bad_inode_ops =
|
||||
.permission = bad_inode_permission,
|
||||
.getattr = bad_inode_getattr,
|
||||
.setattr = bad_inode_setattr,
|
||||
.setxattr = bad_inode_setxattr,
|
||||
.getxattr = bad_inode_getxattr,
|
||||
.listxattr = bad_inode_listxattr,
|
||||
.removexattr = bad_inode_removexattr,
|
||||
};
|
||||
|
||||
|
||||
@@ -175,6 +155,7 @@ void make_bad_inode(struct inode *inode)
|
||||
inode->i_atime = inode->i_mtime = inode->i_ctime =
|
||||
current_fs_time(inode->i_sb);
|
||||
inode->i_op = &bad_inode_ops;
|
||||
inode->i_opflags &= ~IOP_XATTR;
|
||||
inode->i_fop = &bad_file_ops;
|
||||
}
|
||||
EXPORT_SYMBOL(make_bad_inode);
|
||||
|
@@ -10556,10 +10556,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
|
||||
.symlink = btrfs_symlink,
|
||||
.setattr = btrfs_setattr,
|
||||
.mknod = btrfs_mknod,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = btrfs_permission,
|
||||
.get_acl = btrfs_get_acl,
|
||||
.set_acl = btrfs_set_acl,
|
||||
@@ -10633,10 +10630,7 @@ static const struct address_space_operations btrfs_symlink_aops = {
|
||||
static const struct inode_operations btrfs_file_inode_operations = {
|
||||
.getattr = btrfs_getattr,
|
||||
.setattr = btrfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = btrfs_permission,
|
||||
.fiemap = btrfs_fiemap,
|
||||
.get_acl = btrfs_get_acl,
|
||||
@@ -10647,10 +10641,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
|
||||
.getattr = btrfs_getattr,
|
||||
.setattr = btrfs_setattr,
|
||||
.permission = btrfs_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = btrfs_get_acl,
|
||||
.set_acl = btrfs_set_acl,
|
||||
.update_time = btrfs_update_time,
|
||||
@@ -10661,10 +10652,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
|
||||
.getattr = btrfs_getattr,
|
||||
.setattr = btrfs_setattr,
|
||||
.permission = btrfs_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.update_time = btrfs_update_time,
|
||||
};
|
||||
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <linux/mount.h>
|
||||
#include <linux/statfs.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/xattr.h>
|
||||
#include "internal.h"
|
||||
|
||||
static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches);
|
||||
@@ -126,8 +127,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
|
||||
if (d_is_negative(root) ||
|
||||
!d_backing_inode(root)->i_op->lookup ||
|
||||
!d_backing_inode(root)->i_op->mkdir ||
|
||||
!d_backing_inode(root)->i_op->setxattr ||
|
||||
!d_backing_inode(root)->i_op->getxattr ||
|
||||
!(d_backing_inode(root)->i_opflags & IOP_XATTR) ||
|
||||
!root->d_sb->s_op->statfs ||
|
||||
!root->d_sb->s_op->sync_fs)
|
||||
goto error_unsupported;
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <linux/namei.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/xattr.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define CACHEFILES_KEYBUF_SIZE 512
|
||||
@@ -799,8 +800,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
||||
}
|
||||
|
||||
ret = -EPERM;
|
||||
if (!d_backing_inode(subdir)->i_op->setxattr ||
|
||||
!d_backing_inode(subdir)->i_op->getxattr ||
|
||||
if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
|
||||
!d_backing_inode(subdir)->i_op->lookup ||
|
||||
!d_backing_inode(subdir)->i_op->mkdir ||
|
||||
!d_backing_inode(subdir)->i_op->create ||
|
||||
|
@@ -1486,10 +1486,7 @@ const struct inode_operations ceph_dir_iops = {
|
||||
.permission = ceph_permission,
|
||||
.getattr = ceph_getattr,
|
||||
.setattr = ceph_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ceph_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ceph_get_acl,
|
||||
.set_acl = ceph_set_acl,
|
||||
.mknod = ceph_mknod,
|
||||
|
@@ -94,10 +94,7 @@ const struct inode_operations ceph_file_iops = {
|
||||
.permission = ceph_permission,
|
||||
.setattr = ceph_setattr,
|
||||
.getattr = ceph_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ceph_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ceph_get_acl,
|
||||
.set_acl = ceph_set_acl,
|
||||
};
|
||||
@@ -1885,10 +1882,7 @@ static const struct inode_operations ceph_symlink_iops = {
|
||||
.get_link = simple_get_link,
|
||||
.setattr = ceph_setattr,
|
||||
.getattr = ceph_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ceph_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
int __ceph_setattr(struct inode *inode, struct iattr *attr)
|
||||
|
@@ -901,30 +901,21 @@ const struct inode_operations cifs_dir_inode_ops = {
|
||||
.setattr = cifs_setattr,
|
||||
.symlink = cifs_symlink,
|
||||
.mknod = cifs_mknod,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = cifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations cifs_file_inode_ops = {
|
||||
.setattr = cifs_setattr,
|
||||
.getattr = cifs_getattr,
|
||||
.permission = cifs_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = cifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations cifs_symlink_inode_ops = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = cifs_get_link,
|
||||
.permission = cifs_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = cifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
static int cifs_clone_file_range(struct file *src_file, loff_t off,
|
||||
|
@@ -715,4 +715,6 @@ int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
|
||||
int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
|
||||
loff_t offset);
|
||||
|
||||
extern const struct xattr_handler *ecryptfs_xattr_handlers[];
|
||||
|
||||
#endif /* #ifndef ECRYPTFS_KERNEL_H */
|
||||
|
@@ -1005,15 +1005,14 @@ ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc;
|
||||
struct dentry *lower_dentry;
|
||||
|
||||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
if (!d_inode(lower_dentry)->i_op->setxattr) {
|
||||
if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = vfs_setxattr(lower_dentry, name, value, size, flags);
|
||||
if (!rc && inode)
|
||||
fsstack_copy_attr_all(inode, d_inode(lower_dentry));
|
||||
@@ -1025,15 +1024,14 @@ ssize_t
|
||||
ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
|
||||
const char *name, void *value, size_t size)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc;
|
||||
|
||||
if (!lower_inode->i_op->getxattr) {
|
||||
if (!(lower_inode->i_opflags & IOP_XATTR)) {
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
inode_lock(lower_inode);
|
||||
rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
|
||||
name, value, size);
|
||||
rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
|
||||
inode_unlock(lower_inode);
|
||||
out:
|
||||
return rc;
|
||||
@@ -1066,19 +1064,22 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ecryptfs_removexattr(struct dentry *dentry, const char *name)
|
||||
static int ecryptfs_removexattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc;
|
||||
struct dentry *lower_dentry;
|
||||
struct inode *lower_inode;
|
||||
|
||||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
if (!d_inode(lower_dentry)->i_op->removexattr) {
|
||||
lower_inode = ecryptfs_inode_to_lower(inode);
|
||||
if (!(lower_inode->i_opflags & IOP_XATTR)) {
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
inode_lock(d_inode(lower_dentry));
|
||||
rc = d_inode(lower_dentry)->i_op->removexattr(lower_dentry, name);
|
||||
inode_unlock(d_inode(lower_dentry));
|
||||
inode_lock(lower_inode);
|
||||
rc = __vfs_removexattr(lower_dentry, name);
|
||||
inode_unlock(lower_inode);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
@@ -1089,10 +1090,7 @@ const struct inode_operations ecryptfs_symlink_iops = {
|
||||
.permission = ecryptfs_permission,
|
||||
.setattr = ecryptfs_setattr,
|
||||
.getattr = ecryptfs_getattr_link,
|
||||
.setxattr = ecryptfs_setxattr,
|
||||
.getxattr = ecryptfs_getxattr,
|
||||
.listxattr = ecryptfs_listxattr,
|
||||
.removexattr = ecryptfs_removexattr
|
||||
};
|
||||
|
||||
const struct inode_operations ecryptfs_dir_iops = {
|
||||
@@ -1107,18 +1105,43 @@ const struct inode_operations ecryptfs_dir_iops = {
|
||||
.rename = ecryptfs_rename,
|
||||
.permission = ecryptfs_permission,
|
||||
.setattr = ecryptfs_setattr,
|
||||
.setxattr = ecryptfs_setxattr,
|
||||
.getxattr = ecryptfs_getxattr,
|
||||
.listxattr = ecryptfs_listxattr,
|
||||
.removexattr = ecryptfs_removexattr
|
||||
};
|
||||
|
||||
const struct inode_operations ecryptfs_main_iops = {
|
||||
.permission = ecryptfs_permission,
|
||||
.setattr = ecryptfs_setattr,
|
||||
.getattr = ecryptfs_getattr,
|
||||
.setxattr = ecryptfs_setxattr,
|
||||
.getxattr = ecryptfs_getxattr,
|
||||
.listxattr = ecryptfs_listxattr,
|
||||
.removexattr = ecryptfs_removexattr
|
||||
};
|
||||
|
||||
static int ecryptfs_xattr_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *buffer, size_t size)
|
||||
{
|
||||
return ecryptfs_getxattr(dentry, inode, name, buffer, size);
|
||||
}
|
||||
|
||||
static int ecryptfs_xattr_set(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value, size_t size,
|
||||
int flags)
|
||||
{
|
||||
if (value)
|
||||
return ecryptfs_setxattr(dentry, inode, name, value, size, flags);
|
||||
else {
|
||||
BUG_ON(flags != XATTR_REPLACE);
|
||||
return ecryptfs_removexattr(dentry, inode, name);
|
||||
}
|
||||
}
|
||||
|
||||
const struct xattr_handler ecryptfs_xattr_handler = {
|
||||
.prefix = "", /* match anything */
|
||||
.get = ecryptfs_xattr_get,
|
||||
.set = ecryptfs_xattr_set,
|
||||
};
|
||||
|
||||
const struct xattr_handler *ecryptfs_xattr_handlers[] = {
|
||||
&ecryptfs_xattr_handler,
|
||||
NULL
|
||||
};
|
||||
|
@@ -529,6 +529,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
||||
/* ->kill_sb() will take care of sbi after that point */
|
||||
sbi = NULL;
|
||||
s->s_op = &ecryptfs_sops;
|
||||
s->s_xattr = ecryptfs_xattr_handlers;
|
||||
s->s_d_op = &ecryptfs_dops;
|
||||
|
||||
err = "Reading sb failed";
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include <linux/file.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
@@ -422,7 +423,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
|
||||
struct inode *lower_inode = d_inode(lower_dentry);
|
||||
int rc;
|
||||
|
||||
if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
|
||||
if (!(lower_inode->i_opflags & IOP_XATTR)) {
|
||||
printk(KERN_WARNING
|
||||
"No support for setting xattr in lower filesystem\n");
|
||||
rc = -ENOSYS;
|
||||
@@ -436,15 +437,13 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
|
||||
goto out;
|
||||
}
|
||||
inode_lock(lower_inode);
|
||||
size = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
|
||||
ECRYPTFS_XATTR_NAME,
|
||||
xattr_virt, PAGE_SIZE);
|
||||
size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
|
||||
xattr_virt, PAGE_SIZE);
|
||||
if (size < 0)
|
||||
size = 8;
|
||||
put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
|
||||
rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode,
|
||||
ECRYPTFS_XATTR_NAME,
|
||||
xattr_virt, size, 0);
|
||||
rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
|
||||
xattr_virt, size, 0);
|
||||
inode_unlock(lower_inode);
|
||||
if (rc)
|
||||
printk(KERN_ERR "Error whilst attempting to write inode size "
|
||||
|
@@ -241,10 +241,7 @@ const struct file_operations ext2_file_operations = {
|
||||
|
||||
const struct inode_operations ext2_file_inode_operations = {
|
||||
#ifdef CONFIG_EXT2_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
.setattr = ext2_setattr,
|
||||
.get_acl = ext2_get_acl,
|
||||
|
@@ -428,10 +428,7 @@ const struct inode_operations ext2_dir_inode_operations = {
|
||||
.mknod = ext2_mknod,
|
||||
.rename = ext2_rename,
|
||||
#ifdef CONFIG_EXT2_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
.setattr = ext2_setattr,
|
||||
.get_acl = ext2_get_acl,
|
||||
@@ -441,10 +438,7 @@ const struct inode_operations ext2_dir_inode_operations = {
|
||||
|
||||
const struct inode_operations ext2_special_inode_operations = {
|
||||
#ifdef CONFIG_EXT2_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
.setattr = ext2_setattr,
|
||||
.get_acl = ext2_get_acl,
|
||||
|
@@ -25,10 +25,7 @@ const struct inode_operations ext2_symlink_inode_operations = {
|
||||
.get_link = page_get_link,
|
||||
.setattr = ext2_setattr,
|
||||
#ifdef CONFIG_EXT2_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -37,9 +34,6 @@ const struct inode_operations ext2_fast_symlink_inode_operations = {
|
||||
.get_link = simple_get_link,
|
||||
.setattr = ext2_setattr,
|
||||
#ifdef CONFIG_EXT2_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
@@ -706,10 +706,7 @@ const struct file_operations ext4_file_operations = {
|
||||
const struct inode_operations ext4_file_inode_operations = {
|
||||
.setattr = ext4_setattr,
|
||||
.getattr = ext4_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ext4_get_acl,
|
||||
.set_acl = ext4_set_acl,
|
||||
.fiemap = ext4_fiemap,
|
||||
|
@@ -3880,10 +3880,7 @@ const struct inode_operations ext4_dir_inode_operations = {
|
||||
.tmpfile = ext4_tmpfile,
|
||||
.rename2 = ext4_rename2,
|
||||
.setattr = ext4_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ext4_get_acl,
|
||||
.set_acl = ext4_set_acl,
|
||||
.fiemap = ext4_fiemap,
|
||||
@@ -3891,10 +3888,7 @@ const struct inode_operations ext4_dir_inode_operations = {
|
||||
|
||||
const struct inode_operations ext4_special_inode_operations = {
|
||||
.setattr = ext4_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ext4_get_acl,
|
||||
.set_acl = ext4_set_acl,
|
||||
};
|
||||
|
@@ -86,28 +86,19 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = ext4_encrypted_get_link,
|
||||
.setattr = ext4_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations ext4_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = page_get_link,
|
||||
.setattr = ext4_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations ext4_fast_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = simple_get_link,
|
||||
.setattr = ext4_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
@@ -732,10 +732,7 @@ const struct inode_operations f2fs_file_inode_operations = {
|
||||
.get_acl = f2fs_get_acl,
|
||||
.set_acl = f2fs_set_acl,
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
.fiemap = f2fs_fiemap,
|
||||
};
|
||||
|
@@ -1080,10 +1080,7 @@ const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
|
||||
.getattr = f2fs_getattr,
|
||||
.setattr = f2fs_setattr,
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1103,10 +1100,7 @@ const struct inode_operations f2fs_dir_inode_operations = {
|
||||
.get_acl = f2fs_get_acl,
|
||||
.set_acl = f2fs_set_acl,
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1116,10 +1110,7 @@ const struct inode_operations f2fs_symlink_inode_operations = {
|
||||
.getattr = f2fs_getattr,
|
||||
.setattr = f2fs_setattr,
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -1129,9 +1120,6 @@ const struct inode_operations f2fs_special_inode_operations = {
|
||||
.get_acl = f2fs_get_acl,
|
||||
.set_acl = f2fs_set_acl,
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
@@ -1801,10 +1801,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
|
||||
.mknod = fuse_mknod,
|
||||
.permission = fuse_permission,
|
||||
.getattr = fuse_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = fuse_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = fuse_get_acl,
|
||||
.set_acl = fuse_set_acl,
|
||||
};
|
||||
@@ -1824,10 +1821,7 @@ static const struct inode_operations fuse_common_inode_operations = {
|
||||
.setattr = fuse_setattr,
|
||||
.permission = fuse_permission,
|
||||
.getattr = fuse_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = fuse_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = fuse_get_acl,
|
||||
.set_acl = fuse_set_acl,
|
||||
};
|
||||
@@ -1837,10 +1831,7 @@ static const struct inode_operations fuse_symlink_inode_operations = {
|
||||
.get_link = fuse_get_link,
|
||||
.readlink = generic_readlink,
|
||||
.getattr = fuse_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = fuse_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
void fuse_init_common(struct inode *inode)
|
||||
|
@@ -2040,10 +2040,7 @@ const struct inode_operations gfs2_file_iops = {
|
||||
.permission = gfs2_permission,
|
||||
.setattr = gfs2_setattr,
|
||||
.getattr = gfs2_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = gfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = gfs2_fiemap,
|
||||
.get_acl = gfs2_get_acl,
|
||||
.set_acl = gfs2_set_acl,
|
||||
@@ -2062,10 +2059,7 @@ const struct inode_operations gfs2_dir_iops = {
|
||||
.permission = gfs2_permission,
|
||||
.setattr = gfs2_setattr,
|
||||
.getattr = gfs2_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = gfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = gfs2_fiemap,
|
||||
.get_acl = gfs2_get_acl,
|
||||
.set_acl = gfs2_set_acl,
|
||||
@@ -2078,10 +2072,7 @@ const struct inode_operations gfs2_symlink_iops = {
|
||||
.permission = gfs2_permission,
|
||||
.setattr = gfs2_setattr,
|
||||
.getattr = gfs2_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = gfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = gfs2_fiemap,
|
||||
};
|
||||
|
||||
|
@@ -13,9 +13,13 @@
|
||||
#include "hfs_fs.h"
|
||||
#include "btree.h"
|
||||
|
||||
int hfs_setxattr(struct dentry *unused, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
enum hfs_xattr_type {
|
||||
HFS_TYPE,
|
||||
HFS_CREATOR,
|
||||
};
|
||||
|
||||
static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
struct hfs_find_data fd;
|
||||
hfs_cat_rec rec;
|
||||
@@ -36,18 +40,22 @@ int hfs_setxattr(struct dentry *unused, struct inode *inode,
|
||||
sizeof(struct hfs_cat_file));
|
||||
file = &rec.file;
|
||||
|
||||
if (!strcmp(name, "hfs.type")) {
|
||||
switch (type) {
|
||||
case HFS_TYPE:
|
||||
if (size == 4)
|
||||
memcpy(&file->UsrWds.fdType, value, 4);
|
||||
else
|
||||
res = -ERANGE;
|
||||
} else if (!strcmp(name, "hfs.creator")) {
|
||||
break;
|
||||
|
||||
case HFS_CREATOR:
|
||||
if (size == 4)
|
||||
memcpy(&file->UsrWds.fdCreator, value, 4);
|
||||
else
|
||||
res = -ERANGE;
|
||||
} else
|
||||
res = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!res)
|
||||
hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
|
||||
sizeof(struct hfs_cat_file));
|
||||
@@ -56,8 +64,8 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode,
|
||||
const char *name, void *value, size_t size)
|
||||
static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
|
||||
void *value, size_t size)
|
||||
{
|
||||
struct hfs_find_data fd;
|
||||
hfs_cat_rec rec;
|
||||
@@ -80,41 +88,64 @@ ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode,
|
||||
}
|
||||
file = &rec.file;
|
||||
|
||||
if (!strcmp(name, "hfs.type")) {
|
||||
switch (type) {
|
||||
case HFS_TYPE:
|
||||
if (size >= 4) {
|
||||
memcpy(value, &file->UsrWds.fdType, 4);
|
||||
res = 4;
|
||||
} else
|
||||
res = size ? -ERANGE : 4;
|
||||
} else if (!strcmp(name, "hfs.creator")) {
|
||||
break;
|
||||
|
||||
case HFS_CREATOR:
|
||||
if (size >= 4) {
|
||||
memcpy(value, &file->UsrWds.fdCreator, 4);
|
||||
res = 4;
|
||||
} else
|
||||
res = size ? -ERANGE : 4;
|
||||
} else
|
||||
res = -ENODATA;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
if (size)
|
||||
hfs_find_exit(&fd);
|
||||
return res;
|
||||
}
|
||||
|
||||
#define HFS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
|
||||
|
||||
ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
static int hfs_xattr_get(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *name, void *value, size_t size)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
return __hfs_getxattr(inode, handler->flags, value, size);
|
||||
}
|
||||
|
||||
if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
|
||||
static int hfs_xattr_set(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *name, const void *value, size_t size,
|
||||
int flags)
|
||||
{
|
||||
if (!value)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!buffer || !size)
|
||||
return HFS_ATTRLIST_SIZE;
|
||||
if (size < HFS_ATTRLIST_SIZE)
|
||||
return -ERANGE;
|
||||
strcpy(buffer, "hfs.type");
|
||||
strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
|
||||
|
||||
return HFS_ATTRLIST_SIZE;
|
||||
return __hfs_setxattr(inode, handler->flags, value, size, flags);
|
||||
}
|
||||
|
||||
static const struct xattr_handler hfs_creator_handler = {
|
||||
.name = "hfs.creator",
|
||||
.flags = HFS_CREATOR,
|
||||
.get = hfs_xattr_get,
|
||||
.set = hfs_xattr_set,
|
||||
};
|
||||
|
||||
static const struct xattr_handler hfs_type_handler = {
|
||||
.name = "hfs.type",
|
||||
.flags = HFS_TYPE,
|
||||
.get = hfs_xattr_get,
|
||||
.set = hfs_xattr_set,
|
||||
};
|
||||
|
||||
const struct xattr_handler *hfs_xattr_handlers[] = {
|
||||
&hfs_creator_handler,
|
||||
&hfs_type_handler,
|
||||
NULL
|
||||
};
|
||||
|
@@ -212,11 +212,7 @@ extern void hfs_evict_inode(struct inode *);
|
||||
extern void hfs_delete_inode(struct inode *);
|
||||
|
||||
/* attr.c */
|
||||
extern int hfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
extern ssize_t hfs_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *value, size_t size);
|
||||
extern ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
|
||||
extern const struct xattr_handler *hfs_xattr_handlers[];
|
||||
|
||||
/* mdb.c */
|
||||
extern int hfs_mdb_get(struct super_block *);
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/xattr.h>
|
||||
|
||||
#include "hfs_fs.h"
|
||||
#include "btree.h"
|
||||
@@ -687,7 +688,5 @@ static const struct file_operations hfs_file_operations = {
|
||||
static const struct inode_operations hfs_file_inode_operations = {
|
||||
.lookup = hfs_file_lookup,
|
||||
.setattr = hfs_inode_setattr,
|
||||
.setxattr = hfs_setxattr,
|
||||
.getxattr = hfs_getxattr,
|
||||
.listxattr = hfs_listxattr,
|
||||
.listxattr = generic_listxattr,
|
||||
};
|
||||
|
@@ -406,6 +406,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
}
|
||||
|
||||
sb->s_op = &hfs_super_operations;
|
||||
sb->s_xattr = hfs_xattr_handlers;
|
||||
sb->s_flags |= MS_NODIRATIME;
|
||||
mutex_init(&sbi->bitmap_lock);
|
||||
|
||||
|
@@ -562,10 +562,7 @@ const struct inode_operations hfsplus_dir_inode_operations = {
|
||||
.symlink = hfsplus_symlink,
|
||||
.mknod = hfsplus_mknod,
|
||||
.rename = hfsplus_rename,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = hfsplus_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
|
||||
.get_acl = hfsplus_get_posix_acl,
|
||||
.set_acl = hfsplus_set_posix_acl,
|
||||
|
@@ -333,10 +333,7 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
|
||||
|
||||
static const struct inode_operations hfsplus_file_inode_operations = {
|
||||
.setattr = hfsplus_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = hfsplus_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
|
||||
.get_acl = hfsplus_get_posix_acl,
|
||||
.set_acl = hfsplus_set_posix_acl,
|
||||
|
@@ -140,6 +140,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
|
||||
inode->i_fop = &no_open_fops;
|
||||
inode->__i_nlink = 1;
|
||||
inode->i_opflags = 0;
|
||||
if (sb->s_xattr)
|
||||
inode->i_opflags |= IOP_XATTR;
|
||||
i_uid_write(inode, 0);
|
||||
i_gid_write(inode, 0);
|
||||
atomic_set(&inode->i_writecount, 0);
|
||||
|
@@ -61,10 +61,7 @@ const struct inode_operations jffs2_dir_inode_operations =
|
||||
.get_acl = jffs2_get_acl,
|
||||
.set_acl = jffs2_set_acl,
|
||||
.setattr = jffs2_setattr,
|
||||
.setxattr = jffs2_setxattr,
|
||||
.getxattr = jffs2_getxattr,
|
||||
.listxattr = jffs2_listxattr,
|
||||
.removexattr = jffs2_removexattr
|
||||
};
|
||||
|
||||
/***********************************************************************/
|
||||
|
@@ -66,10 +66,7 @@ const struct inode_operations jffs2_file_inode_operations =
|
||||
.get_acl = jffs2_get_acl,
|
||||
.set_acl = jffs2_set_acl,
|
||||
.setattr = jffs2_setattr,
|
||||
.setxattr = jffs2_setxattr,
|
||||
.getxattr = jffs2_getxattr,
|
||||
.listxattr = jffs2_listxattr,
|
||||
.removexattr = jffs2_removexattr
|
||||
};
|
||||
|
||||
const struct address_space_operations jffs2_file_address_operations =
|
||||
|
@@ -16,8 +16,5 @@ const struct inode_operations jffs2_symlink_inode_operations =
|
||||
.readlink = generic_readlink,
|
||||
.get_link = simple_get_link,
|
||||
.setattr = jffs2_setattr,
|
||||
.setxattr = jffs2_setxattr,
|
||||
.getxattr = jffs2_getxattr,
|
||||
.listxattr = jffs2_listxattr,
|
||||
.removexattr = jffs2_removexattr
|
||||
};
|
||||
|
@@ -99,9 +99,6 @@ extern const struct xattr_handler jffs2_user_xattr_handler;
|
||||
extern const struct xattr_handler jffs2_trusted_xattr_handler;
|
||||
|
||||
extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
|
||||
#define jffs2_getxattr generic_getxattr
|
||||
#define jffs2_setxattr generic_setxattr
|
||||
#define jffs2_removexattr generic_removexattr
|
||||
|
||||
#else
|
||||
|
||||
@@ -116,9 +113,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
|
||||
|
||||
#define jffs2_xattr_handlers NULL
|
||||
#define jffs2_listxattr NULL
|
||||
#define jffs2_getxattr NULL
|
||||
#define jffs2_setxattr NULL
|
||||
#define jffs2_removexattr NULL
|
||||
|
||||
#endif /* CONFIG_JFFS2_FS_XATTR */
|
||||
|
||||
|
@@ -140,10 +140,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||
}
|
||||
|
||||
const struct inode_operations jfs_file_inode_operations = {
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = jfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.setattr = jfs_setattr,
|
||||
#ifdef CONFIG_JFS_POSIX_ACL
|
||||
.get_acl = jfs_get_acl,
|
||||
|
@@ -1537,10 +1537,7 @@ const struct inode_operations jfs_dir_inode_operations = {
|
||||
.rmdir = jfs_rmdir,
|
||||
.mknod = jfs_mknod,
|
||||
.rename = jfs_rename,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = jfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.setattr = jfs_setattr,
|
||||
#ifdef CONFIG_JFS_POSIX_ACL
|
||||
.get_acl = jfs_get_acl,
|
||||
|
@@ -25,19 +25,13 @@ const struct inode_operations jfs_fast_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = simple_get_link,
|
||||
.setattr = jfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = jfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations jfs_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = page_get_link,
|
||||
.setattr = jfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = jfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
|
@@ -1126,9 +1126,6 @@ const struct inode_operations kernfs_dir_iops = {
|
||||
.permission = kernfs_iop_permission,
|
||||
.setattr = kernfs_iop_setattr,
|
||||
.getattr = kernfs_iop_getattr,
|
||||
.setxattr = kernfs_iop_setxattr,
|
||||
.removexattr = kernfs_iop_removexattr,
|
||||
.getxattr = kernfs_iop_getxattr,
|
||||
.listxattr = kernfs_iop_listxattr,
|
||||
|
||||
.mkdir = kernfs_iop_mkdir,
|
||||
|
@@ -28,9 +28,6 @@ static const struct inode_operations kernfs_iops = {
|
||||
.permission = kernfs_iop_permission,
|
||||
.setattr = kernfs_iop_setattr,
|
||||
.getattr = kernfs_iop_getattr,
|
||||
.setxattr = kernfs_iop_setxattr,
|
||||
.removexattr = kernfs_iop_removexattr,
|
||||
.getxattr = kernfs_iop_getxattr,
|
||||
.listxattr = kernfs_iop_listxattr,
|
||||
};
|
||||
|
||||
@@ -138,17 +135,12 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
|
||||
static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
|
||||
u32 *secdata_len)
|
||||
{
|
||||
struct kernfs_iattrs *attrs;
|
||||
void *old_secdata;
|
||||
size_t old_secdata_len;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
old_secdata = attrs->ia_secdata;
|
||||
old_secdata_len = attrs->ia_secdata_len;
|
||||
|
||||
@@ -160,71 +152,6 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
void *secdata;
|
||||
int error;
|
||||
u32 secdata_len = 0;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
|
||||
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
|
||||
error = security_inode_setsecurity(inode, suffix,
|
||||
value, size, flags);
|
||||
if (error)
|
||||
return error;
|
||||
error = security_inode_getsecctx(inode,
|
||||
&secdata, &secdata_len);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
mutex_lock(&kernfs_mutex);
|
||||
error = kernfs_node_setsecdata(kn, &secdata, &secdata_len);
|
||||
mutex_unlock(&kernfs_mutex);
|
||||
|
||||
if (secdata)
|
||||
security_release_secctx(secdata, secdata_len);
|
||||
return error;
|
||||
} else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
|
||||
return simple_xattr_set(&attrs->xattrs, name, value, size,
|
||||
flags);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
struct kernfs_node *kn = dentry->d_fsdata;
|
||||
struct kernfs_iattrs *attrs;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);
|
||||
}
|
||||
|
||||
ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode,
|
||||
const char *name, void *buf, size_t size)
|
||||
{
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_get(&attrs->xattrs, name, buf, size);
|
||||
}
|
||||
|
||||
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
|
||||
{
|
||||
struct kernfs_node *kn = dentry->d_fsdata;
|
||||
@@ -376,3 +303,83 @@ int kernfs_iop_permission(struct inode *inode, int mask)
|
||||
|
||||
return generic_permission(inode, mask);
|
||||
}
|
||||
|
||||
static int kernfs_xattr_get(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *suffix, void *value, size_t size)
|
||||
{
|
||||
const char *name = xattr_full_name(handler, suffix);
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_get(&attrs->xattrs, name, value, size);
|
||||
}
|
||||
|
||||
static int kernfs_xattr_set(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *suffix, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
const char *name = xattr_full_name(handler, suffix);
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_set(&attrs->xattrs, name, value, size, flags);
|
||||
}
|
||||
|
||||
const struct xattr_handler kernfs_trusted_xattr_handler = {
|
||||
.prefix = XATTR_TRUSTED_PREFIX,
|
||||
.get = kernfs_xattr_get,
|
||||
.set = kernfs_xattr_set,
|
||||
};
|
||||
|
||||
static int kernfs_security_xattr_set(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *suffix, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
void *secdata;
|
||||
u32 secdata_len = 0;
|
||||
int error;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
error = security_inode_setsecurity(inode, suffix, value, size, flags);
|
||||
if (error)
|
||||
return error;
|
||||
error = security_inode_getsecctx(inode, &secdata, &secdata_len);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
mutex_lock(&kernfs_mutex);
|
||||
error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
|
||||
mutex_unlock(&kernfs_mutex);
|
||||
|
||||
if (secdata)
|
||||
security_release_secctx(secdata, secdata_len);
|
||||
return error;
|
||||
}
|
||||
|
||||
const struct xattr_handler kernfs_security_xattr_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.get = kernfs_xattr_get,
|
||||
.set = kernfs_security_xattr_set,
|
||||
};
|
||||
|
||||
const struct xattr_handler *kernfs_xattr_handlers[] = {
|
||||
&kernfs_trusted_xattr_handler,
|
||||
&kernfs_security_xattr_handler,
|
||||
NULL
|
||||
};
|
||||
|
@@ -76,17 +76,12 @@ extern struct kmem_cache *kernfs_node_cache;
|
||||
/*
|
||||
* inode.c
|
||||
*/
|
||||
extern const struct xattr_handler *kernfs_xattr_handlers[];
|
||||
void kernfs_evict_inode(struct inode *inode);
|
||||
int kernfs_iop_permission(struct inode *inode, int mask);
|
||||
int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);
|
||||
int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct kstat *stat);
|
||||
int kernfs_iop_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
int kernfs_iop_removexattr(struct dentry *dentry, const char *name);
|
||||
ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *buf, size_t size);
|
||||
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size);
|
||||
|
||||
/*
|
||||
|
@@ -158,6 +158,7 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
|
||||
sb->s_blocksize_bits = PAGE_SHIFT;
|
||||
sb->s_magic = magic;
|
||||
sb->s_op = &kernfs_sops;
|
||||
sb->s_xattr = kernfs_xattr_handlers;
|
||||
sb->s_time_gran = 1;
|
||||
|
||||
/* get root inode, initialize and unlock it */
|
||||
|
@@ -134,9 +134,6 @@ static const char *kernfs_iop_get_link(struct dentry *dentry,
|
||||
}
|
||||
|
||||
const struct inode_operations kernfs_symlink_iops = {
|
||||
.setxattr = kernfs_iop_setxattr,
|
||||
.removexattr = kernfs_iop_removexattr,
|
||||
.getxattr = kernfs_iop_getxattr,
|
||||
.listxattr = kernfs_iop_listxattr,
|
||||
.readlink = generic_readlink,
|
||||
.get_link = kernfs_iop_get_link,
|
||||
|
29
fs/libfs.c
29
fs/libfs.c
@@ -236,8 +236,8 @@ static const struct super_operations simple_super_operations = {
|
||||
* Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
|
||||
* will never be mountable)
|
||||
*/
|
||||
struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
|
||||
const struct super_operations *ops,
|
||||
struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, char *name,
|
||||
const struct super_operations *ops, const struct xattr_handler **xattr,
|
||||
const struct dentry_operations *dops, unsigned long magic)
|
||||
{
|
||||
struct super_block *s;
|
||||
@@ -254,6 +254,7 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
|
||||
s->s_blocksize_bits = PAGE_SHIFT;
|
||||
s->s_magic = magic;
|
||||
s->s_op = ops ? ops : &simple_super_operations;
|
||||
s->s_xattr = xattr;
|
||||
s->s_time_gran = 1;
|
||||
root = new_inode(s);
|
||||
if (!root)
|
||||
@@ -281,7 +282,7 @@ Enomem:
|
||||
deactivate_locked_super(s);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
EXPORT_SYMBOL(mount_pseudo);
|
||||
EXPORT_SYMBOL(mount_pseudo_xattr);
|
||||
|
||||
int simple_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
@@ -1149,24 +1150,6 @@ static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static int empty_dir_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static ssize_t empty_dir_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *value, size_t size)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int empty_dir_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
@@ -1177,9 +1160,6 @@ static const struct inode_operations empty_dir_inode_operations = {
|
||||
.permission = generic_permission,
|
||||
.setattr = empty_dir_setattr,
|
||||
.getattr = empty_dir_getattr,
|
||||
.setxattr = empty_dir_setxattr,
|
||||
.getxattr = empty_dir_getxattr,
|
||||
.removexattr = empty_dir_removexattr,
|
||||
.listxattr = empty_dir_listxattr,
|
||||
};
|
||||
|
||||
@@ -1215,6 +1195,7 @@ void make_empty_dir_inode(struct inode *inode)
|
||||
inode->i_blocks = 0;
|
||||
|
||||
inode->i_op = &empty_dir_inode_operations;
|
||||
inode->i_opflags &= ~IOP_XATTR;
|
||||
inode->i_fop = &empty_dir_operations;
|
||||
}
|
||||
|
||||
|
@@ -899,9 +899,6 @@ static const struct inode_operations nfs3_dir_inode_operations = {
|
||||
.setattr = nfs_setattr,
|
||||
#ifdef CONFIG_NFS_V3_ACL
|
||||
.listxattr = nfs3_listxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = nfs3_get_acl,
|
||||
.set_acl = nfs3_set_acl,
|
||||
#endif
|
||||
@@ -913,9 +910,6 @@ static const struct inode_operations nfs3_file_inode_operations = {
|
||||
.setattr = nfs_setattr,
|
||||
#ifdef CONFIG_NFS_V3_ACL
|
||||
.listxattr = nfs3_listxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = nfs3_get_acl,
|
||||
.set_acl = nfs3_set_acl,
|
||||
#endif
|
||||
|
@@ -8941,20 +8941,14 @@ static const struct inode_operations nfs4_dir_inode_operations = {
|
||||
.permission = nfs_permission,
|
||||
.getattr = nfs_getattr,
|
||||
.setattr = nfs_setattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.listxattr = nfs4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
static const struct inode_operations nfs4_file_inode_operations = {
|
||||
.permission = nfs_permission,
|
||||
.getattr = nfs_getattr,
|
||||
.setattr = nfs_setattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.listxattr = nfs4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct nfs_rpc_ops nfs_v4_clientops = {
|
||||
|
@@ -2444,10 +2444,7 @@ const struct inode_operations ocfs2_file_iops = {
|
||||
.setattr = ocfs2_setattr,
|
||||
.getattr = ocfs2_getattr,
|
||||
.permission = ocfs2_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ocfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = ocfs2_fiemap,
|
||||
.get_acl = ocfs2_iop_get_acl,
|
||||
.set_acl = ocfs2_iop_set_acl,
|
||||
|
@@ -2913,10 +2913,7 @@ const struct inode_operations ocfs2_dir_iops = {
|
||||
.setattr = ocfs2_setattr,
|
||||
.getattr = ocfs2_getattr,
|
||||
.permission = ocfs2_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ocfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = ocfs2_fiemap,
|
||||
.get_acl = ocfs2_iop_get_acl,
|
||||
.set_acl = ocfs2_iop_set_acl,
|
||||
|
@@ -91,9 +91,6 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
|
||||
.get_link = page_get_link,
|
||||
.getattr = ocfs2_getattr,
|
||||
.setattr = ocfs2_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ocfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = ocfs2_fiemap,
|
||||
};
|
||||
|
@@ -296,10 +296,7 @@ const struct inode_operations orangefs_file_inode_operations = {
|
||||
.set_acl = orangefs_set_acl,
|
||||
.setattr = orangefs_setattr,
|
||||
.getattr = orangefs_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = orangefs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = orangefs_permission,
|
||||
};
|
||||
|
||||
|
@@ -462,9 +462,6 @@ const struct inode_operations orangefs_dir_inode_operations = {
|
||||
.rename = orangefs_rename,
|
||||
.setattr = orangefs_setattr,
|
||||
.getattr = orangefs_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = orangefs_listxattr,
|
||||
.permission = orangefs_permission,
|
||||
};
|
||||
|
@@ -14,6 +14,5 @@ const struct inode_operations orangefs_symlink_inode_operations = {
|
||||
.setattr = orangefs_setattr,
|
||||
.getattr = orangefs_getattr,
|
||||
.listxattr = orangefs_listxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.permission = orangefs_permission,
|
||||
};
|
||||
|
@@ -73,6 +73,9 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
|
||||
"%s: name %s, buffer_size %zd\n",
|
||||
__func__, name, size);
|
||||
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) {
|
||||
gossip_err("Invalid key length (%d)\n",
|
||||
(int)strlen(name));
|
||||
|
@@ -58,8 +58,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
|
||||
char *buf, *name, *value = NULL;
|
||||
int uninitialized_var(error);
|
||||
|
||||
if (!old->d_inode->i_op->getxattr ||
|
||||
!new->d_inode->i_op->getxattr)
|
||||
if (!(old->d_inode->i_opflags & IOP_XATTR) ||
|
||||
!(new->d_inode->i_opflags & IOP_XATTR))
|
||||
return 0;
|
||||
|
||||
list_size = vfs_listxattr(old, NULL, 0);
|
||||
|
@@ -1013,10 +1013,7 @@ const struct inode_operations ovl_dir_inode_operations = {
|
||||
.mknod = ovl_mknod,
|
||||
.permission = ovl_permission,
|
||||
.getattr = ovl_dir_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ovl_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ovl_get_acl,
|
||||
.update_time = ovl_update_time,
|
||||
};
|
||||
|
@@ -367,10 +367,7 @@ static const struct inode_operations ovl_file_inode_operations = {
|
||||
.setattr = ovl_setattr,
|
||||
.permission = ovl_permission,
|
||||
.getattr = ovl_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ovl_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ovl_get_acl,
|
||||
.update_time = ovl_update_time,
|
||||
};
|
||||
@@ -380,10 +377,7 @@ static const struct inode_operations ovl_symlink_inode_operations = {
|
||||
.get_link = ovl_get_link,
|
||||
.readlink = ovl_readlink,
|
||||
.getattr = ovl_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ovl_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.update_time = ovl_update_time,
|
||||
};
|
||||
|
||||
|
@@ -275,10 +275,10 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
|
||||
char val;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
|
||||
if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr)
|
||||
if (!S_ISDIR(inode->i_mode) || !(inode->i_opflags & IOP_XATTR))
|
||||
return false;
|
||||
|
||||
res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
|
||||
res = __vfs_getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
|
||||
if (res == 1 && val == 'y')
|
||||
return true;
|
||||
|
||||
|
@@ -260,10 +260,7 @@ const struct file_operations reiserfs_file_operations = {
|
||||
|
||||
const struct inode_operations reiserfs_file_inode_operations = {
|
||||
.setattr = reiserfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = reiserfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = reiserfs_permission,
|
||||
.get_acl = reiserfs_get_acl,
|
||||
.set_acl = reiserfs_set_acl,
|
||||
|
@@ -1650,10 +1650,7 @@ const struct inode_operations reiserfs_dir_inode_operations = {
|
||||
.mknod = reiserfs_mknod,
|
||||
.rename = reiserfs_rename,
|
||||
.setattr = reiserfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = reiserfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = reiserfs_permission,
|
||||
.get_acl = reiserfs_get_acl,
|
||||
.set_acl = reiserfs_set_acl,
|
||||
@@ -1667,10 +1664,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = page_get_link,
|
||||
.setattr = reiserfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = reiserfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = reiserfs_permission,
|
||||
};
|
||||
|
||||
@@ -1679,10 +1673,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
|
||||
*/
|
||||
const struct inode_operations reiserfs_special_inode_operations = {
|
||||
.setattr = reiserfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = reiserfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = reiserfs_permission,
|
||||
.get_acl = reiserfs_get_acl,
|
||||
.set_acl = reiserfs_set_acl,
|
||||
|
@@ -425,7 +425,6 @@ failed_read:
|
||||
|
||||
|
||||
const struct inode_operations squashfs_inode_ops = {
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = squashfs_listxattr
|
||||
};
|
||||
|
||||
|
@@ -247,6 +247,5 @@ failed:
|
||||
|
||||
const struct inode_operations squashfs_dir_inode_ops = {
|
||||
.lookup = squashfs_lookup,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = squashfs_listxattr
|
||||
};
|
||||
|
@@ -120,7 +120,6 @@ const struct address_space_operations squashfs_symlink_aops = {
|
||||
const struct inode_operations squashfs_symlink_inode_ops = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = page_get_link,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = squashfs_listxattr
|
||||
};
|
||||
|
||||
|
@@ -42,6 +42,5 @@ static inline int squashfs_xattr_lookup(struct super_block *sb,
|
||||
return 0;
|
||||
}
|
||||
#define squashfs_listxattr NULL
|
||||
#define generic_getxattr NULL
|
||||
#define squashfs_xattr_handlers NULL
|
||||
#endif
|
||||
|
@@ -1182,10 +1182,7 @@ const struct inode_operations ubifs_dir_inode_operations = {
|
||||
.rename = ubifs_rename,
|
||||
.setattr = ubifs_setattr,
|
||||
.getattr = ubifs_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
||||
.update_time = ubifs_update_time,
|
||||
#endif
|
||||
|
@@ -1621,10 +1621,7 @@ const struct address_space_operations ubifs_file_address_operations = {
|
||||
const struct inode_operations ubifs_file_inode_operations = {
|
||||
.setattr = ubifs_setattr,
|
||||
.getattr = ubifs_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
||||
.update_time = ubifs_update_time,
|
||||
#endif
|
||||
@@ -1635,10 +1632,7 @@ const struct inode_operations ubifs_symlink_inode_operations = {
|
||||
.get_link = simple_get_link,
|
||||
.setattr = ubifs_setattr,
|
||||
.getattr = ubifs_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
||||
.update_time = ubifs_update_time,
|
||||
#endif
|
||||
|
250
fs/xattr.c
250
fs/xattr.c
@@ -24,6 +24,59 @@
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
static const char *
|
||||
strcmp_prefix(const char *a, const char *a_prefix)
|
||||
{
|
||||
while (*a_prefix && *a == *a_prefix) {
|
||||
a++;
|
||||
a_prefix++;
|
||||
}
|
||||
return *a_prefix ? NULL : a;
|
||||
}
|
||||
|
||||
/*
|
||||
* In order to implement different sets of xattr operations for each xattr
|
||||
* prefix, a filesystem should create a null-terminated array of struct
|
||||
* xattr_handler (one for each prefix) and hang a pointer to it off of the
|
||||
* s_xattr field of the superblock.
|
||||
*/
|
||||
#define for_each_xattr_handler(handlers, handler) \
|
||||
if (handlers) \
|
||||
for ((handler) = *(handlers)++; \
|
||||
(handler) != NULL; \
|
||||
(handler) = *(handlers)++)
|
||||
|
||||
/*
|
||||
* Find the xattr_handler with the matching prefix.
|
||||
*/
|
||||
static const struct xattr_handler *
|
||||
xattr_resolve_name(struct inode *inode, const char **name)
|
||||
{
|
||||
const struct xattr_handler **handlers = inode->i_sb->s_xattr;
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
if (!(inode->i_opflags & IOP_XATTR)) {
|
||||
if (unlikely(is_bad_inode(inode)))
|
||||
return ERR_PTR(-EIO);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
const char *n;
|
||||
|
||||
n = strcmp_prefix(*name, xattr_prefix(handler));
|
||||
if (n) {
|
||||
if (!handler->prefix ^ !*n) {
|
||||
if (*n)
|
||||
continue;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
*name = n;
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check permissions for extended attribute access. This is a bit complicated
|
||||
* because different namespaces have very different rules.
|
||||
@@ -80,6 +133,23 @@ xattr_permission(struct inode *inode, const char *name, int mask)
|
||||
return inode_permission(inode, mask);
|
||||
}
|
||||
|
||||
int
|
||||
__vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(inode, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
if (!handler->set)
|
||||
return -EOPNOTSUPP;
|
||||
if (size == 0)
|
||||
value = ""; /* empty EA, do not remove */
|
||||
return handler->set(handler, dentry, inode, name, value, size, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(__vfs_setxattr);
|
||||
|
||||
/**
|
||||
* __vfs_setxattr_noperm - perform setxattr operation without performing
|
||||
* permission checks.
|
||||
@@ -106,8 +176,8 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
|
||||
|
||||
if (issec)
|
||||
inode->i_flags &= ~S_NOSEC;
|
||||
if (inode->i_op->setxattr) {
|
||||
error = inode->i_op->setxattr(dentry, inode, name, value, size, flags);
|
||||
if (inode->i_opflags & IOP_XATTR) {
|
||||
error = __vfs_setxattr(dentry, inode, name, value, size, flags);
|
||||
if (!error) {
|
||||
fsnotify_xattr(dentry);
|
||||
security_inode_post_setxattr(dentry, name, value,
|
||||
@@ -115,6 +185,9 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
|
||||
}
|
||||
} else if (issec) {
|
||||
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
|
||||
|
||||
if (unlikely(is_bad_inode(inode)))
|
||||
return -EIO;
|
||||
error = security_inode_setsecurity(inode, suffix, value,
|
||||
size, flags);
|
||||
if (!error)
|
||||
@@ -188,6 +261,7 @@ ssize_t
|
||||
vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
|
||||
size_t xattr_size, gfp_t flags)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
char *value = *xattr_value;
|
||||
int error;
|
||||
@@ -196,10 +270,12 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!inode->i_op->getxattr)
|
||||
handler = xattr_resolve_name(inode, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
if (!handler->get)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
error = inode->i_op->getxattr(dentry, inode, name, NULL, 0);
|
||||
error = handler->get(handler, dentry, inode, name, NULL, 0);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
@@ -210,11 +286,26 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
|
||||
memset(value, 0, error + 1);
|
||||
}
|
||||
|
||||
error = inode->i_op->getxattr(dentry, inode, name, value, error);
|
||||
error = handler->get(handler, dentry, inode, name, value, error);
|
||||
*xattr_value = value;
|
||||
return error;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
void *value, size_t size)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(inode, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
if (!handler->get)
|
||||
return -EOPNOTSUPP;
|
||||
return handler->get(handler, dentry, inode, name, value, size);
|
||||
}
|
||||
EXPORT_SYMBOL(__vfs_getxattr);
|
||||
|
||||
ssize_t
|
||||
vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
|
||||
{
|
||||
@@ -242,28 +333,24 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
|
||||
return ret;
|
||||
}
|
||||
nolsm:
|
||||
if (inode->i_op->getxattr)
|
||||
error = inode->i_op->getxattr(dentry, inode, name, value, size);
|
||||
else
|
||||
error = -EOPNOTSUPP;
|
||||
|
||||
return error;
|
||||
return __vfs_getxattr(dentry, inode, name, value, size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfs_getxattr);
|
||||
|
||||
ssize_t
|
||||
vfs_listxattr(struct dentry *d, char *list, size_t size)
|
||||
vfs_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
ssize_t error;
|
||||
|
||||
error = security_inode_listxattr(d);
|
||||
error = security_inode_listxattr(dentry);
|
||||
if (error)
|
||||
return error;
|
||||
error = -EOPNOTSUPP;
|
||||
if (d->d_inode->i_op->listxattr) {
|
||||
error = d->d_inode->i_op->listxattr(d, list, size);
|
||||
if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
|
||||
error = -EOPNOTSUPP;
|
||||
error = inode->i_op->listxattr(dentry, list, size);
|
||||
} else {
|
||||
error = security_inode_listsecurity(d->d_inode, list, size);
|
||||
error = security_inode_listsecurity(inode, list, size);
|
||||
if (size && error > size)
|
||||
error = -ERANGE;
|
||||
}
|
||||
@@ -271,15 +358,27 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfs_listxattr);
|
||||
|
||||
int
|
||||
__vfs_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(inode, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
if (!handler->set)
|
||||
return -EOPNOTSUPP;
|
||||
return handler->set(handler, dentry, inode, name, NULL, 0, XATTR_REPLACE);
|
||||
}
|
||||
EXPORT_SYMBOL(__vfs_removexattr);
|
||||
|
||||
int
|
||||
vfs_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
|
||||
if (!inode->i_op->removexattr)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
error = xattr_permission(inode, name, MAY_WRITE);
|
||||
if (error)
|
||||
return error;
|
||||
@@ -289,7 +388,7 @@ vfs_removexattr(struct dentry *dentry, const char *name)
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = inode->i_op->removexattr(dentry, name);
|
||||
error = __vfs_removexattr(dentry, name);
|
||||
|
||||
if (!error) {
|
||||
fsnotify_xattr(dentry);
|
||||
@@ -641,76 +740,6 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
strcmp_prefix(const char *a, const char *a_prefix)
|
||||
{
|
||||
while (*a_prefix && *a == *a_prefix) {
|
||||
a++;
|
||||
a_prefix++;
|
||||
}
|
||||
return *a_prefix ? NULL : a;
|
||||
}
|
||||
|
||||
/*
|
||||
* In order to implement different sets of xattr operations for each xattr
|
||||
* prefix with the generic xattr API, a filesystem should create a
|
||||
* null-terminated array of struct xattr_handler (one for each prefix) and
|
||||
* hang a pointer to it off of the s_xattr field of the superblock.
|
||||
*
|
||||
* The generic_fooxattr() functions will use this list to dispatch xattr
|
||||
* operations to the correct xattr_handler.
|
||||
*/
|
||||
#define for_each_xattr_handler(handlers, handler) \
|
||||
if (handlers) \
|
||||
for ((handler) = *(handlers)++; \
|
||||
(handler) != NULL; \
|
||||
(handler) = *(handlers)++)
|
||||
|
||||
/*
|
||||
* Find the xattr_handler with the matching prefix.
|
||||
*/
|
||||
static const struct xattr_handler *
|
||||
xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
if (!*name)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
const char *n;
|
||||
|
||||
n = strcmp_prefix(*name, xattr_prefix(handler));
|
||||
if (n) {
|
||||
if (!handler->prefix ^ !*n) {
|
||||
if (*n)
|
||||
continue;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
*name = n;
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the handler for the prefix and dispatch its get() operation.
|
||||
*/
|
||||
ssize_t
|
||||
generic_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *buffer, size_t size)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
return handler->get(handler, dentry, inode,
|
||||
name, buffer, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Combine the results of the list() operation from every xattr_handler in the
|
||||
* list.
|
||||
@@ -747,44 +776,7 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the handler for the prefix and dispatch its set() operation.
|
||||
*/
|
||||
int
|
||||
generic_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
if (size == 0)
|
||||
value = ""; /* empty EA, do not remove */
|
||||
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
return handler->set(handler, dentry, inode, name, value, size, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the handler for the prefix and dispatch its set() operation to remove
|
||||
* any associated extended attribute.
|
||||
*/
|
||||
int
|
||||
generic_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
return handler->set(handler, dentry, d_inode(dentry), name, NULL,
|
||||
0, XATTR_REPLACE);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(generic_getxattr);
|
||||
EXPORT_SYMBOL(generic_listxattr);
|
||||
EXPORT_SYMBOL(generic_setxattr);
|
||||
EXPORT_SYMBOL(generic_removexattr);
|
||||
|
||||
/**
|
||||
* xattr_full_name - Compute full attribute name from suffix
|
||||
|
@@ -1066,9 +1066,6 @@ static const struct inode_operations xfs_inode_operations = {
|
||||
.set_acl = xfs_set_acl,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.fiemap = xfs_vn_fiemap,
|
||||
.update_time = xfs_vn_update_time,
|
||||
@@ -1094,9 +1091,6 @@ static const struct inode_operations xfs_dir_inode_operations = {
|
||||
.set_acl = xfs_set_acl,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
.tmpfile = xfs_vn_tmpfile,
|
||||
@@ -1122,9 +1116,6 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
|
||||
.set_acl = xfs_set_acl,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
.tmpfile = xfs_vn_tmpfile,
|
||||
@@ -1135,9 +1126,6 @@ static const struct inode_operations xfs_symlink_inode_operations = {
|
||||
.get_link = xfs_vn_get_link,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
};
|
||||
@@ -1147,9 +1135,6 @@ static const struct inode_operations xfs_inline_symlink_inode_operations = {
|
||||
.get_link = xfs_vn_get_link_inline,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
};
|
||||
|
Reference in New Issue
Block a user