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:
Linus Torvalds 2016-10-10 17:11:50 -07:00
commit 97d2116708
80 changed files with 471 additions and 687 deletions

View file

@ -61,10 +61,7 @@ prototypes:
int (*get_acl)(struct inode *, int); int (*get_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *); int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *); int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
void (*update_time)(struct inode *, struct timespec *, int); void (*update_time)(struct inode *, struct timespec *, int);
int (*atomic_open)(struct inode *, struct dentry *, int (*atomic_open)(struct inode *, struct dentry *,
@ -91,15 +88,13 @@ setattr: yes
permission: no (may not block if called in rcu-walk mode) permission: no (may not block if called in rcu-walk mode)
get_acl: no get_acl: no
getattr: no getattr: no
setxattr: yes
getxattr: no
listxattr: no listxattr: no
removexattr: yes
fiemap: no fiemap: no
update_time: no update_time: no
atomic_open: yes atomic_open: yes
tmpfile: no tmpfile: no
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
victim. victim.
cross-directory ->rename() and rename2() has (per-superblock) cross-directory ->rename() and rename2() has (per-superblock)
@ -108,6 +103,23 @@ victim.
See Documentation/filesystems/directory-locking for more detailed discussion See Documentation/filesystems/directory-locking for more detailed discussion
of the locking scheme for directory operations. of the locking scheme for directory operations.
----------------------- xattr_handler operations -----------------------
prototypes:
bool (*list)(struct dentry *dentry);
int (*get)(const struct xattr_handler *handler, struct dentry *dentry,
struct inode *inode, const char *name, void *buffer,
size_t size);
int (*set)(const struct xattr_handler *handler, struct dentry *dentry,
struct inode *inode, const char *name, const void *buffer,
size_t size, int flags);
locking rules:
all may block
i_mutex(inode)
list: no
get: no
set: yes
--------------------------- super_operations --------------------------- --------------------------- super_operations ---------------------------
prototypes: prototypes:
struct inode *(*alloc_inode)(struct super_block *sb); struct inode *(*alloc_inode)(struct super_block *sb);

View file

@ -323,6 +323,35 @@ Whoever sets up the inode is responsible for filling in the "i_op" field. This
is a pointer to a "struct inode_operations" which describes the methods that is a pointer to a "struct inode_operations" which describes the methods that
can be performed on individual inodes. can be performed on individual inodes.
struct xattr_handlers
---------------------
On filesystems that support extended attributes (xattrs), the s_xattr
superblock field points to a NULL-terminated array of xattr handlers. Extended
attributes are name:value pairs.
name: Indicates that the handler matches attributes with the specified name
(such as "system.posix_acl_access"); the prefix field must be NULL.
prefix: Indicates that the handler matches all attributes with the specified
name prefix (such as "user."); the name field must be NULL.
list: Determine if attributes matching this xattr handler should be listed
for a particular dentry. Used by some listxattr implementations like
generic_listxattr.
get: Called by the VFS to get the value of a particular extended attribute.
This method is called by the getxattr(2) system call.
set: Called by the VFS to set the value of a particular extended attribute.
When the new value is NULL, called to remove a particular extended
attribute. This method is called by the the setxattr(2) and
removexattr(2) system calls.
When none of the xattr handlers of a filesystem match the specified attribute
name or when a filesystem doesn't support extended attributes, the various
*xattr(2) system calls return -EOPNOTSUPP.
The Inode Object The Inode Object
================ ================
@ -356,10 +385,7 @@ struct inode_operations {
int (*get_acl)(struct inode *, int); int (*get_acl)(struct inode *, int);
int (*setattr) (struct dentry *, struct iattr *); int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
void (*update_time)(struct inode *, struct timespec *, int); void (*update_time)(struct inode *, struct timespec *, int);
int (*atomic_open)(struct inode *, struct dentry *, struct file *, int (*atomic_open)(struct inode *, struct dentry *, struct file *,
unsigned open_flag, umode_t create_mode, int *opened); unsigned open_flag, umode_t create_mode, int *opened);
@ -463,19 +489,8 @@ otherwise noted.
getattr: called by the VFS to get attributes of a file. This method getattr: called by the VFS to get attributes of a file. This method
is called by stat(2) and related system calls. is called by stat(2) and related system calls.
setxattr: called by the VFS to set an extended attribute for a file.
Extended attribute is a name:value pair associated with an
inode. This method is called by setxattr(2) system call.
getxattr: called by the VFS to retrieve the value of an extended
attribute name. This method is called by getxattr(2) function
call.
listxattr: called by the VFS to list all extended attributes for a listxattr: called by the VFS to list all extended attributes for a
given file. This method is called by listxattr(2) system call. given file. This method is called by the listxattr(2) system call.
removexattr: called by the VFS to remove an extended attribute from
a file. This method is called by removexattr(2) system call.
update_time: called by the VFS to update a specific time or the i_version of update_time: called by the VFS to update a specific time or the i_version of
an inode. If this is not defined the VFS will update the inode itself an inode. If this is not defined the VFS will update the inode itself

View file

@ -3268,10 +3268,7 @@ const struct inode_operations ll_file_inode_operations = {
.setattr = ll_setattr, .setattr = ll_setattr,
.getattr = ll_getattr, .getattr = ll_getattr,
.permission = ll_inode_permission, .permission = ll_inode_permission,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ll_listxattr, .listxattr = ll_listxattr,
.removexattr = generic_removexattr,
.fiemap = ll_fiemap, .fiemap = ll_fiemap,
.get_acl = ll_get_acl, .get_acl = ll_get_acl,
}; };

View file

@ -1152,10 +1152,7 @@ const struct inode_operations ll_dir_inode_operations = {
.setattr = ll_setattr, .setattr = ll_setattr,
.getattr = ll_getattr, .getattr = ll_getattr,
.permission = ll_inode_permission, .permission = ll_inode_permission,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ll_listxattr, .listxattr = ll_listxattr,
.removexattr = generic_removexattr,
.get_acl = ll_get_acl, .get_acl = ll_get_acl,
}; };
@ -1163,9 +1160,6 @@ const struct inode_operations ll_special_inode_operations = {
.setattr = ll_setattr, .setattr = ll_setattr,
.getattr = ll_getattr, .getattr = ll_getattr,
.permission = ll_inode_permission, .permission = ll_inode_permission,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ll_listxattr, .listxattr = ll_listxattr,
.removexattr = generic_removexattr,
.get_acl = ll_get_acl, .get_acl = ll_get_acl,
}; };

View file

@ -154,8 +154,5 @@ const struct inode_operations ll_fast_symlink_inode_operations = {
.get_link = ll_get_link, .get_link = ll_get_link,
.getattr = ll_getattr, .getattr = ll_getattr,
.permission = ll_inode_permission, .permission = ll_inode_permission,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ll_listxattr, .listxattr = ll_listxattr,
.removexattr = generic_removexattr,
}; };

View file

@ -967,9 +967,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
.rename = v9fs_vfs_rename, .rename = v9fs_vfs_rename,
.getattr = v9fs_vfs_getattr_dotl, .getattr = v9fs_vfs_getattr_dotl,
.setattr = v9fs_vfs_setattr_dotl, .setattr = v9fs_vfs_setattr_dotl,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = v9fs_listxattr, .listxattr = v9fs_listxattr,
.get_acl = v9fs_iop_get_acl, .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 = { const struct inode_operations v9fs_file_inode_operations_dotl = {
.getattr = v9fs_vfs_getattr_dotl, .getattr = v9fs_vfs_getattr_dotl,
.setattr = v9fs_vfs_setattr_dotl, .setattr = v9fs_vfs_setattr_dotl,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = v9fs_listxattr, .listxattr = v9fs_listxattr,
.get_acl = v9fs_iop_get_acl, .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, .get_link = v9fs_vfs_get_link_dotl,
.getattr = v9fs_vfs_getattr_dotl, .getattr = v9fs_vfs_getattr_dotl,
.setattr = v9fs_vfs_setattr_dotl, .setattr = v9fs_vfs_setattr_dotl,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = v9fs_listxattr, .listxattr = v9fs_listxattr,
}; };

View file

@ -100,29 +100,12 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
return -EIO; 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, static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
size_t buffer_size) size_t buffer_size)
{ {
return -EIO; return -EIO;
} }
static int bad_inode_removexattr(struct dentry *dentry, const char *name)
{
return -EIO;
}
static const struct inode_operations bad_inode_ops = static const struct inode_operations bad_inode_ops =
{ {
.create = bad_inode_create, .create = bad_inode_create,
@ -142,10 +125,7 @@ static const struct inode_operations bad_inode_ops =
.permission = bad_inode_permission, .permission = bad_inode_permission,
.getattr = bad_inode_getattr, .getattr = bad_inode_getattr,
.setattr = bad_inode_setattr, .setattr = bad_inode_setattr,
.setxattr = bad_inode_setxattr,
.getxattr = bad_inode_getxattr,
.listxattr = bad_inode_listxattr, .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 = inode->i_atime = inode->i_mtime = inode->i_ctime =
current_fs_time(inode->i_sb); current_fs_time(inode->i_sb);
inode->i_op = &bad_inode_ops; inode->i_op = &bad_inode_ops;
inode->i_opflags &= ~IOP_XATTR;
inode->i_fop = &bad_file_ops; inode->i_fop = &bad_file_ops;
} }
EXPORT_SYMBOL(make_bad_inode); EXPORT_SYMBOL(make_bad_inode);

View file

@ -10556,10 +10556,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
.symlink = btrfs_symlink, .symlink = btrfs_symlink,
.setattr = btrfs_setattr, .setattr = btrfs_setattr,
.mknod = btrfs_mknod, .mknod = btrfs_mknod,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = btrfs_listxattr, .listxattr = btrfs_listxattr,
.removexattr = generic_removexattr,
.permission = btrfs_permission, .permission = btrfs_permission,
.get_acl = btrfs_get_acl, .get_acl = btrfs_get_acl,
.set_acl = btrfs_set_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 = { static const struct inode_operations btrfs_file_inode_operations = {
.getattr = btrfs_getattr, .getattr = btrfs_getattr,
.setattr = btrfs_setattr, .setattr = btrfs_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = btrfs_listxattr, .listxattr = btrfs_listxattr,
.removexattr = generic_removexattr,
.permission = btrfs_permission, .permission = btrfs_permission,
.fiemap = btrfs_fiemap, .fiemap = btrfs_fiemap,
.get_acl = btrfs_get_acl, .get_acl = btrfs_get_acl,
@ -10647,10 +10641,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
.getattr = btrfs_getattr, .getattr = btrfs_getattr,
.setattr = btrfs_setattr, .setattr = btrfs_setattr,
.permission = btrfs_permission, .permission = btrfs_permission,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = btrfs_listxattr, .listxattr = btrfs_listxattr,
.removexattr = generic_removexattr,
.get_acl = btrfs_get_acl, .get_acl = btrfs_get_acl,
.set_acl = btrfs_set_acl, .set_acl = btrfs_set_acl,
.update_time = btrfs_update_time, .update_time = btrfs_update_time,
@ -10661,10 +10652,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
.getattr = btrfs_getattr, .getattr = btrfs_getattr,
.setattr = btrfs_setattr, .setattr = btrfs_setattr,
.permission = btrfs_permission, .permission = btrfs_permission,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = btrfs_listxattr, .listxattr = btrfs_listxattr,
.removexattr = generic_removexattr,
.update_time = btrfs_update_time, .update_time = btrfs_update_time,
}; };

View file

@ -20,6 +20,7 @@
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/statfs.h> #include <linux/statfs.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/xattr.h>
#include "internal.h" #include "internal.h"
static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches); 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) || if (d_is_negative(root) ||
!d_backing_inode(root)->i_op->lookup || !d_backing_inode(root)->i_op->lookup ||
!d_backing_inode(root)->i_op->mkdir || !d_backing_inode(root)->i_op->mkdir ||
!d_backing_inode(root)->i_op->setxattr || !(d_backing_inode(root)->i_opflags & IOP_XATTR) ||
!d_backing_inode(root)->i_op->getxattr ||
!root->d_sb->s_op->statfs || !root->d_sb->s_op->statfs ||
!root->d_sb->s_op->sync_fs) !root->d_sb->s_op->sync_fs)
goto error_unsupported; goto error_unsupported;

View file

@ -20,6 +20,7 @@
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/xattr.h>
#include "internal.h" #include "internal.h"
#define CACHEFILES_KEYBUF_SIZE 512 #define CACHEFILES_KEYBUF_SIZE 512
@ -799,8 +800,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
} }
ret = -EPERM; ret = -EPERM;
if (!d_backing_inode(subdir)->i_op->setxattr || if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
!d_backing_inode(subdir)->i_op->getxattr ||
!d_backing_inode(subdir)->i_op->lookup || !d_backing_inode(subdir)->i_op->lookup ||
!d_backing_inode(subdir)->i_op->mkdir || !d_backing_inode(subdir)->i_op->mkdir ||
!d_backing_inode(subdir)->i_op->create || !d_backing_inode(subdir)->i_op->create ||

View file

@ -1486,10 +1486,7 @@ const struct inode_operations ceph_dir_iops = {
.permission = ceph_permission, .permission = ceph_permission,
.getattr = ceph_getattr, .getattr = ceph_getattr,
.setattr = ceph_setattr, .setattr = ceph_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ceph_listxattr, .listxattr = ceph_listxattr,
.removexattr = generic_removexattr,
.get_acl = ceph_get_acl, .get_acl = ceph_get_acl,
.set_acl = ceph_set_acl, .set_acl = ceph_set_acl,
.mknod = ceph_mknod, .mknod = ceph_mknod,

View file

@ -94,10 +94,7 @@ const struct inode_operations ceph_file_iops = {
.permission = ceph_permission, .permission = ceph_permission,
.setattr = ceph_setattr, .setattr = ceph_setattr,
.getattr = ceph_getattr, .getattr = ceph_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ceph_listxattr, .listxattr = ceph_listxattr,
.removexattr = generic_removexattr,
.get_acl = ceph_get_acl, .get_acl = ceph_get_acl,
.set_acl = ceph_set_acl, .set_acl = ceph_set_acl,
}; };
@ -1885,10 +1882,7 @@ static const struct inode_operations ceph_symlink_iops = {
.get_link = simple_get_link, .get_link = simple_get_link,
.setattr = ceph_setattr, .setattr = ceph_setattr,
.getattr = ceph_getattr, .getattr = ceph_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ceph_listxattr, .listxattr = ceph_listxattr,
.removexattr = generic_removexattr,
}; };
int __ceph_setattr(struct inode *inode, struct iattr *attr) int __ceph_setattr(struct inode *inode, struct iattr *attr)

View file

@ -901,30 +901,21 @@ const struct inode_operations cifs_dir_inode_ops = {
.setattr = cifs_setattr, .setattr = cifs_setattr,
.symlink = cifs_symlink, .symlink = cifs_symlink,
.mknod = cifs_mknod, .mknod = cifs_mknod,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = cifs_listxattr, .listxattr = cifs_listxattr,
.removexattr = generic_removexattr,
}; };
const struct inode_operations cifs_file_inode_ops = { const struct inode_operations cifs_file_inode_ops = {
.setattr = cifs_setattr, .setattr = cifs_setattr,
.getattr = cifs_getattr, .getattr = cifs_getattr,
.permission = cifs_permission, .permission = cifs_permission,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = cifs_listxattr, .listxattr = cifs_listxattr,
.removexattr = generic_removexattr,
}; };
const struct inode_operations cifs_symlink_inode_ops = { const struct inode_operations cifs_symlink_inode_ops = {
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = cifs_get_link, .get_link = cifs_get_link,
.permission = cifs_permission, .permission = cifs_permission,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = cifs_listxattr, .listxattr = cifs_listxattr,
.removexattr = generic_removexattr,
}; };
static int cifs_clone_file_range(struct file *src_file, loff_t off, static int cifs_clone_file_range(struct file *src_file, loff_t off,

View file

@ -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, int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
loff_t offset); loff_t offset);
extern const struct xattr_handler *ecryptfs_xattr_handlers[];
#endif /* #ifndef ECRYPTFS_KERNEL_H */ #endif /* #ifndef ECRYPTFS_KERNEL_H */

View file

@ -1005,15 +1005,14 @@ ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value, const char *name, const void *value,
size_t size, int flags) size_t size, int flags)
{ {
int rc = 0; int rc;
struct dentry *lower_dentry; struct dentry *lower_dentry;
lower_dentry = ecryptfs_dentry_to_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; rc = -EOPNOTSUPP;
goto out; goto out;
} }
rc = vfs_setxattr(lower_dentry, name, value, size, flags); rc = vfs_setxattr(lower_dentry, name, value, size, flags);
if (!rc && inode) if (!rc && inode)
fsstack_copy_attr_all(inode, d_inode(lower_dentry)); 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, ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
const char *name, void *value, size_t size) 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; rc = -EOPNOTSUPP;
goto out; goto out;
} }
inode_lock(lower_inode); inode_lock(lower_inode);
rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode, rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
name, value, size);
inode_unlock(lower_inode); inode_unlock(lower_inode);
out: out:
return rc; return rc;
@ -1066,19 +1064,22 @@ out:
return rc; 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 dentry *lower_dentry;
struct inode *lower_inode;
lower_dentry = ecryptfs_dentry_to_lower(dentry); 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; rc = -EOPNOTSUPP;
goto out; goto out;
} }
inode_lock(d_inode(lower_dentry)); inode_lock(lower_inode);
rc = d_inode(lower_dentry)->i_op->removexattr(lower_dentry, name); rc = __vfs_removexattr(lower_dentry, name);
inode_unlock(d_inode(lower_dentry)); inode_unlock(lower_inode);
out: out:
return rc; return rc;
} }
@ -1089,10 +1090,7 @@ const struct inode_operations ecryptfs_symlink_iops = {
.permission = ecryptfs_permission, .permission = ecryptfs_permission,
.setattr = ecryptfs_setattr, .setattr = ecryptfs_setattr,
.getattr = ecryptfs_getattr_link, .getattr = ecryptfs_getattr_link,
.setxattr = ecryptfs_setxattr,
.getxattr = ecryptfs_getxattr,
.listxattr = ecryptfs_listxattr, .listxattr = ecryptfs_listxattr,
.removexattr = ecryptfs_removexattr
}; };
const struct inode_operations ecryptfs_dir_iops = { const struct inode_operations ecryptfs_dir_iops = {
@ -1107,18 +1105,43 @@ const struct inode_operations ecryptfs_dir_iops = {
.rename = ecryptfs_rename, .rename = ecryptfs_rename,
.permission = ecryptfs_permission, .permission = ecryptfs_permission,
.setattr = ecryptfs_setattr, .setattr = ecryptfs_setattr,
.setxattr = ecryptfs_setxattr,
.getxattr = ecryptfs_getxattr,
.listxattr = ecryptfs_listxattr, .listxattr = ecryptfs_listxattr,
.removexattr = ecryptfs_removexattr
}; };
const struct inode_operations ecryptfs_main_iops = { const struct inode_operations ecryptfs_main_iops = {
.permission = ecryptfs_permission, .permission = ecryptfs_permission,
.setattr = ecryptfs_setattr, .setattr = ecryptfs_setattr,
.getattr = ecryptfs_getattr, .getattr = ecryptfs_getattr,
.setxattr = ecryptfs_setxattr,
.getxattr = ecryptfs_getxattr,
.listxattr = ecryptfs_listxattr, .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
}; };

View file

@ -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 */ /* ->kill_sb() will take care of sbi after that point */
sbi = NULL; sbi = NULL;
s->s_op = &ecryptfs_sops; s->s_op = &ecryptfs_sops;
s->s_xattr = ecryptfs_xattr_handlers;
s->s_d_op = &ecryptfs_dops; s->s_d_op = &ecryptfs_dops;
err = "Reading sb failed"; err = "Reading sb failed";

View file

@ -32,6 +32,7 @@
#include <linux/file.h> #include <linux/file.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/xattr.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "ecryptfs_kernel.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); struct inode *lower_inode = d_inode(lower_dentry);
int rc; int rc;
if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) { if (!(lower_inode->i_opflags & IOP_XATTR)) {
printk(KERN_WARNING printk(KERN_WARNING
"No support for setting xattr in lower filesystem\n"); "No support for setting xattr in lower filesystem\n");
rc = -ENOSYS; rc = -ENOSYS;
@ -436,14 +437,12 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
goto out; goto out;
} }
inode_lock(lower_inode); inode_lock(lower_inode);
size = lower_inode->i_op->getxattr(lower_dentry, lower_inode, size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
ECRYPTFS_XATTR_NAME,
xattr_virt, PAGE_SIZE); xattr_virt, PAGE_SIZE);
if (size < 0) if (size < 0)
size = 8; size = 8;
put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt); put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode, rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
ECRYPTFS_XATTR_NAME,
xattr_virt, size, 0); xattr_virt, size, 0);
inode_unlock(lower_inode); inode_unlock(lower_inode);
if (rc) if (rc)

View file

@ -241,10 +241,7 @@ const struct file_operations ext2_file_operations = {
const struct inode_operations ext2_file_inode_operations = { const struct inode_operations ext2_file_inode_operations = {
#ifdef CONFIG_EXT2_FS_XATTR #ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext2_listxattr, .listxattr = ext2_listxattr,
.removexattr = generic_removexattr,
#endif #endif
.setattr = ext2_setattr, .setattr = ext2_setattr,
.get_acl = ext2_get_acl, .get_acl = ext2_get_acl,

View file

@ -428,10 +428,7 @@ const struct inode_operations ext2_dir_inode_operations = {
.mknod = ext2_mknod, .mknod = ext2_mknod,
.rename = ext2_rename, .rename = ext2_rename,
#ifdef CONFIG_EXT2_FS_XATTR #ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext2_listxattr, .listxattr = ext2_listxattr,
.removexattr = generic_removexattr,
#endif #endif
.setattr = ext2_setattr, .setattr = ext2_setattr,
.get_acl = ext2_get_acl, .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 = { const struct inode_operations ext2_special_inode_operations = {
#ifdef CONFIG_EXT2_FS_XATTR #ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext2_listxattr, .listxattr = ext2_listxattr,
.removexattr = generic_removexattr,
#endif #endif
.setattr = ext2_setattr, .setattr = ext2_setattr,
.get_acl = ext2_get_acl, .get_acl = ext2_get_acl,

View file

@ -25,10 +25,7 @@ const struct inode_operations ext2_symlink_inode_operations = {
.get_link = page_get_link, .get_link = page_get_link,
.setattr = ext2_setattr, .setattr = ext2_setattr,
#ifdef CONFIG_EXT2_FS_XATTR #ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext2_listxattr, .listxattr = ext2_listxattr,
.removexattr = generic_removexattr,
#endif #endif
}; };
@ -37,9 +34,6 @@ const struct inode_operations ext2_fast_symlink_inode_operations = {
.get_link = simple_get_link, .get_link = simple_get_link,
.setattr = ext2_setattr, .setattr = ext2_setattr,
#ifdef CONFIG_EXT2_FS_XATTR #ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext2_listxattr, .listxattr = ext2_listxattr,
.removexattr = generic_removexattr,
#endif #endif
}; };

View file

@ -706,10 +706,7 @@ const struct file_operations ext4_file_operations = {
const struct inode_operations ext4_file_inode_operations = { const struct inode_operations ext4_file_inode_operations = {
.setattr = ext4_setattr, .setattr = ext4_setattr,
.getattr = ext4_getattr, .getattr = ext4_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr, .listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
.get_acl = ext4_get_acl, .get_acl = ext4_get_acl,
.set_acl = ext4_set_acl, .set_acl = ext4_set_acl,
.fiemap = ext4_fiemap, .fiemap = ext4_fiemap,

View file

@ -3880,10 +3880,7 @@ const struct inode_operations ext4_dir_inode_operations = {
.tmpfile = ext4_tmpfile, .tmpfile = ext4_tmpfile,
.rename2 = ext4_rename2, .rename2 = ext4_rename2,
.setattr = ext4_setattr, .setattr = ext4_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr, .listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
.get_acl = ext4_get_acl, .get_acl = ext4_get_acl,
.set_acl = ext4_set_acl, .set_acl = ext4_set_acl,
.fiemap = ext4_fiemap, .fiemap = ext4_fiemap,
@ -3891,10 +3888,7 @@ const struct inode_operations ext4_dir_inode_operations = {
const struct inode_operations ext4_special_inode_operations = { const struct inode_operations ext4_special_inode_operations = {
.setattr = ext4_setattr, .setattr = ext4_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr, .listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
.get_acl = ext4_get_acl, .get_acl = ext4_get_acl,
.set_acl = ext4_set_acl, .set_acl = ext4_set_acl,
}; };

View file

@ -86,28 +86,19 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = ext4_encrypted_get_link, .get_link = ext4_encrypted_get_link,
.setattr = ext4_setattr, .setattr = ext4_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr, .listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
}; };
const struct inode_operations ext4_symlink_inode_operations = { const struct inode_operations ext4_symlink_inode_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = page_get_link, .get_link = page_get_link,
.setattr = ext4_setattr, .setattr = ext4_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr, .listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
}; };
const struct inode_operations ext4_fast_symlink_inode_operations = { const struct inode_operations ext4_fast_symlink_inode_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = simple_get_link, .get_link = simple_get_link,
.setattr = ext4_setattr, .setattr = ext4_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr, .listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
}; };

View file

@ -732,10 +732,7 @@ const struct inode_operations f2fs_file_inode_operations = {
.get_acl = f2fs_get_acl, .get_acl = f2fs_get_acl,
.set_acl = f2fs_set_acl, .set_acl = f2fs_set_acl,
#ifdef CONFIG_F2FS_FS_XATTR #ifdef CONFIG_F2FS_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = f2fs_listxattr, .listxattr = f2fs_listxattr,
.removexattr = generic_removexattr,
#endif #endif
.fiemap = f2fs_fiemap, .fiemap = f2fs_fiemap,
}; };

View file

@ -1080,10 +1080,7 @@ const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
.getattr = f2fs_getattr, .getattr = f2fs_getattr,
.setattr = f2fs_setattr, .setattr = f2fs_setattr,
#ifdef CONFIG_F2FS_FS_XATTR #ifdef CONFIG_F2FS_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = f2fs_listxattr, .listxattr = f2fs_listxattr,
.removexattr = generic_removexattr,
#endif #endif
}; };
@ -1103,10 +1100,7 @@ const struct inode_operations f2fs_dir_inode_operations = {
.get_acl = f2fs_get_acl, .get_acl = f2fs_get_acl,
.set_acl = f2fs_set_acl, .set_acl = f2fs_set_acl,
#ifdef CONFIG_F2FS_FS_XATTR #ifdef CONFIG_F2FS_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = f2fs_listxattr, .listxattr = f2fs_listxattr,
.removexattr = generic_removexattr,
#endif #endif
}; };
@ -1116,10 +1110,7 @@ const struct inode_operations f2fs_symlink_inode_operations = {
.getattr = f2fs_getattr, .getattr = f2fs_getattr,
.setattr = f2fs_setattr, .setattr = f2fs_setattr,
#ifdef CONFIG_F2FS_FS_XATTR #ifdef CONFIG_F2FS_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = f2fs_listxattr, .listxattr = f2fs_listxattr,
.removexattr = generic_removexattr,
#endif #endif
}; };
@ -1129,9 +1120,6 @@ const struct inode_operations f2fs_special_inode_operations = {
.get_acl = f2fs_get_acl, .get_acl = f2fs_get_acl,
.set_acl = f2fs_set_acl, .set_acl = f2fs_set_acl,
#ifdef CONFIG_F2FS_FS_XATTR #ifdef CONFIG_F2FS_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = f2fs_listxattr, .listxattr = f2fs_listxattr,
.removexattr = generic_removexattr,
#endif #endif
}; };

View file

@ -1801,10 +1801,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
.mknod = fuse_mknod, .mknod = fuse_mknod,
.permission = fuse_permission, .permission = fuse_permission,
.getattr = fuse_getattr, .getattr = fuse_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = fuse_listxattr, .listxattr = fuse_listxattr,
.removexattr = generic_removexattr,
.get_acl = fuse_get_acl, .get_acl = fuse_get_acl,
.set_acl = fuse_set_acl, .set_acl = fuse_set_acl,
}; };
@ -1824,10 +1821,7 @@ static const struct inode_operations fuse_common_inode_operations = {
.setattr = fuse_setattr, .setattr = fuse_setattr,
.permission = fuse_permission, .permission = fuse_permission,
.getattr = fuse_getattr, .getattr = fuse_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = fuse_listxattr, .listxattr = fuse_listxattr,
.removexattr = generic_removexattr,
.get_acl = fuse_get_acl, .get_acl = fuse_get_acl,
.set_acl = fuse_set_acl, .set_acl = fuse_set_acl,
}; };
@ -1837,10 +1831,7 @@ static const struct inode_operations fuse_symlink_inode_operations = {
.get_link = fuse_get_link, .get_link = fuse_get_link,
.readlink = generic_readlink, .readlink = generic_readlink,
.getattr = fuse_getattr, .getattr = fuse_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = fuse_listxattr, .listxattr = fuse_listxattr,
.removexattr = generic_removexattr,
}; };
void fuse_init_common(struct inode *inode) void fuse_init_common(struct inode *inode)

View file

@ -2040,10 +2040,7 @@ const struct inode_operations gfs2_file_iops = {
.permission = gfs2_permission, .permission = gfs2_permission,
.setattr = gfs2_setattr, .setattr = gfs2_setattr,
.getattr = gfs2_getattr, .getattr = gfs2_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = gfs2_listxattr, .listxattr = gfs2_listxattr,
.removexattr = generic_removexattr,
.fiemap = gfs2_fiemap, .fiemap = gfs2_fiemap,
.get_acl = gfs2_get_acl, .get_acl = gfs2_get_acl,
.set_acl = gfs2_set_acl, .set_acl = gfs2_set_acl,
@ -2062,10 +2059,7 @@ const struct inode_operations gfs2_dir_iops = {
.permission = gfs2_permission, .permission = gfs2_permission,
.setattr = gfs2_setattr, .setattr = gfs2_setattr,
.getattr = gfs2_getattr, .getattr = gfs2_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = gfs2_listxattr, .listxattr = gfs2_listxattr,
.removexattr = generic_removexattr,
.fiemap = gfs2_fiemap, .fiemap = gfs2_fiemap,
.get_acl = gfs2_get_acl, .get_acl = gfs2_get_acl,
.set_acl = gfs2_set_acl, .set_acl = gfs2_set_acl,
@ -2078,10 +2072,7 @@ const struct inode_operations gfs2_symlink_iops = {
.permission = gfs2_permission, .permission = gfs2_permission,
.setattr = gfs2_setattr, .setattr = gfs2_setattr,
.getattr = gfs2_getattr, .getattr = gfs2_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = gfs2_listxattr, .listxattr = gfs2_listxattr,
.removexattr = generic_removexattr,
.fiemap = gfs2_fiemap, .fiemap = gfs2_fiemap,
}; };

View file

@ -13,9 +13,13 @@
#include "hfs_fs.h" #include "hfs_fs.h"
#include "btree.h" #include "btree.h"
int hfs_setxattr(struct dentry *unused, struct inode *inode, enum hfs_xattr_type {
const char *name, const void *value, HFS_TYPE,
size_t size, int flags) 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; struct hfs_find_data fd;
hfs_cat_rec rec; hfs_cat_rec rec;
@ -36,18 +40,22 @@ int hfs_setxattr(struct dentry *unused, struct inode *inode,
sizeof(struct hfs_cat_file)); sizeof(struct hfs_cat_file));
file = &rec.file; file = &rec.file;
if (!strcmp(name, "hfs.type")) { switch (type) {
case HFS_TYPE:
if (size == 4) if (size == 4)
memcpy(&file->UsrWds.fdType, value, 4); memcpy(&file->UsrWds.fdType, value, 4);
else else
res = -ERANGE; res = -ERANGE;
} else if (!strcmp(name, "hfs.creator")) { break;
case HFS_CREATOR:
if (size == 4) if (size == 4)
memcpy(&file->UsrWds.fdCreator, value, 4); memcpy(&file->UsrWds.fdCreator, value, 4);
else else
res = -ERANGE; res = -ERANGE;
} else break;
res = -EOPNOTSUPP; }
if (!res) if (!res)
hfs_bnode_write(fd.bnode, &rec, fd.entryoffset, hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
sizeof(struct hfs_cat_file)); sizeof(struct hfs_cat_file));
@ -56,8 +64,8 @@ out:
return res; return res;
} }
ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode, static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
const char *name, void *value, size_t size) void *value, size_t size)
{ {
struct hfs_find_data fd; struct hfs_find_data fd;
hfs_cat_rec rec; hfs_cat_rec rec;
@ -80,41 +88,64 @@ ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode,
} }
file = &rec.file; file = &rec.file;
if (!strcmp(name, "hfs.type")) { switch (type) {
case HFS_TYPE:
if (size >= 4) { if (size >= 4) {
memcpy(value, &file->UsrWds.fdType, 4); memcpy(value, &file->UsrWds.fdType, 4);
res = 4; res = 4;
} else } else
res = size ? -ERANGE : 4; res = size ? -ERANGE : 4;
} else if (!strcmp(name, "hfs.creator")) { break;
case HFS_CREATOR:
if (size >= 4) { if (size >= 4) {
memcpy(value, &file->UsrWds.fdCreator, 4); memcpy(value, &file->UsrWds.fdCreator, 4);
res = 4; res = 4;
} else } else
res = size ? -ERANGE : 4; res = size ? -ERANGE : 4;
} else break;
res = -ENODATA; }
out: out:
if (size) if (size)
hfs_find_exit(&fd); hfs_find_exit(&fd);
return res; return res;
} }
#define HFS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type")) static int hfs_xattr_get(const struct xattr_handler *handler,
struct dentry *unused, struct inode *inode,
ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size) 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; return -EOPNOTSUPP;
if (!buffer || !size) return __hfs_setxattr(inode, handler->flags, value, size, flags);
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;
} }
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
};

View file

@ -212,11 +212,7 @@ extern void hfs_evict_inode(struct inode *);
extern void hfs_delete_inode(struct inode *); extern void hfs_delete_inode(struct inode *);
/* attr.c */ /* attr.c */
extern int hfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name, extern const struct xattr_handler *hfs_xattr_handlers[];
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);
/* mdb.c */ /* mdb.c */
extern int hfs_mdb_get(struct super_block *); extern int hfs_mdb_get(struct super_block *);

View file

@ -15,6 +15,7 @@
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/xattr.h>
#include "hfs_fs.h" #include "hfs_fs.h"
#include "btree.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 = { static const struct inode_operations hfs_file_inode_operations = {
.lookup = hfs_file_lookup, .lookup = hfs_file_lookup,
.setattr = hfs_inode_setattr, .setattr = hfs_inode_setattr,
.setxattr = hfs_setxattr, .listxattr = generic_listxattr,
.getxattr = hfs_getxattr,
.listxattr = hfs_listxattr,
}; };

View file

@ -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_op = &hfs_super_operations;
sb->s_xattr = hfs_xattr_handlers;
sb->s_flags |= MS_NODIRATIME; sb->s_flags |= MS_NODIRATIME;
mutex_init(&sbi->bitmap_lock); mutex_init(&sbi->bitmap_lock);

View file

@ -562,10 +562,7 @@ const struct inode_operations hfsplus_dir_inode_operations = {
.symlink = hfsplus_symlink, .symlink = hfsplus_symlink,
.mknod = hfsplus_mknod, .mknod = hfsplus_mknod,
.rename = hfsplus_rename, .rename = hfsplus_rename,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = hfsplus_listxattr, .listxattr = hfsplus_listxattr,
.removexattr = generic_removexattr,
#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
.get_acl = hfsplus_get_posix_acl, .get_acl = hfsplus_get_posix_acl,
.set_acl = hfsplus_set_posix_acl, .set_acl = hfsplus_set_posix_acl,

View file

@ -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 = { static const struct inode_operations hfsplus_file_inode_operations = {
.setattr = hfsplus_setattr, .setattr = hfsplus_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = hfsplus_listxattr, .listxattr = hfsplus_listxattr,
.removexattr = generic_removexattr,
#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
.get_acl = hfsplus_get_posix_acl, .get_acl = hfsplus_get_posix_acl,
.set_acl = hfsplus_set_posix_acl, .set_acl = hfsplus_set_posix_acl,

View file

@ -140,6 +140,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
inode->i_fop = &no_open_fops; inode->i_fop = &no_open_fops;
inode->__i_nlink = 1; inode->__i_nlink = 1;
inode->i_opflags = 0; inode->i_opflags = 0;
if (sb->s_xattr)
inode->i_opflags |= IOP_XATTR;
i_uid_write(inode, 0); i_uid_write(inode, 0);
i_gid_write(inode, 0); i_gid_write(inode, 0);
atomic_set(&inode->i_writecount, 0); atomic_set(&inode->i_writecount, 0);

View file

@ -61,10 +61,7 @@ const struct inode_operations jffs2_dir_inode_operations =
.get_acl = jffs2_get_acl, .get_acl = jffs2_get_acl,
.set_acl = jffs2_set_acl, .set_acl = jffs2_set_acl,
.setattr = jffs2_setattr, .setattr = jffs2_setattr,
.setxattr = jffs2_setxattr,
.getxattr = jffs2_getxattr,
.listxattr = jffs2_listxattr, .listxattr = jffs2_listxattr,
.removexattr = jffs2_removexattr
}; };
/***********************************************************************/ /***********************************************************************/

View file

@ -66,10 +66,7 @@ const struct inode_operations jffs2_file_inode_operations =
.get_acl = jffs2_get_acl, .get_acl = jffs2_get_acl,
.set_acl = jffs2_set_acl, .set_acl = jffs2_set_acl,
.setattr = jffs2_setattr, .setattr = jffs2_setattr,
.setxattr = jffs2_setxattr,
.getxattr = jffs2_getxattr,
.listxattr = jffs2_listxattr, .listxattr = jffs2_listxattr,
.removexattr = jffs2_removexattr
}; };
const struct address_space_operations jffs2_file_address_operations = const struct address_space_operations jffs2_file_address_operations =

View file

@ -16,8 +16,5 @@ const struct inode_operations jffs2_symlink_inode_operations =
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = simple_get_link, .get_link = simple_get_link,
.setattr = jffs2_setattr, .setattr = jffs2_setattr,
.setxattr = jffs2_setxattr,
.getxattr = jffs2_getxattr,
.listxattr = jffs2_listxattr, .listxattr = jffs2_listxattr,
.removexattr = jffs2_removexattr
}; };

View file

@ -99,9 +99,6 @@ extern const struct xattr_handler jffs2_user_xattr_handler;
extern const struct xattr_handler jffs2_trusted_xattr_handler; extern const struct xattr_handler jffs2_trusted_xattr_handler;
extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); 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 #else
@ -116,9 +113,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
#define jffs2_xattr_handlers NULL #define jffs2_xattr_handlers NULL
#define jffs2_listxattr NULL #define jffs2_listxattr NULL
#define jffs2_getxattr NULL
#define jffs2_setxattr NULL
#define jffs2_removexattr NULL
#endif /* CONFIG_JFFS2_FS_XATTR */ #endif /* CONFIG_JFFS2_FS_XATTR */

View file

@ -140,10 +140,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
} }
const struct inode_operations jfs_file_inode_operations = { const struct inode_operations jfs_file_inode_operations = {
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = jfs_listxattr, .listxattr = jfs_listxattr,
.removexattr = generic_removexattr,
.setattr = jfs_setattr, .setattr = jfs_setattr,
#ifdef CONFIG_JFS_POSIX_ACL #ifdef CONFIG_JFS_POSIX_ACL
.get_acl = jfs_get_acl, .get_acl = jfs_get_acl,

View file

@ -1537,10 +1537,7 @@ const struct inode_operations jfs_dir_inode_operations = {
.rmdir = jfs_rmdir, .rmdir = jfs_rmdir,
.mknod = jfs_mknod, .mknod = jfs_mknod,
.rename = jfs_rename, .rename = jfs_rename,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = jfs_listxattr, .listxattr = jfs_listxattr,
.removexattr = generic_removexattr,
.setattr = jfs_setattr, .setattr = jfs_setattr,
#ifdef CONFIG_JFS_POSIX_ACL #ifdef CONFIG_JFS_POSIX_ACL
.get_acl = jfs_get_acl, .get_acl = jfs_get_acl,

View file

@ -25,19 +25,13 @@ const struct inode_operations jfs_fast_symlink_inode_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = simple_get_link, .get_link = simple_get_link,
.setattr = jfs_setattr, .setattr = jfs_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = jfs_listxattr, .listxattr = jfs_listxattr,
.removexattr = generic_removexattr,
}; };
const struct inode_operations jfs_symlink_inode_operations = { const struct inode_operations jfs_symlink_inode_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = page_get_link, .get_link = page_get_link,
.setattr = jfs_setattr, .setattr = jfs_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = jfs_listxattr, .listxattr = jfs_listxattr,
.removexattr = generic_removexattr,
}; };

View file

@ -1126,9 +1126,6 @@ const struct inode_operations kernfs_dir_iops = {
.permission = kernfs_iop_permission, .permission = kernfs_iop_permission,
.setattr = kernfs_iop_setattr, .setattr = kernfs_iop_setattr,
.getattr = kernfs_iop_getattr, .getattr = kernfs_iop_getattr,
.setxattr = kernfs_iop_setxattr,
.removexattr = kernfs_iop_removexattr,
.getxattr = kernfs_iop_getxattr,
.listxattr = kernfs_iop_listxattr, .listxattr = kernfs_iop_listxattr,
.mkdir = kernfs_iop_mkdir, .mkdir = kernfs_iop_mkdir,

View file

@ -28,9 +28,6 @@ static const struct inode_operations kernfs_iops = {
.permission = kernfs_iop_permission, .permission = kernfs_iop_permission,
.setattr = kernfs_iop_setattr, .setattr = kernfs_iop_setattr,
.getattr = kernfs_iop_getattr, .getattr = kernfs_iop_getattr,
.setxattr = kernfs_iop_setxattr,
.removexattr = kernfs_iop_removexattr,
.getxattr = kernfs_iop_getxattr,
.listxattr = kernfs_iop_listxattr, .listxattr = kernfs_iop_listxattr,
}; };
@ -138,17 +135,12 @@ out:
return error; 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) u32 *secdata_len)
{ {
struct kernfs_iattrs *attrs;
void *old_secdata; void *old_secdata;
size_t old_secdata_len; size_t old_secdata_len;
attrs = kernfs_iattrs(kn);
if (!attrs)
return -ENOMEM;
old_secdata = attrs->ia_secdata; old_secdata = attrs->ia_secdata;
old_secdata_len = attrs->ia_secdata_len; old_secdata_len = attrs->ia_secdata_len;
@ -160,71 +152,6 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
return 0; 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) ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
{ {
struct kernfs_node *kn = dentry->d_fsdata; 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); 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
};

View file

@ -76,17 +76,12 @@ extern struct kmem_cache *kernfs_node_cache;
/* /*
* inode.c * inode.c
*/ */
extern const struct xattr_handler *kernfs_xattr_handlers[];
void kernfs_evict_inode(struct inode *inode); void kernfs_evict_inode(struct inode *inode);
int kernfs_iop_permission(struct inode *inode, int mask); int kernfs_iop_permission(struct inode *inode, int mask);
int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr); int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);
int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry, int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat); 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); ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size);
/* /*

View file

@ -158,6 +158,7 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
sb->s_blocksize_bits = PAGE_SHIFT; sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_magic = magic; sb->s_magic = magic;
sb->s_op = &kernfs_sops; sb->s_op = &kernfs_sops;
sb->s_xattr = kernfs_xattr_handlers;
sb->s_time_gran = 1; sb->s_time_gran = 1;
/* get root inode, initialize and unlock it */ /* get root inode, initialize and unlock it */

View file

@ -134,9 +134,6 @@ static const char *kernfs_iop_get_link(struct dentry *dentry,
} }
const struct inode_operations kernfs_symlink_iops = { const struct inode_operations kernfs_symlink_iops = {
.setxattr = kernfs_iop_setxattr,
.removexattr = kernfs_iop_removexattr,
.getxattr = kernfs_iop_getxattr,
.listxattr = kernfs_iop_listxattr, .listxattr = kernfs_iop_listxattr,
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = kernfs_iop_get_link, .get_link = kernfs_iop_get_link,

View file

@ -236,8 +236,8 @@ static const struct super_operations simple_super_operations = {
* Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
* will never be mountable) * will never be mountable)
*/ */
struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name, struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, char *name,
const struct super_operations *ops, const struct super_operations *ops, const struct xattr_handler **xattr,
const struct dentry_operations *dops, unsigned long magic) const struct dentry_operations *dops, unsigned long magic)
{ {
struct super_block *s; 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_blocksize_bits = PAGE_SHIFT;
s->s_magic = magic; s->s_magic = magic;
s->s_op = ops ? ops : &simple_super_operations; s->s_op = ops ? ops : &simple_super_operations;
s->s_xattr = xattr;
s->s_time_gran = 1; s->s_time_gran = 1;
root = new_inode(s); root = new_inode(s);
if (!root) if (!root)
@ -281,7 +282,7 @@ Enomem:
deactivate_locked_super(s); deactivate_locked_super(s);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
EXPORT_SYMBOL(mount_pseudo); EXPORT_SYMBOL(mount_pseudo_xattr);
int simple_open(struct inode *inode, struct file *file) 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; 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) static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
@ -1177,9 +1160,6 @@ static const struct inode_operations empty_dir_inode_operations = {
.permission = generic_permission, .permission = generic_permission,
.setattr = empty_dir_setattr, .setattr = empty_dir_setattr,
.getattr = empty_dir_getattr, .getattr = empty_dir_getattr,
.setxattr = empty_dir_setxattr,
.getxattr = empty_dir_getxattr,
.removexattr = empty_dir_removexattr,
.listxattr = empty_dir_listxattr, .listxattr = empty_dir_listxattr,
}; };
@ -1215,6 +1195,7 @@ void make_empty_dir_inode(struct inode *inode)
inode->i_blocks = 0; inode->i_blocks = 0;
inode->i_op = &empty_dir_inode_operations; inode->i_op = &empty_dir_inode_operations;
inode->i_opflags &= ~IOP_XATTR;
inode->i_fop = &empty_dir_operations; inode->i_fop = &empty_dir_operations;
} }

View file

@ -899,9 +899,6 @@ static const struct inode_operations nfs3_dir_inode_operations = {
.setattr = nfs_setattr, .setattr = nfs_setattr,
#ifdef CONFIG_NFS_V3_ACL #ifdef CONFIG_NFS_V3_ACL
.listxattr = nfs3_listxattr, .listxattr = nfs3_listxattr,
.getxattr = generic_getxattr,
.setxattr = generic_setxattr,
.removexattr = generic_removexattr,
.get_acl = nfs3_get_acl, .get_acl = nfs3_get_acl,
.set_acl = nfs3_set_acl, .set_acl = nfs3_set_acl,
#endif #endif
@ -913,9 +910,6 @@ static const struct inode_operations nfs3_file_inode_operations = {
.setattr = nfs_setattr, .setattr = nfs_setattr,
#ifdef CONFIG_NFS_V3_ACL #ifdef CONFIG_NFS_V3_ACL
.listxattr = nfs3_listxattr, .listxattr = nfs3_listxattr,
.getxattr = generic_getxattr,
.setxattr = generic_setxattr,
.removexattr = generic_removexattr,
.get_acl = nfs3_get_acl, .get_acl = nfs3_get_acl,
.set_acl = nfs3_set_acl, .set_acl = nfs3_set_acl,
#endif #endif

View file

@ -8941,20 +8941,14 @@ static const struct inode_operations nfs4_dir_inode_operations = {
.permission = nfs_permission, .permission = nfs_permission,
.getattr = nfs_getattr, .getattr = nfs_getattr,
.setattr = nfs_setattr, .setattr = nfs_setattr,
.getxattr = generic_getxattr,
.setxattr = generic_setxattr,
.listxattr = nfs4_listxattr, .listxattr = nfs4_listxattr,
.removexattr = generic_removexattr,
}; };
static const struct inode_operations nfs4_file_inode_operations = { static const struct inode_operations nfs4_file_inode_operations = {
.permission = nfs_permission, .permission = nfs_permission,
.getattr = nfs_getattr, .getattr = nfs_getattr,
.setattr = nfs_setattr, .setattr = nfs_setattr,
.getxattr = generic_getxattr,
.setxattr = generic_setxattr,
.listxattr = nfs4_listxattr, .listxattr = nfs4_listxattr,
.removexattr = generic_removexattr,
}; };
const struct nfs_rpc_ops nfs_v4_clientops = { const struct nfs_rpc_ops nfs_v4_clientops = {

View file

@ -2444,10 +2444,7 @@ const struct inode_operations ocfs2_file_iops = {
.setattr = ocfs2_setattr, .setattr = ocfs2_setattr,
.getattr = ocfs2_getattr, .getattr = ocfs2_getattr,
.permission = ocfs2_permission, .permission = ocfs2_permission,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ocfs2_listxattr, .listxattr = ocfs2_listxattr,
.removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap, .fiemap = ocfs2_fiemap,
.get_acl = ocfs2_iop_get_acl, .get_acl = ocfs2_iop_get_acl,
.set_acl = ocfs2_iop_set_acl, .set_acl = ocfs2_iop_set_acl,

View file

@ -2913,10 +2913,7 @@ const struct inode_operations ocfs2_dir_iops = {
.setattr = ocfs2_setattr, .setattr = ocfs2_setattr,
.getattr = ocfs2_getattr, .getattr = ocfs2_getattr,
.permission = ocfs2_permission, .permission = ocfs2_permission,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ocfs2_listxattr, .listxattr = ocfs2_listxattr,
.removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap, .fiemap = ocfs2_fiemap,
.get_acl = ocfs2_iop_get_acl, .get_acl = ocfs2_iop_get_acl,
.set_acl = ocfs2_iop_set_acl, .set_acl = ocfs2_iop_set_acl,

View file

@ -91,9 +91,6 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
.get_link = page_get_link, .get_link = page_get_link,
.getattr = ocfs2_getattr, .getattr = ocfs2_getattr,
.setattr = ocfs2_setattr, .setattr = ocfs2_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ocfs2_listxattr, .listxattr = ocfs2_listxattr,
.removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap, .fiemap = ocfs2_fiemap,
}; };

View file

@ -296,10 +296,7 @@ const struct inode_operations orangefs_file_inode_operations = {
.set_acl = orangefs_set_acl, .set_acl = orangefs_set_acl,
.setattr = orangefs_setattr, .setattr = orangefs_setattr,
.getattr = orangefs_getattr, .getattr = orangefs_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = orangefs_listxattr, .listxattr = orangefs_listxattr,
.removexattr = generic_removexattr,
.permission = orangefs_permission, .permission = orangefs_permission,
}; };

View file

@ -462,9 +462,6 @@ const struct inode_operations orangefs_dir_inode_operations = {
.rename = orangefs_rename, .rename = orangefs_rename,
.setattr = orangefs_setattr, .setattr = orangefs_setattr,
.getattr = orangefs_getattr, .getattr = orangefs_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = orangefs_listxattr, .listxattr = orangefs_listxattr,
.permission = orangefs_permission, .permission = orangefs_permission,
}; };

View file

@ -14,6 +14,5 @@ const struct inode_operations orangefs_symlink_inode_operations = {
.setattr = orangefs_setattr, .setattr = orangefs_setattr,
.getattr = orangefs_getattr, .getattr = orangefs_getattr,
.listxattr = orangefs_listxattr, .listxattr = orangefs_listxattr,
.setxattr = generic_setxattr,
.permission = orangefs_permission, .permission = orangefs_permission,
}; };

View file

@ -73,6 +73,9 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
"%s: name %s, buffer_size %zd\n", "%s: name %s, buffer_size %zd\n",
__func__, name, size); __func__, name, size);
if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) { if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) {
gossip_err("Invalid key length (%d)\n", gossip_err("Invalid key length (%d)\n",
(int)strlen(name)); (int)strlen(name));

View file

@ -58,8 +58,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
char *buf, *name, *value = NULL; char *buf, *name, *value = NULL;
int uninitialized_var(error); int uninitialized_var(error);
if (!old->d_inode->i_op->getxattr || if (!(old->d_inode->i_opflags & IOP_XATTR) ||
!new->d_inode->i_op->getxattr) !(new->d_inode->i_opflags & IOP_XATTR))
return 0; return 0;
list_size = vfs_listxattr(old, NULL, 0); list_size = vfs_listxattr(old, NULL, 0);

View file

@ -1013,10 +1013,7 @@ const struct inode_operations ovl_dir_inode_operations = {
.mknod = ovl_mknod, .mknod = ovl_mknod,
.permission = ovl_permission, .permission = ovl_permission,
.getattr = ovl_dir_getattr, .getattr = ovl_dir_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ovl_listxattr, .listxattr = ovl_listxattr,
.removexattr = generic_removexattr,
.get_acl = ovl_get_acl, .get_acl = ovl_get_acl,
.update_time = ovl_update_time, .update_time = ovl_update_time,
}; };

View file

@ -367,10 +367,7 @@ static const struct inode_operations ovl_file_inode_operations = {
.setattr = ovl_setattr, .setattr = ovl_setattr,
.permission = ovl_permission, .permission = ovl_permission,
.getattr = ovl_getattr, .getattr = ovl_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ovl_listxattr, .listxattr = ovl_listxattr,
.removexattr = generic_removexattr,
.get_acl = ovl_get_acl, .get_acl = ovl_get_acl,
.update_time = ovl_update_time, .update_time = ovl_update_time,
}; };
@ -380,10 +377,7 @@ static const struct inode_operations ovl_symlink_inode_operations = {
.get_link = ovl_get_link, .get_link = ovl_get_link,
.readlink = ovl_readlink, .readlink = ovl_readlink,
.getattr = ovl_getattr, .getattr = ovl_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ovl_listxattr, .listxattr = ovl_listxattr,
.removexattr = generic_removexattr,
.update_time = ovl_update_time, .update_time = ovl_update_time,
}; };

View file

@ -275,10 +275,10 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
char val; char val;
struct inode *inode = dentry->d_inode; 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; 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') if (res == 1 && val == 'y')
return true; return true;

View file

@ -260,10 +260,7 @@ const struct file_operations reiserfs_file_operations = {
const struct inode_operations reiserfs_file_inode_operations = { const struct inode_operations reiserfs_file_inode_operations = {
.setattr = reiserfs_setattr, .setattr = reiserfs_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = reiserfs_listxattr, .listxattr = reiserfs_listxattr,
.removexattr = generic_removexattr,
.permission = reiserfs_permission, .permission = reiserfs_permission,
.get_acl = reiserfs_get_acl, .get_acl = reiserfs_get_acl,
.set_acl = reiserfs_set_acl, .set_acl = reiserfs_set_acl,

View file

@ -1650,10 +1650,7 @@ const struct inode_operations reiserfs_dir_inode_operations = {
.mknod = reiserfs_mknod, .mknod = reiserfs_mknod,
.rename = reiserfs_rename, .rename = reiserfs_rename,
.setattr = reiserfs_setattr, .setattr = reiserfs_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = reiserfs_listxattr, .listxattr = reiserfs_listxattr,
.removexattr = generic_removexattr,
.permission = reiserfs_permission, .permission = reiserfs_permission,
.get_acl = reiserfs_get_acl, .get_acl = reiserfs_get_acl,
.set_acl = reiserfs_set_acl, .set_acl = reiserfs_set_acl,
@ -1667,10 +1664,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = page_get_link, .get_link = page_get_link,
.setattr = reiserfs_setattr, .setattr = reiserfs_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = reiserfs_listxattr, .listxattr = reiserfs_listxattr,
.removexattr = generic_removexattr,
.permission = reiserfs_permission, .permission = reiserfs_permission,
}; };
@ -1679,10 +1673,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
*/ */
const struct inode_operations reiserfs_special_inode_operations = { const struct inode_operations reiserfs_special_inode_operations = {
.setattr = reiserfs_setattr, .setattr = reiserfs_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = reiserfs_listxattr, .listxattr = reiserfs_listxattr,
.removexattr = generic_removexattr,
.permission = reiserfs_permission, .permission = reiserfs_permission,
.get_acl = reiserfs_get_acl, .get_acl = reiserfs_get_acl,
.set_acl = reiserfs_set_acl, .set_acl = reiserfs_set_acl,

View file

@ -425,7 +425,6 @@ failed_read:
const struct inode_operations squashfs_inode_ops = { const struct inode_operations squashfs_inode_ops = {
.getxattr = generic_getxattr,
.listxattr = squashfs_listxattr .listxattr = squashfs_listxattr
}; };

View file

@ -247,6 +247,5 @@ failed:
const struct inode_operations squashfs_dir_inode_ops = { const struct inode_operations squashfs_dir_inode_ops = {
.lookup = squashfs_lookup, .lookup = squashfs_lookup,
.getxattr = generic_getxattr,
.listxattr = squashfs_listxattr .listxattr = squashfs_listxattr
}; };

View file

@ -120,7 +120,6 @@ const struct address_space_operations squashfs_symlink_aops = {
const struct inode_operations squashfs_symlink_inode_ops = { const struct inode_operations squashfs_symlink_inode_ops = {
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = page_get_link, .get_link = page_get_link,
.getxattr = generic_getxattr,
.listxattr = squashfs_listxattr .listxattr = squashfs_listxattr
}; };

View file

@ -42,6 +42,5 @@ static inline int squashfs_xattr_lookup(struct super_block *sb,
return 0; return 0;
} }
#define squashfs_listxattr NULL #define squashfs_listxattr NULL
#define generic_getxattr NULL
#define squashfs_xattr_handlers NULL #define squashfs_xattr_handlers NULL
#endif #endif

View file

@ -1182,10 +1182,7 @@ const struct inode_operations ubifs_dir_inode_operations = {
.rename = ubifs_rename, .rename = ubifs_rename,
.setattr = ubifs_setattr, .setattr = ubifs_setattr,
.getattr = ubifs_getattr, .getattr = ubifs_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ubifs_listxattr, .listxattr = ubifs_listxattr,
.removexattr = generic_removexattr,
#ifdef CONFIG_UBIFS_ATIME_SUPPORT #ifdef CONFIG_UBIFS_ATIME_SUPPORT
.update_time = ubifs_update_time, .update_time = ubifs_update_time,
#endif #endif

View file

@ -1621,10 +1621,7 @@ const struct address_space_operations ubifs_file_address_operations = {
const struct inode_operations ubifs_file_inode_operations = { const struct inode_operations ubifs_file_inode_operations = {
.setattr = ubifs_setattr, .setattr = ubifs_setattr,
.getattr = ubifs_getattr, .getattr = ubifs_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ubifs_listxattr, .listxattr = ubifs_listxattr,
.removexattr = generic_removexattr,
#ifdef CONFIG_UBIFS_ATIME_SUPPORT #ifdef CONFIG_UBIFS_ATIME_SUPPORT
.update_time = ubifs_update_time, .update_time = ubifs_update_time,
#endif #endif
@ -1635,10 +1632,7 @@ const struct inode_operations ubifs_symlink_inode_operations = {
.get_link = simple_get_link, .get_link = simple_get_link,
.setattr = ubifs_setattr, .setattr = ubifs_setattr,
.getattr = ubifs_getattr, .getattr = ubifs_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ubifs_listxattr, .listxattr = ubifs_listxattr,
.removexattr = generic_removexattr,
#ifdef CONFIG_UBIFS_ATIME_SUPPORT #ifdef CONFIG_UBIFS_ATIME_SUPPORT
.update_time = ubifs_update_time, .update_time = ubifs_update_time,
#endif #endif

View file

@ -24,6 +24,59 @@
#include <asm/uaccess.h> #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 * Check permissions for extended attribute access. This is a bit complicated
* because different namespaces have very different rules. * 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); 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 * __vfs_setxattr_noperm - perform setxattr operation without performing
* permission checks. * permission checks.
@ -106,8 +176,8 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
if (issec) if (issec)
inode->i_flags &= ~S_NOSEC; inode->i_flags &= ~S_NOSEC;
if (inode->i_op->setxattr) { if (inode->i_opflags & IOP_XATTR) {
error = inode->i_op->setxattr(dentry, inode, name, value, size, flags); error = __vfs_setxattr(dentry, inode, name, value, size, flags);
if (!error) { if (!error) {
fsnotify_xattr(dentry); fsnotify_xattr(dentry);
security_inode_post_setxattr(dentry, name, value, security_inode_post_setxattr(dentry, name, value,
@ -115,6 +185,9 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
} }
} else if (issec) { } else if (issec) {
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN; const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
if (unlikely(is_bad_inode(inode)))
return -EIO;
error = security_inode_setsecurity(inode, suffix, value, error = security_inode_setsecurity(inode, suffix, value,
size, flags); size, flags);
if (!error) if (!error)
@ -188,6 +261,7 @@ ssize_t
vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
size_t xattr_size, gfp_t flags) size_t xattr_size, gfp_t flags)
{ {
const struct xattr_handler *handler;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
char *value = *xattr_value; char *value = *xattr_value;
int error; int error;
@ -196,10 +270,12 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
if (error) if (error)
return 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; return -EOPNOTSUPP;
error = handler->get(handler, dentry, inode, name, NULL, 0);
error = inode->i_op->getxattr(dentry, inode, name, NULL, 0);
if (error < 0) if (error < 0)
return error; return error;
@ -210,11 +286,26 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
memset(value, 0, error + 1); 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; *xattr_value = value;
return error; 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 ssize_t
vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) 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; return ret;
} }
nolsm: nolsm:
if (inode->i_op->getxattr) return __vfs_getxattr(dentry, inode, name, value, size);
error = inode->i_op->getxattr(dentry, inode, name, value, size);
else
error = -EOPNOTSUPP;
return error;
} }
EXPORT_SYMBOL_GPL(vfs_getxattr); EXPORT_SYMBOL_GPL(vfs_getxattr);
ssize_t 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; ssize_t error;
error = security_inode_listxattr(d); error = security_inode_listxattr(dentry);
if (error) if (error)
return error; return error;
if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
error = -EOPNOTSUPP; error = -EOPNOTSUPP;
if (d->d_inode->i_op->listxattr) { error = inode->i_op->listxattr(dentry, list, size);
error = d->d_inode->i_op->listxattr(d, list, size);
} else { } else {
error = security_inode_listsecurity(d->d_inode, list, size); error = security_inode_listsecurity(inode, list, size);
if (size && error > size) if (size && error > size)
error = -ERANGE; error = -ERANGE;
} }
@ -271,15 +358,27 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
} }
EXPORT_SYMBOL_GPL(vfs_listxattr); 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 int
vfs_removexattr(struct dentry *dentry, const char *name) vfs_removexattr(struct dentry *dentry, const char *name)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int error; int error;
if (!inode->i_op->removexattr)
return -EOPNOTSUPP;
error = xattr_permission(inode, name, MAY_WRITE); error = xattr_permission(inode, name, MAY_WRITE);
if (error) if (error)
return error; return error;
@ -289,7 +388,7 @@ vfs_removexattr(struct dentry *dentry, const char *name)
if (error) if (error)
goto out; goto out;
error = inode->i_op->removexattr(dentry, name); error = __vfs_removexattr(dentry, name);
if (!error) { if (!error) {
fsnotify_xattr(dentry); fsnotify_xattr(dentry);
@ -641,76 +740,6 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
return error; 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 * Combine the results of the list() operation from every xattr_handler in the
* list. * list.
@ -747,44 +776,7 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
} }
return 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_listxattr);
EXPORT_SYMBOL(generic_setxattr);
EXPORT_SYMBOL(generic_removexattr);
/** /**
* xattr_full_name - Compute full attribute name from suffix * xattr_full_name - Compute full attribute name from suffix

View file

@ -1066,9 +1066,6 @@ static const struct inode_operations xfs_inode_operations = {
.set_acl = xfs_set_acl, .set_acl = xfs_set_acl,
.getattr = xfs_vn_getattr, .getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr, .setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr, .listxattr = xfs_vn_listxattr,
.fiemap = xfs_vn_fiemap, .fiemap = xfs_vn_fiemap,
.update_time = xfs_vn_update_time, .update_time = xfs_vn_update_time,
@ -1094,9 +1091,6 @@ static const struct inode_operations xfs_dir_inode_operations = {
.set_acl = xfs_set_acl, .set_acl = xfs_set_acl,
.getattr = xfs_vn_getattr, .getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr, .setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr, .listxattr = xfs_vn_listxattr,
.update_time = xfs_vn_update_time, .update_time = xfs_vn_update_time,
.tmpfile = xfs_vn_tmpfile, .tmpfile = xfs_vn_tmpfile,
@ -1122,9 +1116,6 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
.set_acl = xfs_set_acl, .set_acl = xfs_set_acl,
.getattr = xfs_vn_getattr, .getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr, .setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr, .listxattr = xfs_vn_listxattr,
.update_time = xfs_vn_update_time, .update_time = xfs_vn_update_time,
.tmpfile = xfs_vn_tmpfile, .tmpfile = xfs_vn_tmpfile,
@ -1135,9 +1126,6 @@ static const struct inode_operations xfs_symlink_inode_operations = {
.get_link = xfs_vn_get_link, .get_link = xfs_vn_get_link,
.getattr = xfs_vn_getattr, .getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr, .setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr, .listxattr = xfs_vn_listxattr,
.update_time = xfs_vn_update_time, .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, .get_link = xfs_vn_get_link_inline,
.getattr = xfs_vn_getattr, .getattr = xfs_vn_getattr,
.setattr = xfs_vn_setattr, .setattr = xfs_vn_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = xfs_vn_listxattr, .listxattr = xfs_vn_listxattr,
.update_time = xfs_vn_update_time, .update_time = xfs_vn_update_time,
}; };

View file

@ -592,6 +592,7 @@ is_uncached_acl(struct posix_acl *acl)
#define IOP_FASTPERM 0x0001 #define IOP_FASTPERM 0x0001
#define IOP_LOOKUP 0x0002 #define IOP_LOOKUP 0x0002
#define IOP_NOFOLLOW 0x0004 #define IOP_NOFOLLOW 0x0004
#define IOP_XATTR 0x0008
/* /*
* Keep mostly read-only and often accessed (especially for * Keep mostly read-only and often accessed (especially for
@ -1751,12 +1752,7 @@ struct inode_operations {
struct inode *, struct dentry *, unsigned int); struct inode *, struct dentry *, unsigned int);
int (*setattr) (struct dentry *, struct iattr *); int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, struct inode *,
const char *, const void *, size_t, int);
ssize_t (*getxattr) (struct dentry *, struct inode *,
const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
u64 len); u64 len);
int (*update_time)(struct inode *, struct timespec *, int); int (*update_time)(struct inode *, struct timespec *, int);
@ -2087,11 +2083,20 @@ struct super_block *sget(struct file_system_type *type,
int (*test)(struct super_block *,void *), int (*test)(struct super_block *,void *),
int (*set)(struct super_block *,void *), int (*set)(struct super_block *,void *),
int flags, void *data); int flags, void *data);
extern struct dentry *mount_pseudo(struct file_system_type *, char *, extern struct dentry *mount_pseudo_xattr(struct file_system_type *, char *,
const struct super_operations *ops, const struct super_operations *ops,
const struct xattr_handler **xattr,
const struct dentry_operations *dops, const struct dentry_operations *dops,
unsigned long); unsigned long);
static inline struct dentry *
mount_pseudo(struct file_system_type *fs_type, char *name,
const struct super_operations *ops,
const struct dentry_operations *dops, unsigned long magic)
{
return mount_pseudo_xattr(fs_type, name, ops, NULL, dops, magic);
}
/* Alas, no aliases. Too much hassle with bringing module.h everywhere */ /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
#define fops_get(fops) \ #define fops_get(fops) \
(((fops) && try_module_get((fops)->owner) ? (fops) : NULL)) (((fops) && try_module_get((fops)->owner) ? (fops) : NULL))

View file

@ -46,17 +46,16 @@ struct xattr {
}; };
ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t); ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
ssize_t __vfs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t);
ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t); ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
int __vfs_setxattr(struct dentry *, struct inode *, const char *, const void *, size_t, int);
int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, int); int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, int);
int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int); int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
int __vfs_removexattr(struct dentry *, const char *);
int vfs_removexattr(struct dentry *, const char *); int vfs_removexattr(struct dentry *, const char *);
ssize_t generic_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size);
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size); ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
int generic_setxattr(struct dentry *dentry, struct inode *inode,
const char *name, const void *value, size_t size, int flags);
int generic_removexattr(struct dentry *dentry, const char *name);
ssize_t vfs_getxattr_alloc(struct dentry *dentry, const char *name, ssize_t vfs_getxattr_alloc(struct dentry *dentry, const char *name,
char **xattr_value, size_t size, gfp_t flags); char **xattr_value, size_t size, gfp_t flags);

View file

@ -3175,10 +3175,7 @@ static const struct inode_operations shmem_short_symlink_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = simple_get_link, .get_link = simple_get_link,
#ifdef CONFIG_TMPFS_XATTR #ifdef CONFIG_TMPFS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = shmem_listxattr, .listxattr = shmem_listxattr,
.removexattr = generic_removexattr,
#endif #endif
}; };
@ -3186,10 +3183,7 @@ static const struct inode_operations shmem_symlink_inode_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.get_link = shmem_get_link, .get_link = shmem_get_link,
#ifdef CONFIG_TMPFS_XATTR #ifdef CONFIG_TMPFS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = shmem_listxattr, .listxattr = shmem_listxattr,
.removexattr = generic_removexattr,
#endif #endif
}; };
@ -3683,10 +3677,7 @@ static const struct inode_operations shmem_inode_operations = {
.getattr = shmem_getattr, .getattr = shmem_getattr,
.setattr = shmem_setattr, .setattr = shmem_setattr,
#ifdef CONFIG_TMPFS_XATTR #ifdef CONFIG_TMPFS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = shmem_listxattr, .listxattr = shmem_listxattr,
.removexattr = generic_removexattr,
.set_acl = simple_set_acl, .set_acl = simple_set_acl,
#endif #endif
}; };
@ -3705,10 +3696,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
.tmpfile = shmem_tmpfile, .tmpfile = shmem_tmpfile,
#endif #endif
#ifdef CONFIG_TMPFS_XATTR #ifdef CONFIG_TMPFS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = shmem_listxattr, .listxattr = shmem_listxattr,
.removexattr = generic_removexattr,
#endif #endif
#ifdef CONFIG_TMPFS_POSIX_ACL #ifdef CONFIG_TMPFS_POSIX_ACL
.setattr = shmem_setattr, .setattr = shmem_setattr,
@ -3718,10 +3706,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
static const struct inode_operations shmem_special_inode_operations = { static const struct inode_operations shmem_special_inode_operations = {
#ifdef CONFIG_TMPFS_XATTR #ifdef CONFIG_TMPFS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = shmem_listxattr, .listxattr = shmem_listxattr,
.removexattr = generic_removexattr,
#endif #endif
#ifdef CONFIG_TMPFS_POSIX_ACL #ifdef CONFIG_TMPFS_POSIX_ACL
.setattr = shmem_setattr, .setattr = shmem_setattr,

View file

@ -320,10 +320,37 @@ static const struct dentry_operations sockfs_dentry_operations = {
.d_dname = sockfs_dname, .d_dname = sockfs_dname,
}; };
static int sockfs_xattr_get(const struct xattr_handler *handler,
struct dentry *dentry, struct inode *inode,
const char *suffix, void *value, size_t size)
{
if (value) {
if (dentry->d_name.len + 1 > size)
return -ERANGE;
memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
}
return dentry->d_name.len + 1;
}
#define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
#define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
#define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
static const struct xattr_handler sockfs_xattr_handler = {
.name = XATTR_NAME_SOCKPROTONAME,
.get = sockfs_xattr_get,
};
static const struct xattr_handler *sockfs_xattr_handlers[] = {
&sockfs_xattr_handler,
NULL
};
static struct dentry *sockfs_mount(struct file_system_type *fs_type, static struct dentry *sockfs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data) int flags, const char *dev_name, void *data)
{ {
return mount_pseudo(fs_type, "socket:", &sockfs_ops, return mount_pseudo_xattr(fs_type, "socket:", &sockfs_ops,
sockfs_xattr_handlers,
&sockfs_dentry_operations, SOCKFS_MAGIC); &sockfs_dentry_operations, SOCKFS_MAGIC);
} }
@ -463,35 +490,6 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
return NULL; return NULL;
} }
#define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
#define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
#define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
static ssize_t sockfs_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size)
{
const char *proto_name;
size_t proto_size;
int error;
error = -ENODATA;
if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
proto_name = dentry->d_name.name;
proto_size = strlen(proto_name);
if (value) {
error = -ERANGE;
if (proto_size + 1 > size)
goto out;
strncpy(value, proto_name, proto_size + 1);
}
error = proto_size + 1;
}
out:
return error;
}
static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer, static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
size_t size) size_t size)
{ {
@ -521,7 +519,6 @@ static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
} }
static const struct inode_operations sockfs_inode_ops = { static const struct inode_operations sockfs_inode_ops = {
.getxattr = sockfs_getxattr,
.listxattr = sockfs_listxattr, .listxattr = sockfs_listxattr,
}; };

View file

@ -310,13 +310,8 @@ int cap_inode_need_killpriv(struct dentry *dentry)
struct inode *inode = d_backing_inode(dentry); struct inode *inode = d_backing_inode(dentry);
int error; int error;
if (!inode->i_op->getxattr) error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
return 0; return error > 0;
error = inode->i_op->getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
if (error <= 0)
return 0;
return 1;
} }
/** /**
@ -329,12 +324,12 @@ int cap_inode_need_killpriv(struct dentry *dentry)
*/ */
int cap_inode_killpriv(struct dentry *dentry) int cap_inode_killpriv(struct dentry *dentry)
{ {
struct inode *inode = d_backing_inode(dentry); int error;
if (!inode->i_op->removexattr) error = __vfs_removexattr(dentry, XATTR_NAME_CAPS);
return 0; if (error == -EOPNOTSUPP)
error = 0;
return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); return error;
} }
/* /*
@ -394,10 +389,10 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
if (!inode || !inode->i_op->getxattr) if (!inode)
return -ENODATA; return -ENODATA;
size = inode->i_op->getxattr((struct dentry *)dentry, inode, size = __vfs_getxattr((struct dentry *)dentry, inode,
XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ); XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ);
if (size == -ENODATA || size == -EOPNOTSUPP) if (size == -ENODATA || size == -EOPNOTSUPP)
/* no data, that's ok */ /* no data, that's ok */

View file

@ -182,8 +182,9 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
int error; int error;
int size; int size;
if (!inode->i_op->getxattr) if (!(inode->i_opflags & IOP_XATTR))
return -EOPNOTSUPP; return -EOPNOTSUPP;
desc = init_desc(type); desc = init_desc(type);
if (IS_ERR(desc)) if (IS_ERR(desc))
return PTR_ERR(desc); return PTR_ERR(desc);
@ -253,8 +254,8 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
&xattr_data, &xattr_data,
sizeof(xattr_data), 0); sizeof(xattr_data), 0);
} else if (rc == -ENODATA && inode->i_op->removexattr) { } else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) {
rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM); rc = __vfs_removexattr(dentry, XATTR_NAME_EVM);
} }
return rc; return rc;
} }

View file

@ -78,11 +78,11 @@ static int evm_find_protected_xattrs(struct dentry *dentry)
int error; int error;
int count = 0; int count = 0;
if (!inode->i_op->getxattr) if (!(inode->i_opflags & IOP_XATTR))
return -EOPNOTSUPP; return -EOPNOTSUPP;
for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) { for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
error = inode->i_op->getxattr(dentry, inode, *xattr, NULL, 0); error = __vfs_getxattr(dentry, inode, *xattr, NULL, 0);
if (error < 0) { if (error < 0) {
if (error == -ENODATA) if (error == -ENODATA)
continue; continue;

View file

@ -165,13 +165,13 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
int ima_read_xattr(struct dentry *dentry, int ima_read_xattr(struct dentry *dentry,
struct evm_ima_xattr_data **xattr_value) struct evm_ima_xattr_data **xattr_value)
{ {
struct inode *inode = d_backing_inode(dentry); ssize_t ret;
if (!inode->i_op->getxattr) ret = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
return 0;
return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
0, GFP_NOFS); 0, GFP_NOFS);
if (ret == -EOPNOTSUPP)
ret = 0;
return ret;
} }
/* /*
@ -195,7 +195,7 @@ int ima_appraise_measurement(enum ima_hooks func,
enum integrity_status status = INTEGRITY_UNKNOWN; enum integrity_status status = INTEGRITY_UNKNOWN;
int rc = xattr_len, hash_start = 0; int rc = xattr_len, hash_start = 0;
if (!inode->i_op->getxattr) if (!(inode->i_opflags & IOP_XATTR))
return INTEGRITY_UNKNOWN; return INTEGRITY_UNKNOWN;
if (rc <= 0) { if (rc <= 0) {
@ -322,10 +322,10 @@ void ima_inode_post_setattr(struct dentry *dentry)
{ {
struct inode *inode = d_backing_inode(dentry); struct inode *inode = d_backing_inode(dentry);
struct integrity_iint_cache *iint; struct integrity_iint_cache *iint;
int must_appraise, rc; int must_appraise;
if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
|| !inode->i_op->removexattr) || !(inode->i_opflags & IOP_XATTR))
return; return;
must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
@ -338,8 +338,7 @@ void ima_inode_post_setattr(struct dentry *dentry)
iint->flags |= IMA_APPRAISE; iint->flags |= IMA_APPRAISE;
} }
if (!must_appraise) if (!must_appraise)
rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); __vfs_removexattr(dentry, XATTR_NAME_IMA);
return;
} }
/* /*

View file

@ -507,14 +507,14 @@ static int sb_finish_set_opts(struct super_block *sb)
the root directory. -ENODATA is ok, as this may be the root directory. -ENODATA is ok, as this may be
the first boot of the SELinux kernel before we have the first boot of the SELinux kernel before we have
assigned xattr values to the filesystem. */ assigned xattr values to the filesystem. */
if (!root_inode->i_op->getxattr) { if (!(root_inode->i_opflags & IOP_XATTR)) {
printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
"xattr support\n", sb->s_id, sb->s_type->name); "xattr support\n", sb->s_id, sb->s_type->name);
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
goto out; goto out;
} }
rc = root_inode->i_op->getxattr(root, root_inode,
XATTR_NAME_SELINUX, NULL, 0); rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
if (rc < 0 && rc != -ENODATA) { if (rc < 0 && rc != -ENODATA) {
if (rc == -EOPNOTSUPP) if (rc == -EOPNOTSUPP)
printk(KERN_WARNING "SELinux: (dev %s, type " printk(KERN_WARNING "SELinux: (dev %s, type "
@ -1410,11 +1410,10 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
case SECURITY_FS_USE_NATIVE: case SECURITY_FS_USE_NATIVE:
break; break;
case SECURITY_FS_USE_XATTR: case SECURITY_FS_USE_XATTR:
if (!inode->i_op->getxattr) { if (!(inode->i_opflags & IOP_XATTR)) {
isec->sid = sbsec->def_sid; isec->sid = sbsec->def_sid;
break; break;
} }
/* Need a dentry, since the xattr API requires one. /* Need a dentry, since the xattr API requires one.
Life would be simpler if we could just pass the inode. */ Life would be simpler if we could just pass the inode. */
if (opt_dentry) { if (opt_dentry) {
@ -1445,14 +1444,12 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
goto out_unlock; goto out_unlock;
} }
context[len] = '\0'; context[len] = '\0';
rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX, rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
context, len);
if (rc == -ERANGE) { if (rc == -ERANGE) {
kfree(context); kfree(context);
/* Need a larger buffer. Query for the right size. */ /* Need a larger buffer. Query for the right size. */
rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX, rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
NULL, 0);
if (rc < 0) { if (rc < 0) {
dput(dentry); dput(dentry);
goto out_unlock; goto out_unlock;
@ -1465,9 +1462,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
goto out_unlock; goto out_unlock;
} }
context[len] = '\0'; context[len] = '\0';
rc = inode->i_op->getxattr(dentry, inode, rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
XATTR_NAME_SELINUX,
context, len);
} }
dput(dentry); dput(dentry);
if (rc < 0) { if (rc < 0) {

View file

@ -265,14 +265,14 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
char *buffer; char *buffer;
struct smack_known *skp = NULL; struct smack_known *skp = NULL;
if (ip->i_op->getxattr == NULL) if (!(ip->i_opflags & IOP_XATTR))
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL); buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
if (buffer == NULL) if (buffer == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
rc = ip->i_op->getxattr(dp, ip, name, buffer, SMK_LONGLABEL); rc = __vfs_getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
if (rc < 0) if (rc < 0)
skp = ERR_PTR(rc); skp = ERR_PTR(rc);
else if (rc == 0) else if (rc == 0)
@ -3520,7 +3520,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
* It would be curious if the label of the task * It would be curious if the label of the task
* does not match that assigned. * does not match that assigned.
*/ */
if (inode->i_op->getxattr == NULL) if (!(inode->i_opflags & IOP_XATTR))
break; break;
/* /*
* Get the dentry for xattr. * Get the dentry for xattr.
@ -3545,12 +3545,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
*/ */
if (isp->smk_flags & SMK_INODE_CHANGED) { if (isp->smk_flags & SMK_INODE_CHANGED) {
isp->smk_flags &= ~SMK_INODE_CHANGED; isp->smk_flags &= ~SMK_INODE_CHANGED;
rc = inode->i_op->setxattr(dp, inode, rc = __vfs_setxattr(dp, inode,
XATTR_NAME_SMACKTRANSMUTE, XATTR_NAME_SMACKTRANSMUTE,
TRANS_TRUE, TRANS_TRUE_SIZE, TRANS_TRUE, TRANS_TRUE_SIZE,
0); 0);
} else { } else {
rc = inode->i_op->getxattr(dp, inode, rc = __vfs_getxattr(dp, inode,
XATTR_NAME_SMACKTRANSMUTE, trattr, XATTR_NAME_SMACKTRANSMUTE, trattr,
TRANS_TRUE_SIZE); TRANS_TRUE_SIZE);
if (rc >= 0 && strncmp(trattr, TRANS_TRUE, if (rc >= 0 && strncmp(trattr, TRANS_TRUE,