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:
commit
97d2116708
@ -61,10 +61,7 @@ prototypes:
|
||||
int (*get_acl)(struct inode *, int);
|
||||
int (*setattr) (struct dentry *, struct iattr *);
|
||||
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);
|
||||
int (*removexattr) (struct dentry *, const char *);
|
||||
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
|
||||
void (*update_time)(struct inode *, struct timespec *, int);
|
||||
int (*atomic_open)(struct inode *, struct dentry *,
|
||||
@ -91,15 +88,13 @@ setattr: yes
|
||||
permission: no (may not block if called in rcu-walk mode)
|
||||
get_acl: no
|
||||
getattr: no
|
||||
setxattr: yes
|
||||
getxattr: no
|
||||
listxattr: no
|
||||
removexattr: yes
|
||||
fiemap: no
|
||||
update_time: no
|
||||
atomic_open: yes
|
||||
tmpfile: no
|
||||
|
||||
|
||||
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
|
||||
victim.
|
||||
cross-directory ->rename() and rename2() has (per-superblock)
|
||||
@ -108,6 +103,23 @@ victim.
|
||||
See Documentation/filesystems/directory-locking for more detailed discussion
|
||||
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 ---------------------------
|
||||
prototypes:
|
||||
struct inode *(*alloc_inode)(struct super_block *sb);
|
||||
|
@ -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
|
||||
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
|
||||
================
|
||||
@ -356,10 +385,7 @@ struct inode_operations {
|
||||
int (*get_acl)(struct inode *, int);
|
||||
int (*setattr) (struct dentry *, struct iattr *);
|
||||
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);
|
||||
int (*removexattr) (struct dentry *, const char *);
|
||||
void (*update_time)(struct inode *, struct timespec *, int);
|
||||
int (*atomic_open)(struct inode *, struct dentry *, struct file *,
|
||||
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
|
||||
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
|
||||
given file. This method is called by 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.
|
||||
given file. This method is called by the listxattr(2) system call.
|
||||
|
||||
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
|
||||
|
@ -3268,10 +3268,7 @@ const struct inode_operations ll_file_inode_operations = {
|
||||
.setattr = ll_setattr,
|
||||
.getattr = ll_getattr,
|
||||
.permission = ll_inode_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ll_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = ll_fiemap,
|
||||
.get_acl = ll_get_acl,
|
||||
};
|
||||
|
@ -1152,10 +1152,7 @@ const struct inode_operations ll_dir_inode_operations = {
|
||||
.setattr = ll_setattr,
|
||||
.getattr = ll_getattr,
|
||||
.permission = ll_inode_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ll_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ll_get_acl,
|
||||
};
|
||||
|
||||
@ -1163,9 +1160,6 @@ const struct inode_operations ll_special_inode_operations = {
|
||||
.setattr = ll_setattr,
|
||||
.getattr = ll_getattr,
|
||||
.permission = ll_inode_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ll_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ll_get_acl,
|
||||
};
|
||||
|
@ -154,8 +154,5 @@ const struct inode_operations ll_fast_symlink_inode_operations = {
|
||||
.get_link = ll_get_link,
|
||||
.getattr = ll_getattr,
|
||||
.permission = ll_inode_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ll_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
@ -967,9 +967,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
|
||||
.rename = v9fs_vfs_rename,
|
||||
.getattr = v9fs_vfs_getattr_dotl,
|
||||
.setattr = v9fs_vfs_setattr_dotl,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = v9fs_listxattr,
|
||||
.get_acl = v9fs_iop_get_acl,
|
||||
};
|
||||
@ -977,9 +974,6 @@ const struct inode_operations v9fs_dir_inode_operations_dotl = {
|
||||
const struct inode_operations v9fs_file_inode_operations_dotl = {
|
||||
.getattr = v9fs_vfs_getattr_dotl,
|
||||
.setattr = v9fs_vfs_setattr_dotl,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = v9fs_listxattr,
|
||||
.get_acl = v9fs_iop_get_acl,
|
||||
};
|
||||
@ -989,8 +983,5 @@ const struct inode_operations v9fs_symlink_inode_operations_dotl = {
|
||||
.get_link = v9fs_vfs_get_link_dotl,
|
||||
.getattr = v9fs_vfs_getattr_dotl,
|
||||
.setattr = v9fs_vfs_setattr_dotl,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = v9fs_listxattr,
|
||||
};
|
||||
|
@ -100,29 +100,12 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int bad_inode_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value, size_t size, int flags)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static ssize_t bad_inode_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *buffer, size_t size)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
|
||||
size_t buffer_size)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int bad_inode_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static const struct inode_operations bad_inode_ops =
|
||||
{
|
||||
.create = bad_inode_create,
|
||||
@ -142,10 +125,7 @@ static const struct inode_operations bad_inode_ops =
|
||||
.permission = bad_inode_permission,
|
||||
.getattr = bad_inode_getattr,
|
||||
.setattr = bad_inode_setattr,
|
||||
.setxattr = bad_inode_setxattr,
|
||||
.getxattr = bad_inode_getxattr,
|
||||
.listxattr = bad_inode_listxattr,
|
||||
.removexattr = bad_inode_removexattr,
|
||||
};
|
||||
|
||||
|
||||
@ -175,6 +155,7 @@ void make_bad_inode(struct inode *inode)
|
||||
inode->i_atime = inode->i_mtime = inode->i_ctime =
|
||||
current_fs_time(inode->i_sb);
|
||||
inode->i_op = &bad_inode_ops;
|
||||
inode->i_opflags &= ~IOP_XATTR;
|
||||
inode->i_fop = &bad_file_ops;
|
||||
}
|
||||
EXPORT_SYMBOL(make_bad_inode);
|
||||
|
@ -10556,10 +10556,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
|
||||
.symlink = btrfs_symlink,
|
||||
.setattr = btrfs_setattr,
|
||||
.mknod = btrfs_mknod,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = btrfs_permission,
|
||||
.get_acl = btrfs_get_acl,
|
||||
.set_acl = btrfs_set_acl,
|
||||
@ -10633,10 +10630,7 @@ static const struct address_space_operations btrfs_symlink_aops = {
|
||||
static const struct inode_operations btrfs_file_inode_operations = {
|
||||
.getattr = btrfs_getattr,
|
||||
.setattr = btrfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = btrfs_permission,
|
||||
.fiemap = btrfs_fiemap,
|
||||
.get_acl = btrfs_get_acl,
|
||||
@ -10647,10 +10641,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
|
||||
.getattr = btrfs_getattr,
|
||||
.setattr = btrfs_setattr,
|
||||
.permission = btrfs_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = btrfs_get_acl,
|
||||
.set_acl = btrfs_set_acl,
|
||||
.update_time = btrfs_update_time,
|
||||
@ -10661,10 +10652,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
|
||||
.getattr = btrfs_getattr,
|
||||
.setattr = btrfs_setattr,
|
||||
.permission = btrfs_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.update_time = btrfs_update_time,
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/mount.h>
|
||||
#include <linux/statfs.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/xattr.h>
|
||||
#include "internal.h"
|
||||
|
||||
static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches);
|
||||
@ -126,8 +127,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
|
||||
if (d_is_negative(root) ||
|
||||
!d_backing_inode(root)->i_op->lookup ||
|
||||
!d_backing_inode(root)->i_op->mkdir ||
|
||||
!d_backing_inode(root)->i_op->setxattr ||
|
||||
!d_backing_inode(root)->i_op->getxattr ||
|
||||
!(d_backing_inode(root)->i_opflags & IOP_XATTR) ||
|
||||
!root->d_sb->s_op->statfs ||
|
||||
!root->d_sb->s_op->sync_fs)
|
||||
goto error_unsupported;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/namei.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/xattr.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define CACHEFILES_KEYBUF_SIZE 512
|
||||
@ -799,8 +800,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
||||
}
|
||||
|
||||
ret = -EPERM;
|
||||
if (!d_backing_inode(subdir)->i_op->setxattr ||
|
||||
!d_backing_inode(subdir)->i_op->getxattr ||
|
||||
if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
|
||||
!d_backing_inode(subdir)->i_op->lookup ||
|
||||
!d_backing_inode(subdir)->i_op->mkdir ||
|
||||
!d_backing_inode(subdir)->i_op->create ||
|
||||
|
@ -1486,10 +1486,7 @@ const struct inode_operations ceph_dir_iops = {
|
||||
.permission = ceph_permission,
|
||||
.getattr = ceph_getattr,
|
||||
.setattr = ceph_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ceph_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ceph_get_acl,
|
||||
.set_acl = ceph_set_acl,
|
||||
.mknod = ceph_mknod,
|
||||
|
@ -94,10 +94,7 @@ const struct inode_operations ceph_file_iops = {
|
||||
.permission = ceph_permission,
|
||||
.setattr = ceph_setattr,
|
||||
.getattr = ceph_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ceph_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ceph_get_acl,
|
||||
.set_acl = ceph_set_acl,
|
||||
};
|
||||
@ -1885,10 +1882,7 @@ static const struct inode_operations ceph_symlink_iops = {
|
||||
.get_link = simple_get_link,
|
||||
.setattr = ceph_setattr,
|
||||
.getattr = ceph_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ceph_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
int __ceph_setattr(struct inode *inode, struct iattr *attr)
|
||||
|
@ -901,30 +901,21 @@ const struct inode_operations cifs_dir_inode_ops = {
|
||||
.setattr = cifs_setattr,
|
||||
.symlink = cifs_symlink,
|
||||
.mknod = cifs_mknod,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = cifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations cifs_file_inode_ops = {
|
||||
.setattr = cifs_setattr,
|
||||
.getattr = cifs_getattr,
|
||||
.permission = cifs_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = cifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations cifs_symlink_inode_ops = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = cifs_get_link,
|
||||
.permission = cifs_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = cifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
static int cifs_clone_file_range(struct file *src_file, loff_t off,
|
||||
|
@ -715,4 +715,6 @@ int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
|
||||
int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
|
||||
loff_t offset);
|
||||
|
||||
extern const struct xattr_handler *ecryptfs_xattr_handlers[];
|
||||
|
||||
#endif /* #ifndef ECRYPTFS_KERNEL_H */
|
||||
|
@ -1005,15 +1005,14 @@ ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc;
|
||||
struct dentry *lower_dentry;
|
||||
|
||||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
if (!d_inode(lower_dentry)->i_op->setxattr) {
|
||||
if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = vfs_setxattr(lower_dentry, name, value, size, flags);
|
||||
if (!rc && inode)
|
||||
fsstack_copy_attr_all(inode, d_inode(lower_dentry));
|
||||
@ -1025,15 +1024,14 @@ ssize_t
|
||||
ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
|
||||
const char *name, void *value, size_t size)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc;
|
||||
|
||||
if (!lower_inode->i_op->getxattr) {
|
||||
if (!(lower_inode->i_opflags & IOP_XATTR)) {
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
inode_lock(lower_inode);
|
||||
rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
|
||||
name, value, size);
|
||||
rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
|
||||
inode_unlock(lower_inode);
|
||||
out:
|
||||
return rc;
|
||||
@ -1066,19 +1064,22 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ecryptfs_removexattr(struct dentry *dentry, const char *name)
|
||||
static int ecryptfs_removexattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name)
|
||||
{
|
||||
int rc = 0;
|
||||
int rc;
|
||||
struct dentry *lower_dentry;
|
||||
struct inode *lower_inode;
|
||||
|
||||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
if (!d_inode(lower_dentry)->i_op->removexattr) {
|
||||
lower_inode = ecryptfs_inode_to_lower(inode);
|
||||
if (!(lower_inode->i_opflags & IOP_XATTR)) {
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
inode_lock(d_inode(lower_dentry));
|
||||
rc = d_inode(lower_dentry)->i_op->removexattr(lower_dentry, name);
|
||||
inode_unlock(d_inode(lower_dentry));
|
||||
inode_lock(lower_inode);
|
||||
rc = __vfs_removexattr(lower_dentry, name);
|
||||
inode_unlock(lower_inode);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
@ -1089,10 +1090,7 @@ const struct inode_operations ecryptfs_symlink_iops = {
|
||||
.permission = ecryptfs_permission,
|
||||
.setattr = ecryptfs_setattr,
|
||||
.getattr = ecryptfs_getattr_link,
|
||||
.setxattr = ecryptfs_setxattr,
|
||||
.getxattr = ecryptfs_getxattr,
|
||||
.listxattr = ecryptfs_listxattr,
|
||||
.removexattr = ecryptfs_removexattr
|
||||
};
|
||||
|
||||
const struct inode_operations ecryptfs_dir_iops = {
|
||||
@ -1107,18 +1105,43 @@ const struct inode_operations ecryptfs_dir_iops = {
|
||||
.rename = ecryptfs_rename,
|
||||
.permission = ecryptfs_permission,
|
||||
.setattr = ecryptfs_setattr,
|
||||
.setxattr = ecryptfs_setxattr,
|
||||
.getxattr = ecryptfs_getxattr,
|
||||
.listxattr = ecryptfs_listxattr,
|
||||
.removexattr = ecryptfs_removexattr
|
||||
};
|
||||
|
||||
const struct inode_operations ecryptfs_main_iops = {
|
||||
.permission = ecryptfs_permission,
|
||||
.setattr = ecryptfs_setattr,
|
||||
.getattr = ecryptfs_getattr,
|
||||
.setxattr = ecryptfs_setxattr,
|
||||
.getxattr = ecryptfs_getxattr,
|
||||
.listxattr = ecryptfs_listxattr,
|
||||
.removexattr = ecryptfs_removexattr
|
||||
};
|
||||
|
||||
static int ecryptfs_xattr_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *buffer, size_t size)
|
||||
{
|
||||
return ecryptfs_getxattr(dentry, inode, name, buffer, size);
|
||||
}
|
||||
|
||||
static int ecryptfs_xattr_set(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value, size_t size,
|
||||
int flags)
|
||||
{
|
||||
if (value)
|
||||
return ecryptfs_setxattr(dentry, inode, name, value, size, flags);
|
||||
else {
|
||||
BUG_ON(flags != XATTR_REPLACE);
|
||||
return ecryptfs_removexattr(dentry, inode, name);
|
||||
}
|
||||
}
|
||||
|
||||
const struct xattr_handler ecryptfs_xattr_handler = {
|
||||
.prefix = "", /* match anything */
|
||||
.get = ecryptfs_xattr_get,
|
||||
.set = ecryptfs_xattr_set,
|
||||
};
|
||||
|
||||
const struct xattr_handler *ecryptfs_xattr_handlers[] = {
|
||||
&ecryptfs_xattr_handler,
|
||||
NULL
|
||||
};
|
||||
|
@ -529,6 +529,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
||||
/* ->kill_sb() will take care of sbi after that point */
|
||||
sbi = NULL;
|
||||
s->s_op = &ecryptfs_sops;
|
||||
s->s_xattr = ecryptfs_xattr_handlers;
|
||||
s->s_d_op = &ecryptfs_dops;
|
||||
|
||||
err = "Reading sb failed";
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/file.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
@ -422,7 +423,7 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
|
||||
struct inode *lower_inode = d_inode(lower_dentry);
|
||||
int rc;
|
||||
|
||||
if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
|
||||
if (!(lower_inode->i_opflags & IOP_XATTR)) {
|
||||
printk(KERN_WARNING
|
||||
"No support for setting xattr in lower filesystem\n");
|
||||
rc = -ENOSYS;
|
||||
@ -436,14 +437,12 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
|
||||
goto out;
|
||||
}
|
||||
inode_lock(lower_inode);
|
||||
size = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
|
||||
ECRYPTFS_XATTR_NAME,
|
||||
size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
|
||||
xattr_virt, PAGE_SIZE);
|
||||
if (size < 0)
|
||||
size = 8;
|
||||
put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
|
||||
rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode,
|
||||
ECRYPTFS_XATTR_NAME,
|
||||
rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
|
||||
xattr_virt, size, 0);
|
||||
inode_unlock(lower_inode);
|
||||
if (rc)
|
||||
|
@ -241,10 +241,7 @@ const struct file_operations ext2_file_operations = {
|
||||
|
||||
const struct inode_operations ext2_file_inode_operations = {
|
||||
#ifdef CONFIG_EXT2_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
.setattr = ext2_setattr,
|
||||
.get_acl = ext2_get_acl,
|
||||
|
@ -428,10 +428,7 @@ const struct inode_operations ext2_dir_inode_operations = {
|
||||
.mknod = ext2_mknod,
|
||||
.rename = ext2_rename,
|
||||
#ifdef CONFIG_EXT2_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
.setattr = ext2_setattr,
|
||||
.get_acl = ext2_get_acl,
|
||||
@ -441,10 +438,7 @@ const struct inode_operations ext2_dir_inode_operations = {
|
||||
|
||||
const struct inode_operations ext2_special_inode_operations = {
|
||||
#ifdef CONFIG_EXT2_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
.setattr = ext2_setattr,
|
||||
.get_acl = ext2_get_acl,
|
||||
|
@ -25,10 +25,7 @@ const struct inode_operations ext2_symlink_inode_operations = {
|
||||
.get_link = page_get_link,
|
||||
.setattr = ext2_setattr,
|
||||
#ifdef CONFIG_EXT2_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -37,9 +34,6 @@ const struct inode_operations ext2_fast_symlink_inode_operations = {
|
||||
.get_link = simple_get_link,
|
||||
.setattr = ext2_setattr,
|
||||
#ifdef CONFIG_EXT2_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
@ -706,10 +706,7 @@ const struct file_operations ext4_file_operations = {
|
||||
const struct inode_operations ext4_file_inode_operations = {
|
||||
.setattr = ext4_setattr,
|
||||
.getattr = ext4_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ext4_get_acl,
|
||||
.set_acl = ext4_set_acl,
|
||||
.fiemap = ext4_fiemap,
|
||||
|
@ -3880,10 +3880,7 @@ const struct inode_operations ext4_dir_inode_operations = {
|
||||
.tmpfile = ext4_tmpfile,
|
||||
.rename2 = ext4_rename2,
|
||||
.setattr = ext4_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ext4_get_acl,
|
||||
.set_acl = ext4_set_acl,
|
||||
.fiemap = ext4_fiemap,
|
||||
@ -3891,10 +3888,7 @@ const struct inode_operations ext4_dir_inode_operations = {
|
||||
|
||||
const struct inode_operations ext4_special_inode_operations = {
|
||||
.setattr = ext4_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ext4_get_acl,
|
||||
.set_acl = ext4_set_acl,
|
||||
};
|
||||
|
@ -86,28 +86,19 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = ext4_encrypted_get_link,
|
||||
.setattr = ext4_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations ext4_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = page_get_link,
|
||||
.setattr = ext4_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations ext4_fast_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = simple_get_link,
|
||||
.setattr = ext4_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ext4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
@ -732,10 +732,7 @@ const struct inode_operations f2fs_file_inode_operations = {
|
||||
.get_acl = f2fs_get_acl,
|
||||
.set_acl = f2fs_set_acl,
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
.fiemap = f2fs_fiemap,
|
||||
};
|
||||
|
@ -1080,10 +1080,7 @@ const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
|
||||
.getattr = f2fs_getattr,
|
||||
.setattr = f2fs_setattr,
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -1103,10 +1100,7 @@ const struct inode_operations f2fs_dir_inode_operations = {
|
||||
.get_acl = f2fs_get_acl,
|
||||
.set_acl = f2fs_set_acl,
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -1116,10 +1110,7 @@ const struct inode_operations f2fs_symlink_inode_operations = {
|
||||
.getattr = f2fs_getattr,
|
||||
.setattr = f2fs_setattr,
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -1129,9 +1120,6 @@ const struct inode_operations f2fs_special_inode_operations = {
|
||||
.get_acl = f2fs_get_acl,
|
||||
.set_acl = f2fs_set_acl,
|
||||
#ifdef CONFIG_F2FS_FS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = f2fs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
@ -1801,10 +1801,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
|
||||
.mknod = fuse_mknod,
|
||||
.permission = fuse_permission,
|
||||
.getattr = fuse_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = fuse_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = fuse_get_acl,
|
||||
.set_acl = fuse_set_acl,
|
||||
};
|
||||
@ -1824,10 +1821,7 @@ static const struct inode_operations fuse_common_inode_operations = {
|
||||
.setattr = fuse_setattr,
|
||||
.permission = fuse_permission,
|
||||
.getattr = fuse_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = fuse_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = fuse_get_acl,
|
||||
.set_acl = fuse_set_acl,
|
||||
};
|
||||
@ -1837,10 +1831,7 @@ static const struct inode_operations fuse_symlink_inode_operations = {
|
||||
.get_link = fuse_get_link,
|
||||
.readlink = generic_readlink,
|
||||
.getattr = fuse_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = fuse_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
void fuse_init_common(struct inode *inode)
|
||||
|
@ -2040,10 +2040,7 @@ const struct inode_operations gfs2_file_iops = {
|
||||
.permission = gfs2_permission,
|
||||
.setattr = gfs2_setattr,
|
||||
.getattr = gfs2_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = gfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = gfs2_fiemap,
|
||||
.get_acl = gfs2_get_acl,
|
||||
.set_acl = gfs2_set_acl,
|
||||
@ -2062,10 +2059,7 @@ const struct inode_operations gfs2_dir_iops = {
|
||||
.permission = gfs2_permission,
|
||||
.setattr = gfs2_setattr,
|
||||
.getattr = gfs2_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = gfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = gfs2_fiemap,
|
||||
.get_acl = gfs2_get_acl,
|
||||
.set_acl = gfs2_set_acl,
|
||||
@ -2078,10 +2072,7 @@ const struct inode_operations gfs2_symlink_iops = {
|
||||
.permission = gfs2_permission,
|
||||
.setattr = gfs2_setattr,
|
||||
.getattr = gfs2_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = gfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = gfs2_fiemap,
|
||||
};
|
||||
|
||||
|
@ -13,9 +13,13 @@
|
||||
#include "hfs_fs.h"
|
||||
#include "btree.h"
|
||||
|
||||
int hfs_setxattr(struct dentry *unused, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
enum hfs_xattr_type {
|
||||
HFS_TYPE,
|
||||
HFS_CREATOR,
|
||||
};
|
||||
|
||||
static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
struct hfs_find_data fd;
|
||||
hfs_cat_rec rec;
|
||||
@ -36,18 +40,22 @@ int hfs_setxattr(struct dentry *unused, struct inode *inode,
|
||||
sizeof(struct hfs_cat_file));
|
||||
file = &rec.file;
|
||||
|
||||
if (!strcmp(name, "hfs.type")) {
|
||||
switch (type) {
|
||||
case HFS_TYPE:
|
||||
if (size == 4)
|
||||
memcpy(&file->UsrWds.fdType, value, 4);
|
||||
else
|
||||
res = -ERANGE;
|
||||
} else if (!strcmp(name, "hfs.creator")) {
|
||||
break;
|
||||
|
||||
case HFS_CREATOR:
|
||||
if (size == 4)
|
||||
memcpy(&file->UsrWds.fdCreator, value, 4);
|
||||
else
|
||||
res = -ERANGE;
|
||||
} else
|
||||
res = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!res)
|
||||
hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
|
||||
sizeof(struct hfs_cat_file));
|
||||
@ -56,8 +64,8 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode,
|
||||
const char *name, void *value, size_t size)
|
||||
static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
|
||||
void *value, size_t size)
|
||||
{
|
||||
struct hfs_find_data fd;
|
||||
hfs_cat_rec rec;
|
||||
@ -80,41 +88,64 @@ ssize_t hfs_getxattr(struct dentry *unused, struct inode *inode,
|
||||
}
|
||||
file = &rec.file;
|
||||
|
||||
if (!strcmp(name, "hfs.type")) {
|
||||
switch (type) {
|
||||
case HFS_TYPE:
|
||||
if (size >= 4) {
|
||||
memcpy(value, &file->UsrWds.fdType, 4);
|
||||
res = 4;
|
||||
} else
|
||||
res = size ? -ERANGE : 4;
|
||||
} else if (!strcmp(name, "hfs.creator")) {
|
||||
break;
|
||||
|
||||
case HFS_CREATOR:
|
||||
if (size >= 4) {
|
||||
memcpy(value, &file->UsrWds.fdCreator, 4);
|
||||
res = 4;
|
||||
} else
|
||||
res = size ? -ERANGE : 4;
|
||||
} else
|
||||
res = -ENODATA;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
if (size)
|
||||
hfs_find_exit(&fd);
|
||||
return res;
|
||||
}
|
||||
|
||||
#define HFS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
|
||||
|
||||
ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
static int hfs_xattr_get(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *name, void *value, size_t size)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
return __hfs_getxattr(inode, handler->flags, value, size);
|
||||
}
|
||||
|
||||
if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
|
||||
static int hfs_xattr_set(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *name, const void *value, size_t size,
|
||||
int flags)
|
||||
{
|
||||
if (!value)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!buffer || !size)
|
||||
return HFS_ATTRLIST_SIZE;
|
||||
if (size < HFS_ATTRLIST_SIZE)
|
||||
return -ERANGE;
|
||||
strcpy(buffer, "hfs.type");
|
||||
strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
|
||||
|
||||
return HFS_ATTRLIST_SIZE;
|
||||
return __hfs_setxattr(inode, handler->flags, value, size, flags);
|
||||
}
|
||||
|
||||
static const struct xattr_handler hfs_creator_handler = {
|
||||
.name = "hfs.creator",
|
||||
.flags = HFS_CREATOR,
|
||||
.get = hfs_xattr_get,
|
||||
.set = hfs_xattr_set,
|
||||
};
|
||||
|
||||
static const struct xattr_handler hfs_type_handler = {
|
||||
.name = "hfs.type",
|
||||
.flags = HFS_TYPE,
|
||||
.get = hfs_xattr_get,
|
||||
.set = hfs_xattr_set,
|
||||
};
|
||||
|
||||
const struct xattr_handler *hfs_xattr_handlers[] = {
|
||||
&hfs_creator_handler,
|
||||
&hfs_type_handler,
|
||||
NULL
|
||||
};
|
||||
|
@ -212,11 +212,7 @@ extern void hfs_evict_inode(struct inode *);
|
||||
extern void hfs_delete_inode(struct inode *);
|
||||
|
||||
/* attr.c */
|
||||
extern int hfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
extern ssize_t hfs_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *value, size_t size);
|
||||
extern ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
|
||||
extern const struct xattr_handler *hfs_xattr_handlers[];
|
||||
|
||||
/* mdb.c */
|
||||
extern int hfs_mdb_get(struct super_block *);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/xattr.h>
|
||||
|
||||
#include "hfs_fs.h"
|
||||
#include "btree.h"
|
||||
@ -687,7 +688,5 @@ static const struct file_operations hfs_file_operations = {
|
||||
static const struct inode_operations hfs_file_inode_operations = {
|
||||
.lookup = hfs_file_lookup,
|
||||
.setattr = hfs_inode_setattr,
|
||||
.setxattr = hfs_setxattr,
|
||||
.getxattr = hfs_getxattr,
|
||||
.listxattr = hfs_listxattr,
|
||||
.listxattr = generic_listxattr,
|
||||
};
|
||||
|
@ -406,6 +406,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
}
|
||||
|
||||
sb->s_op = &hfs_super_operations;
|
||||
sb->s_xattr = hfs_xattr_handlers;
|
||||
sb->s_flags |= MS_NODIRATIME;
|
||||
mutex_init(&sbi->bitmap_lock);
|
||||
|
||||
|
@ -562,10 +562,7 @@ const struct inode_operations hfsplus_dir_inode_operations = {
|
||||
.symlink = hfsplus_symlink,
|
||||
.mknod = hfsplus_mknod,
|
||||
.rename = hfsplus_rename,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = hfsplus_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
|
||||
.get_acl = hfsplus_get_posix_acl,
|
||||
.set_acl = hfsplus_set_posix_acl,
|
||||
|
@ -333,10 +333,7 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
|
||||
|
||||
static const struct inode_operations hfsplus_file_inode_operations = {
|
||||
.setattr = hfsplus_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = hfsplus_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
|
||||
.get_acl = hfsplus_get_posix_acl,
|
||||
.set_acl = hfsplus_set_posix_acl,
|
||||
|
@ -140,6 +140,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
|
||||
inode->i_fop = &no_open_fops;
|
||||
inode->__i_nlink = 1;
|
||||
inode->i_opflags = 0;
|
||||
if (sb->s_xattr)
|
||||
inode->i_opflags |= IOP_XATTR;
|
||||
i_uid_write(inode, 0);
|
||||
i_gid_write(inode, 0);
|
||||
atomic_set(&inode->i_writecount, 0);
|
||||
|
@ -61,10 +61,7 @@ const struct inode_operations jffs2_dir_inode_operations =
|
||||
.get_acl = jffs2_get_acl,
|
||||
.set_acl = jffs2_set_acl,
|
||||
.setattr = jffs2_setattr,
|
||||
.setxattr = jffs2_setxattr,
|
||||
.getxattr = jffs2_getxattr,
|
||||
.listxattr = jffs2_listxattr,
|
||||
.removexattr = jffs2_removexattr
|
||||
};
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -66,10 +66,7 @@ const struct inode_operations jffs2_file_inode_operations =
|
||||
.get_acl = jffs2_get_acl,
|
||||
.set_acl = jffs2_set_acl,
|
||||
.setattr = jffs2_setattr,
|
||||
.setxattr = jffs2_setxattr,
|
||||
.getxattr = jffs2_getxattr,
|
||||
.listxattr = jffs2_listxattr,
|
||||
.removexattr = jffs2_removexattr
|
||||
};
|
||||
|
||||
const struct address_space_operations jffs2_file_address_operations =
|
||||
|
@ -16,8 +16,5 @@ const struct inode_operations jffs2_symlink_inode_operations =
|
||||
.readlink = generic_readlink,
|
||||
.get_link = simple_get_link,
|
||||
.setattr = jffs2_setattr,
|
||||
.setxattr = jffs2_setxattr,
|
||||
.getxattr = jffs2_getxattr,
|
||||
.listxattr = jffs2_listxattr,
|
||||
.removexattr = jffs2_removexattr
|
||||
};
|
||||
|
@ -99,9 +99,6 @@ extern const struct xattr_handler jffs2_user_xattr_handler;
|
||||
extern const struct xattr_handler jffs2_trusted_xattr_handler;
|
||||
|
||||
extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
|
||||
#define jffs2_getxattr generic_getxattr
|
||||
#define jffs2_setxattr generic_setxattr
|
||||
#define jffs2_removexattr generic_removexattr
|
||||
|
||||
#else
|
||||
|
||||
@ -116,9 +113,6 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
|
||||
|
||||
#define jffs2_xattr_handlers NULL
|
||||
#define jffs2_listxattr NULL
|
||||
#define jffs2_getxattr NULL
|
||||
#define jffs2_setxattr NULL
|
||||
#define jffs2_removexattr NULL
|
||||
|
||||
#endif /* CONFIG_JFFS2_FS_XATTR */
|
||||
|
||||
|
@ -140,10 +140,7 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||
}
|
||||
|
||||
const struct inode_operations jfs_file_inode_operations = {
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = jfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.setattr = jfs_setattr,
|
||||
#ifdef CONFIG_JFS_POSIX_ACL
|
||||
.get_acl = jfs_get_acl,
|
||||
|
@ -1537,10 +1537,7 @@ const struct inode_operations jfs_dir_inode_operations = {
|
||||
.rmdir = jfs_rmdir,
|
||||
.mknod = jfs_mknod,
|
||||
.rename = jfs_rename,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = jfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.setattr = jfs_setattr,
|
||||
#ifdef CONFIG_JFS_POSIX_ACL
|
||||
.get_acl = jfs_get_acl,
|
||||
|
@ -25,19 +25,13 @@ const struct inode_operations jfs_fast_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = simple_get_link,
|
||||
.setattr = jfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = jfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct inode_operations jfs_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = page_get_link,
|
||||
.setattr = jfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = jfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
|
@ -1126,9 +1126,6 @@ const struct inode_operations kernfs_dir_iops = {
|
||||
.permission = kernfs_iop_permission,
|
||||
.setattr = kernfs_iop_setattr,
|
||||
.getattr = kernfs_iop_getattr,
|
||||
.setxattr = kernfs_iop_setxattr,
|
||||
.removexattr = kernfs_iop_removexattr,
|
||||
.getxattr = kernfs_iop_getxattr,
|
||||
.listxattr = kernfs_iop_listxattr,
|
||||
|
||||
.mkdir = kernfs_iop_mkdir,
|
||||
|
@ -28,9 +28,6 @@ static const struct inode_operations kernfs_iops = {
|
||||
.permission = kernfs_iop_permission,
|
||||
.setattr = kernfs_iop_setattr,
|
||||
.getattr = kernfs_iop_getattr,
|
||||
.setxattr = kernfs_iop_setxattr,
|
||||
.removexattr = kernfs_iop_removexattr,
|
||||
.getxattr = kernfs_iop_getxattr,
|
||||
.listxattr = kernfs_iop_listxattr,
|
||||
};
|
||||
|
||||
@ -138,17 +135,12 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
|
||||
static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
|
||||
u32 *secdata_len)
|
||||
{
|
||||
struct kernfs_iattrs *attrs;
|
||||
void *old_secdata;
|
||||
size_t old_secdata_len;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
old_secdata = attrs->ia_secdata;
|
||||
old_secdata_len = attrs->ia_secdata_len;
|
||||
|
||||
@ -160,71 +152,6 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
void *secdata;
|
||||
int error;
|
||||
u32 secdata_len = 0;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
|
||||
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
|
||||
error = security_inode_setsecurity(inode, suffix,
|
||||
value, size, flags);
|
||||
if (error)
|
||||
return error;
|
||||
error = security_inode_getsecctx(inode,
|
||||
&secdata, &secdata_len);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
mutex_lock(&kernfs_mutex);
|
||||
error = kernfs_node_setsecdata(kn, &secdata, &secdata_len);
|
||||
mutex_unlock(&kernfs_mutex);
|
||||
|
||||
if (secdata)
|
||||
security_release_secctx(secdata, secdata_len);
|
||||
return error;
|
||||
} else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
|
||||
return simple_xattr_set(&attrs->xattrs, name, value, size,
|
||||
flags);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
struct kernfs_node *kn = dentry->d_fsdata;
|
||||
struct kernfs_iattrs *attrs;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);
|
||||
}
|
||||
|
||||
ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode,
|
||||
const char *name, void *buf, size_t size)
|
||||
{
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_get(&attrs->xattrs, name, buf, size);
|
||||
}
|
||||
|
||||
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
|
||||
{
|
||||
struct kernfs_node *kn = dentry->d_fsdata;
|
||||
@ -376,3 +303,83 @@ int kernfs_iop_permission(struct inode *inode, int mask)
|
||||
|
||||
return generic_permission(inode, mask);
|
||||
}
|
||||
|
||||
static int kernfs_xattr_get(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *suffix, void *value, size_t size)
|
||||
{
|
||||
const char *name = xattr_full_name(handler, suffix);
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_get(&attrs->xattrs, name, value, size);
|
||||
}
|
||||
|
||||
static int kernfs_xattr_set(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *suffix, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
const char *name = xattr_full_name(handler, suffix);
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_set(&attrs->xattrs, name, value, size, flags);
|
||||
}
|
||||
|
||||
const struct xattr_handler kernfs_trusted_xattr_handler = {
|
||||
.prefix = XATTR_TRUSTED_PREFIX,
|
||||
.get = kernfs_xattr_get,
|
||||
.set = kernfs_xattr_set,
|
||||
};
|
||||
|
||||
static int kernfs_security_xattr_set(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *suffix, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
void *secdata;
|
||||
u32 secdata_len = 0;
|
||||
int error;
|
||||
|
||||
attrs = kernfs_iattrs(kn);
|
||||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
error = security_inode_setsecurity(inode, suffix, value, size, flags);
|
||||
if (error)
|
||||
return error;
|
||||
error = security_inode_getsecctx(inode, &secdata, &secdata_len);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
mutex_lock(&kernfs_mutex);
|
||||
error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
|
||||
mutex_unlock(&kernfs_mutex);
|
||||
|
||||
if (secdata)
|
||||
security_release_secctx(secdata, secdata_len);
|
||||
return error;
|
||||
}
|
||||
|
||||
const struct xattr_handler kernfs_security_xattr_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.get = kernfs_xattr_get,
|
||||
.set = kernfs_security_xattr_set,
|
||||
};
|
||||
|
||||
const struct xattr_handler *kernfs_xattr_handlers[] = {
|
||||
&kernfs_trusted_xattr_handler,
|
||||
&kernfs_security_xattr_handler,
|
||||
NULL
|
||||
};
|
||||
|
@ -76,17 +76,12 @@ extern struct kmem_cache *kernfs_node_cache;
|
||||
/*
|
||||
* inode.c
|
||||
*/
|
||||
extern const struct xattr_handler *kernfs_xattr_handlers[];
|
||||
void kernfs_evict_inode(struct inode *inode);
|
||||
int kernfs_iop_permission(struct inode *inode, int mask);
|
||||
int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);
|
||||
int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
||||
struct kstat *stat);
|
||||
int kernfs_iop_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
int kernfs_iop_removexattr(struct dentry *dentry, const char *name);
|
||||
ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *buf, size_t size);
|
||||
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size);
|
||||
|
||||
/*
|
||||
|
@ -158,6 +158,7 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
|
||||
sb->s_blocksize_bits = PAGE_SHIFT;
|
||||
sb->s_magic = magic;
|
||||
sb->s_op = &kernfs_sops;
|
||||
sb->s_xattr = kernfs_xattr_handlers;
|
||||
sb->s_time_gran = 1;
|
||||
|
||||
/* get root inode, initialize and unlock it */
|
||||
|
@ -134,9 +134,6 @@ static const char *kernfs_iop_get_link(struct dentry *dentry,
|
||||
}
|
||||
|
||||
const struct inode_operations kernfs_symlink_iops = {
|
||||
.setxattr = kernfs_iop_setxattr,
|
||||
.removexattr = kernfs_iop_removexattr,
|
||||
.getxattr = kernfs_iop_getxattr,
|
||||
.listxattr = kernfs_iop_listxattr,
|
||||
.readlink = generic_readlink,
|
||||
.get_link = kernfs_iop_get_link,
|
||||
|
29
fs/libfs.c
29
fs/libfs.c
@ -236,8 +236,8 @@ static const struct super_operations simple_super_operations = {
|
||||
* Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
|
||||
* will never be mountable)
|
||||
*/
|
||||
struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
|
||||
const struct super_operations *ops,
|
||||
struct dentry *mount_pseudo_xattr(struct file_system_type *fs_type, char *name,
|
||||
const struct super_operations *ops, const struct xattr_handler **xattr,
|
||||
const struct dentry_operations *dops, unsigned long magic)
|
||||
{
|
||||
struct super_block *s;
|
||||
@ -254,6 +254,7 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
|
||||
s->s_blocksize_bits = PAGE_SHIFT;
|
||||
s->s_magic = magic;
|
||||
s->s_op = ops ? ops : &simple_super_operations;
|
||||
s->s_xattr = xattr;
|
||||
s->s_time_gran = 1;
|
||||
root = new_inode(s);
|
||||
if (!root)
|
||||
@ -281,7 +282,7 @@ Enomem:
|
||||
deactivate_locked_super(s);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
EXPORT_SYMBOL(mount_pseudo);
|
||||
EXPORT_SYMBOL(mount_pseudo_xattr);
|
||||
|
||||
int simple_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
@ -1149,24 +1150,6 @@ static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr)
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static int empty_dir_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static ssize_t empty_dir_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *value, size_t size)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int empty_dir_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
@ -1177,9 +1160,6 @@ static const struct inode_operations empty_dir_inode_operations = {
|
||||
.permission = generic_permission,
|
||||
.setattr = empty_dir_setattr,
|
||||
.getattr = empty_dir_getattr,
|
||||
.setxattr = empty_dir_setxattr,
|
||||
.getxattr = empty_dir_getxattr,
|
||||
.removexattr = empty_dir_removexattr,
|
||||
.listxattr = empty_dir_listxattr,
|
||||
};
|
||||
|
||||
@ -1215,6 +1195,7 @@ void make_empty_dir_inode(struct inode *inode)
|
||||
inode->i_blocks = 0;
|
||||
|
||||
inode->i_op = &empty_dir_inode_operations;
|
||||
inode->i_opflags &= ~IOP_XATTR;
|
||||
inode->i_fop = &empty_dir_operations;
|
||||
}
|
||||
|
||||
|
@ -899,9 +899,6 @@ static const struct inode_operations nfs3_dir_inode_operations = {
|
||||
.setattr = nfs_setattr,
|
||||
#ifdef CONFIG_NFS_V3_ACL
|
||||
.listxattr = nfs3_listxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = nfs3_get_acl,
|
||||
.set_acl = nfs3_set_acl,
|
||||
#endif
|
||||
@ -913,9 +910,6 @@ static const struct inode_operations nfs3_file_inode_operations = {
|
||||
.setattr = nfs_setattr,
|
||||
#ifdef CONFIG_NFS_V3_ACL
|
||||
.listxattr = nfs3_listxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = nfs3_get_acl,
|
||||
.set_acl = nfs3_set_acl,
|
||||
#endif
|
||||
|
@ -8941,20 +8941,14 @@ static const struct inode_operations nfs4_dir_inode_operations = {
|
||||
.permission = nfs_permission,
|
||||
.getattr = nfs_getattr,
|
||||
.setattr = nfs_setattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.listxattr = nfs4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
static const struct inode_operations nfs4_file_inode_operations = {
|
||||
.permission = nfs_permission,
|
||||
.getattr = nfs_getattr,
|
||||
.setattr = nfs_setattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.listxattr = nfs4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
const struct nfs_rpc_ops nfs_v4_clientops = {
|
||||
|
@ -2444,10 +2444,7 @@ const struct inode_operations ocfs2_file_iops = {
|
||||
.setattr = ocfs2_setattr,
|
||||
.getattr = ocfs2_getattr,
|
||||
.permission = ocfs2_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ocfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = ocfs2_fiemap,
|
||||
.get_acl = ocfs2_iop_get_acl,
|
||||
.set_acl = ocfs2_iop_set_acl,
|
||||
|
@ -2913,10 +2913,7 @@ const struct inode_operations ocfs2_dir_iops = {
|
||||
.setattr = ocfs2_setattr,
|
||||
.getattr = ocfs2_getattr,
|
||||
.permission = ocfs2_permission,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ocfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = ocfs2_fiemap,
|
||||
.get_acl = ocfs2_iop_get_acl,
|
||||
.set_acl = ocfs2_iop_set_acl,
|
||||
|
@ -91,9 +91,6 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
|
||||
.get_link = page_get_link,
|
||||
.getattr = ocfs2_getattr,
|
||||
.setattr = ocfs2_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ocfs2_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.fiemap = ocfs2_fiemap,
|
||||
};
|
||||
|
@ -296,10 +296,7 @@ const struct inode_operations orangefs_file_inode_operations = {
|
||||
.set_acl = orangefs_set_acl,
|
||||
.setattr = orangefs_setattr,
|
||||
.getattr = orangefs_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = orangefs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = orangefs_permission,
|
||||
};
|
||||
|
||||
|
@ -462,9 +462,6 @@ const struct inode_operations orangefs_dir_inode_operations = {
|
||||
.rename = orangefs_rename,
|
||||
.setattr = orangefs_setattr,
|
||||
.getattr = orangefs_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = orangefs_listxattr,
|
||||
.permission = orangefs_permission,
|
||||
};
|
||||
|
@ -14,6 +14,5 @@ const struct inode_operations orangefs_symlink_inode_operations = {
|
||||
.setattr = orangefs_setattr,
|
||||
.getattr = orangefs_getattr,
|
||||
.listxattr = orangefs_listxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.permission = orangefs_permission,
|
||||
};
|
||||
|
@ -73,6 +73,9 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
|
||||
"%s: name %s, buffer_size %zd\n",
|
||||
__func__, name, size);
|
||||
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (strlen(name) >= ORANGEFS_MAX_XATTR_NAMELEN) {
|
||||
gossip_err("Invalid key length (%d)\n",
|
||||
(int)strlen(name));
|
||||
|
@ -58,8 +58,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
|
||||
char *buf, *name, *value = NULL;
|
||||
int uninitialized_var(error);
|
||||
|
||||
if (!old->d_inode->i_op->getxattr ||
|
||||
!new->d_inode->i_op->getxattr)
|
||||
if (!(old->d_inode->i_opflags & IOP_XATTR) ||
|
||||
!(new->d_inode->i_opflags & IOP_XATTR))
|
||||
return 0;
|
||||
|
||||
list_size = vfs_listxattr(old, NULL, 0);
|
||||
|
@ -1013,10 +1013,7 @@ const struct inode_operations ovl_dir_inode_operations = {
|
||||
.mknod = ovl_mknod,
|
||||
.permission = ovl_permission,
|
||||
.getattr = ovl_dir_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ovl_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ovl_get_acl,
|
||||
.update_time = ovl_update_time,
|
||||
};
|
||||
|
@ -367,10 +367,7 @@ static const struct inode_operations ovl_file_inode_operations = {
|
||||
.setattr = ovl_setattr,
|
||||
.permission = ovl_permission,
|
||||
.getattr = ovl_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ovl_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.get_acl = ovl_get_acl,
|
||||
.update_time = ovl_update_time,
|
||||
};
|
||||
@ -380,10 +377,7 @@ static const struct inode_operations ovl_symlink_inode_operations = {
|
||||
.get_link = ovl_get_link,
|
||||
.readlink = ovl_readlink,
|
||||
.getattr = ovl_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ovl_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.update_time = ovl_update_time,
|
||||
};
|
||||
|
||||
|
@ -275,10 +275,10 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
|
||||
char val;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
|
||||
if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr)
|
||||
if (!S_ISDIR(inode->i_mode) || !(inode->i_opflags & IOP_XATTR))
|
||||
return false;
|
||||
|
||||
res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
|
||||
res = __vfs_getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
|
||||
if (res == 1 && val == 'y')
|
||||
return true;
|
||||
|
||||
|
@ -260,10 +260,7 @@ const struct file_operations reiserfs_file_operations = {
|
||||
|
||||
const struct inode_operations reiserfs_file_inode_operations = {
|
||||
.setattr = reiserfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = reiserfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = reiserfs_permission,
|
||||
.get_acl = reiserfs_get_acl,
|
||||
.set_acl = reiserfs_set_acl,
|
||||
|
@ -1650,10 +1650,7 @@ const struct inode_operations reiserfs_dir_inode_operations = {
|
||||
.mknod = reiserfs_mknod,
|
||||
.rename = reiserfs_rename,
|
||||
.setattr = reiserfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = reiserfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = reiserfs_permission,
|
||||
.get_acl = reiserfs_get_acl,
|
||||
.set_acl = reiserfs_set_acl,
|
||||
@ -1667,10 +1664,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = page_get_link,
|
||||
.setattr = reiserfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = reiserfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = reiserfs_permission,
|
||||
};
|
||||
|
||||
@ -1679,10 +1673,7 @@ const struct inode_operations reiserfs_symlink_inode_operations = {
|
||||
*/
|
||||
const struct inode_operations reiserfs_special_inode_operations = {
|
||||
.setattr = reiserfs_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = reiserfs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.permission = reiserfs_permission,
|
||||
.get_acl = reiserfs_get_acl,
|
||||
.set_acl = reiserfs_set_acl,
|
||||
|
@ -425,7 +425,6 @@ failed_read:
|
||||
|
||||
|
||||
const struct inode_operations squashfs_inode_ops = {
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = squashfs_listxattr
|
||||
};
|
||||
|
||||
|
@ -247,6 +247,5 @@ failed:
|
||||
|
||||
const struct inode_operations squashfs_dir_inode_ops = {
|
||||
.lookup = squashfs_lookup,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = squashfs_listxattr
|
||||
};
|
||||
|
@ -120,7 +120,6 @@ const struct address_space_operations squashfs_symlink_aops = {
|
||||
const struct inode_operations squashfs_symlink_inode_ops = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = page_get_link,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = squashfs_listxattr
|
||||
};
|
||||
|
||||
|
@ -42,6 +42,5 @@ static inline int squashfs_xattr_lookup(struct super_block *sb,
|
||||
return 0;
|
||||
}
|
||||
#define squashfs_listxattr NULL
|
||||
#define generic_getxattr NULL
|
||||
#define squashfs_xattr_handlers NULL
|
||||
#endif
|
||||
|
@ -1182,10 +1182,7 @@ const struct inode_operations ubifs_dir_inode_operations = {
|
||||
.rename = ubifs_rename,
|
||||
.setattr = ubifs_setattr,
|
||||
.getattr = ubifs_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
||||
.update_time = ubifs_update_time,
|
||||
#endif
|
||||
|
@ -1621,10 +1621,7 @@ const struct address_space_operations ubifs_file_address_operations = {
|
||||
const struct inode_operations ubifs_file_inode_operations = {
|
||||
.setattr = ubifs_setattr,
|
||||
.getattr = ubifs_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
||||
.update_time = ubifs_update_time,
|
||||
#endif
|
||||
@ -1635,10 +1632,7 @@ const struct inode_operations ubifs_symlink_inode_operations = {
|
||||
.get_link = simple_get_link,
|
||||
.setattr = ubifs_setattr,
|
||||
.getattr = ubifs_getattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = ubifs_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
|
||||
.update_time = ubifs_update_time,
|
||||
#endif
|
||||
|
248
fs/xattr.c
248
fs/xattr.c
@ -24,6 +24,59 @@
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
static const char *
|
||||
strcmp_prefix(const char *a, const char *a_prefix)
|
||||
{
|
||||
while (*a_prefix && *a == *a_prefix) {
|
||||
a++;
|
||||
a_prefix++;
|
||||
}
|
||||
return *a_prefix ? NULL : a;
|
||||
}
|
||||
|
||||
/*
|
||||
* In order to implement different sets of xattr operations for each xattr
|
||||
* prefix, a filesystem should create a null-terminated array of struct
|
||||
* xattr_handler (one for each prefix) and hang a pointer to it off of the
|
||||
* s_xattr field of the superblock.
|
||||
*/
|
||||
#define for_each_xattr_handler(handlers, handler) \
|
||||
if (handlers) \
|
||||
for ((handler) = *(handlers)++; \
|
||||
(handler) != NULL; \
|
||||
(handler) = *(handlers)++)
|
||||
|
||||
/*
|
||||
* Find the xattr_handler with the matching prefix.
|
||||
*/
|
||||
static const struct xattr_handler *
|
||||
xattr_resolve_name(struct inode *inode, const char **name)
|
||||
{
|
||||
const struct xattr_handler **handlers = inode->i_sb->s_xattr;
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
if (!(inode->i_opflags & IOP_XATTR)) {
|
||||
if (unlikely(is_bad_inode(inode)))
|
||||
return ERR_PTR(-EIO);
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
const char *n;
|
||||
|
||||
n = strcmp_prefix(*name, xattr_prefix(handler));
|
||||
if (n) {
|
||||
if (!handler->prefix ^ !*n) {
|
||||
if (*n)
|
||||
continue;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
*name = n;
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check permissions for extended attribute access. This is a bit complicated
|
||||
* because different namespaces have very different rules.
|
||||
@ -80,6 +133,23 @@ xattr_permission(struct inode *inode, const char *name, int mask)
|
||||
return inode_permission(inode, mask);
|
||||
}
|
||||
|
||||
int
|
||||
__vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(inode, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
if (!handler->set)
|
||||
return -EOPNOTSUPP;
|
||||
if (size == 0)
|
||||
value = ""; /* empty EA, do not remove */
|
||||
return handler->set(handler, dentry, inode, name, value, size, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(__vfs_setxattr);
|
||||
|
||||
/**
|
||||
* __vfs_setxattr_noperm - perform setxattr operation without performing
|
||||
* permission checks.
|
||||
@ -106,8 +176,8 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
|
||||
|
||||
if (issec)
|
||||
inode->i_flags &= ~S_NOSEC;
|
||||
if (inode->i_op->setxattr) {
|
||||
error = inode->i_op->setxattr(dentry, inode, name, value, size, flags);
|
||||
if (inode->i_opflags & IOP_XATTR) {
|
||||
error = __vfs_setxattr(dentry, inode, name, value, size, flags);
|
||||
if (!error) {
|
||||
fsnotify_xattr(dentry);
|
||||
security_inode_post_setxattr(dentry, name, value,
|
||||
@ -115,6 +185,9 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
|
||||
}
|
||||
} else if (issec) {
|
||||
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
|
||||
|
||||
if (unlikely(is_bad_inode(inode)))
|
||||
return -EIO;
|
||||
error = security_inode_setsecurity(inode, suffix, value,
|
||||
size, flags);
|
||||
if (!error)
|
||||
@ -188,6 +261,7 @@ ssize_t
|
||||
vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
|
||||
size_t xattr_size, gfp_t flags)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
char *value = *xattr_value;
|
||||
int error;
|
||||
@ -196,10 +270,12 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!inode->i_op->getxattr)
|
||||
handler = xattr_resolve_name(inode, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
if (!handler->get)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
error = inode->i_op->getxattr(dentry, inode, name, NULL, 0);
|
||||
error = handler->get(handler, dentry, inode, name, NULL, 0);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
@ -210,11 +286,26 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
|
||||
memset(value, 0, error + 1);
|
||||
}
|
||||
|
||||
error = inode->i_op->getxattr(dentry, inode, name, value, error);
|
||||
error = handler->get(handler, dentry, inode, name, value, error);
|
||||
*xattr_value = value;
|
||||
return error;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
void *value, size_t size)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(inode, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
if (!handler->get)
|
||||
return -EOPNOTSUPP;
|
||||
return handler->get(handler, dentry, inode, name, value, size);
|
||||
}
|
||||
EXPORT_SYMBOL(__vfs_getxattr);
|
||||
|
||||
ssize_t
|
||||
vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
|
||||
{
|
||||
@ -242,28 +333,24 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
|
||||
return ret;
|
||||
}
|
||||
nolsm:
|
||||
if (inode->i_op->getxattr)
|
||||
error = inode->i_op->getxattr(dentry, inode, name, value, size);
|
||||
else
|
||||
error = -EOPNOTSUPP;
|
||||
|
||||
return error;
|
||||
return __vfs_getxattr(dentry, inode, name, value, size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfs_getxattr);
|
||||
|
||||
ssize_t
|
||||
vfs_listxattr(struct dentry *d, char *list, size_t size)
|
||||
vfs_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
ssize_t error;
|
||||
|
||||
error = security_inode_listxattr(d);
|
||||
error = security_inode_listxattr(dentry);
|
||||
if (error)
|
||||
return error;
|
||||
if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
|
||||
error = -EOPNOTSUPP;
|
||||
if (d->d_inode->i_op->listxattr) {
|
||||
error = d->d_inode->i_op->listxattr(d, list, size);
|
||||
error = inode->i_op->listxattr(dentry, list, size);
|
||||
} else {
|
||||
error = security_inode_listsecurity(d->d_inode, list, size);
|
||||
error = security_inode_listsecurity(inode, list, size);
|
||||
if (size && error > size)
|
||||
error = -ERANGE;
|
||||
}
|
||||
@ -271,15 +358,27 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfs_listxattr);
|
||||
|
||||
int
|
||||
__vfs_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(inode, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
if (!handler->set)
|
||||
return -EOPNOTSUPP;
|
||||
return handler->set(handler, dentry, inode, name, NULL, 0, XATTR_REPLACE);
|
||||
}
|
||||
EXPORT_SYMBOL(__vfs_removexattr);
|
||||
|
||||
int
|
||||
vfs_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
|
||||
if (!inode->i_op->removexattr)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
error = xattr_permission(inode, name, MAY_WRITE);
|
||||
if (error)
|
||||
return error;
|
||||
@ -289,7 +388,7 @@ vfs_removexattr(struct dentry *dentry, const char *name)
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = inode->i_op->removexattr(dentry, name);
|
||||
error = __vfs_removexattr(dentry, name);
|
||||
|
||||
if (!error) {
|
||||
fsnotify_xattr(dentry);
|
||||
@ -641,76 +740,6 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
strcmp_prefix(const char *a, const char *a_prefix)
|
||||
{
|
||||
while (*a_prefix && *a == *a_prefix) {
|
||||
a++;
|
||||
a_prefix++;
|
||||
}
|
||||
return *a_prefix ? NULL : a;
|
||||
}
|
||||
|
||||
/*
|
||||
* In order to implement different sets of xattr operations for each xattr
|
||||
* prefix with the generic xattr API, a filesystem should create a
|
||||
* null-terminated array of struct xattr_handler (one for each prefix) and
|
||||
* hang a pointer to it off of the s_xattr field of the superblock.
|
||||
*
|
||||
* The generic_fooxattr() functions will use this list to dispatch xattr
|
||||
* operations to the correct xattr_handler.
|
||||
*/
|
||||
#define for_each_xattr_handler(handlers, handler) \
|
||||
if (handlers) \
|
||||
for ((handler) = *(handlers)++; \
|
||||
(handler) != NULL; \
|
||||
(handler) = *(handlers)++)
|
||||
|
||||
/*
|
||||
* Find the xattr_handler with the matching prefix.
|
||||
*/
|
||||
static const struct xattr_handler *
|
||||
xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
if (!*name)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
const char *n;
|
||||
|
||||
n = strcmp_prefix(*name, xattr_prefix(handler));
|
||||
if (n) {
|
||||
if (!handler->prefix ^ !*n) {
|
||||
if (*n)
|
||||
continue;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
*name = n;
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the handler for the prefix and dispatch its get() operation.
|
||||
*/
|
||||
ssize_t
|
||||
generic_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *buffer, size_t size)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
return handler->get(handler, dentry, inode,
|
||||
name, buffer, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Combine the results of the list() operation from every xattr_handler in the
|
||||
* list.
|
||||
@ -747,44 +776,7 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the handler for the prefix and dispatch its set() operation.
|
||||
*/
|
||||
int
|
||||
generic_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
if (size == 0)
|
||||
value = ""; /* empty EA, do not remove */
|
||||
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
return handler->set(handler, dentry, inode, name, value, size, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the handler for the prefix and dispatch its set() operation to remove
|
||||
* any associated extended attribute.
|
||||
*/
|
||||
int
|
||||
generic_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
return handler->set(handler, dentry, d_inode(dentry), name, NULL,
|
||||
0, XATTR_REPLACE);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(generic_getxattr);
|
||||
EXPORT_SYMBOL(generic_listxattr);
|
||||
EXPORT_SYMBOL(generic_setxattr);
|
||||
EXPORT_SYMBOL(generic_removexattr);
|
||||
|
||||
/**
|
||||
* xattr_full_name - Compute full attribute name from suffix
|
||||
|
@ -1066,9 +1066,6 @@ static const struct inode_operations xfs_inode_operations = {
|
||||
.set_acl = xfs_set_acl,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.fiemap = xfs_vn_fiemap,
|
||||
.update_time = xfs_vn_update_time,
|
||||
@ -1094,9 +1091,6 @@ static const struct inode_operations xfs_dir_inode_operations = {
|
||||
.set_acl = xfs_set_acl,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
.tmpfile = xfs_vn_tmpfile,
|
||||
@ -1122,9 +1116,6 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
|
||||
.set_acl = xfs_set_acl,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
.tmpfile = xfs_vn_tmpfile,
|
||||
@ -1135,9 +1126,6 @@ static const struct inode_operations xfs_symlink_inode_operations = {
|
||||
.get_link = xfs_vn_get_link,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
};
|
||||
@ -1147,9 +1135,6 @@ static const struct inode_operations xfs_inline_symlink_inode_operations = {
|
||||
.get_link = xfs_vn_get_link_inline,
|
||||
.getattr = xfs_vn_getattr,
|
||||
.setattr = xfs_vn_setattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = xfs_vn_listxattr,
|
||||
.update_time = xfs_vn_update_time,
|
||||
};
|
||||
|
@ -592,6 +592,7 @@ is_uncached_acl(struct posix_acl *acl)
|
||||
#define IOP_FASTPERM 0x0001
|
||||
#define IOP_LOOKUP 0x0002
|
||||
#define IOP_NOFOLLOW 0x0004
|
||||
#define IOP_XATTR 0x0008
|
||||
|
||||
/*
|
||||
* Keep mostly read-only and often accessed (especially for
|
||||
@ -1751,12 +1752,7 @@ struct inode_operations {
|
||||
struct inode *, struct dentry *, unsigned int);
|
||||
int (*setattr) (struct dentry *, struct iattr *);
|
||||
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);
|
||||
int (*removexattr) (struct dentry *, const char *);
|
||||
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
|
||||
u64 len);
|
||||
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 (*set)(struct super_block *,void *),
|
||||
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 xattr_handler **xattr,
|
||||
const struct dentry_operations *dops,
|
||||
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 */
|
||||
#define fops_get(fops) \
|
||||
(((fops) && try_module_get((fops)->owner) ? (fops) : NULL))
|
||||
|
@ -46,17 +46,16 @@ struct xattr {
|
||||
};
|
||||
|
||||
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_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(struct dentry *, const char *, const void *, size_t, int);
|
||||
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);
|
||||
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,
|
||||
char **xattr_value, size_t size, gfp_t flags);
|
||||
|
||||
|
15
mm/shmem.c
15
mm/shmem.c
@ -3175,10 +3175,7 @@ static const struct inode_operations shmem_short_symlink_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = simple_get_link,
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -3186,10 +3183,7 @@ static const struct inode_operations shmem_symlink_inode_operations = {
|
||||
.readlink = generic_readlink,
|
||||
.get_link = shmem_get_link,
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -3683,10 +3677,7 @@ static const struct inode_operations shmem_inode_operations = {
|
||||
.getattr = shmem_getattr,
|
||||
.setattr = shmem_setattr,
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.set_acl = simple_set_acl,
|
||||
#endif
|
||||
};
|
||||
@ -3705,10 +3696,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
|
||||
.tmpfile = shmem_tmpfile,
|
||||
#endif
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
#ifdef CONFIG_TMPFS_POSIX_ACL
|
||||
.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 = {
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
#ifdef CONFIG_TMPFS_POSIX_ACL
|
||||
.setattr = shmem_setattr,
|
||||
|
59
net/socket.c
59
net/socket.c
@ -320,10 +320,37 @@ static const struct dentry_operations sockfs_dentry_operations = {
|
||||
.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,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -463,35 +490,6 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
|
||||
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,
|
||||
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 = {
|
||||
.getxattr = sockfs_getxattr,
|
||||
.listxattr = sockfs_listxattr,
|
||||
};
|
||||
|
||||
|
@ -310,13 +310,8 @@ int cap_inode_need_killpriv(struct dentry *dentry)
|
||||
struct inode *inode = d_backing_inode(dentry);
|
||||
int error;
|
||||
|
||||
if (!inode->i_op->getxattr)
|
||||
return 0;
|
||||
|
||||
error = inode->i_op->getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
|
||||
if (error <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
|
||||
return error > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -329,12 +324,12 @@ int cap_inode_need_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)
|
||||
return 0;
|
||||
|
||||
return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
|
||||
error = __vfs_removexattr(dentry, XATTR_NAME_CAPS);
|
||||
if (error == -EOPNOTSUPP)
|
||||
error = 0;
|
||||
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));
|
||||
|
||||
if (!inode || !inode->i_op->getxattr)
|
||||
if (!inode)
|
||||
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);
|
||||
if (size == -ENODATA || size == -EOPNOTSUPP)
|
||||
/* no data, that's ok */
|
||||
|
@ -182,8 +182,9 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
|
||||
int error;
|
||||
int size;
|
||||
|
||||
if (!inode->i_op->getxattr)
|
||||
if (!(inode->i_opflags & IOP_XATTR))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
desc = init_desc(type);
|
||||
if (IS_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,
|
||||
&xattr_data,
|
||||
sizeof(xattr_data), 0);
|
||||
} else if (rc == -ENODATA && inode->i_op->removexattr) {
|
||||
rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
|
||||
} else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) {
|
||||
rc = __vfs_removexattr(dentry, XATTR_NAME_EVM);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -78,11 +78,11 @@ static int evm_find_protected_xattrs(struct dentry *dentry)
|
||||
int error;
|
||||
int count = 0;
|
||||
|
||||
if (!inode->i_op->getxattr)
|
||||
if (!(inode->i_opflags & IOP_XATTR))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
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 == -ENODATA)
|
||||
continue;
|
||||
|
@ -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,
|
||||
struct evm_ima_xattr_data **xattr_value)
|
||||
{
|
||||
struct inode *inode = d_backing_inode(dentry);
|
||||
ssize_t ret;
|
||||
|
||||
if (!inode->i_op->getxattr)
|
||||
return 0;
|
||||
|
||||
return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
|
||||
ret = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
|
||||
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;
|
||||
int rc = xattr_len, hash_start = 0;
|
||||
|
||||
if (!inode->i_op->getxattr)
|
||||
if (!(inode->i_opflags & IOP_XATTR))
|
||||
return INTEGRITY_UNKNOWN;
|
||||
|
||||
if (rc <= 0) {
|
||||
@ -322,10 +322,10 @@ void ima_inode_post_setattr(struct dentry *dentry)
|
||||
{
|
||||
struct inode *inode = d_backing_inode(dentry);
|
||||
struct integrity_iint_cache *iint;
|
||||
int must_appraise, rc;
|
||||
int must_appraise;
|
||||
|
||||
if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
|
||||
|| !inode->i_op->removexattr)
|
||||
|| !(inode->i_opflags & IOP_XATTR))
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
if (!must_appraise)
|
||||
rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA);
|
||||
return;
|
||||
__vfs_removexattr(dentry, XATTR_NAME_IMA);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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 first boot of the SELinux kernel before we have
|
||||
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 "
|
||||
"xattr support\n", sb->s_id, sb->s_type->name);
|
||||
rc = -EOPNOTSUPP;
|
||||
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 == -EOPNOTSUPP)
|
||||
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:
|
||||
break;
|
||||
case SECURITY_FS_USE_XATTR:
|
||||
if (!inode->i_op->getxattr) {
|
||||
if (!(inode->i_opflags & IOP_XATTR)) {
|
||||
isec->sid = sbsec->def_sid;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Need a dentry, since the xattr API requires one.
|
||||
Life would be simpler if we could just pass the inode. */
|
||||
if (opt_dentry) {
|
||||
@ -1445,14 +1444,12 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
|
||||
goto out_unlock;
|
||||
}
|
||||
context[len] = '\0';
|
||||
rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
|
||||
context, len);
|
||||
rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
|
||||
if (rc == -ERANGE) {
|
||||
kfree(context);
|
||||
|
||||
/* Need a larger buffer. Query for the right size. */
|
||||
rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
|
||||
NULL, 0);
|
||||
rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
|
||||
if (rc < 0) {
|
||||
dput(dentry);
|
||||
goto out_unlock;
|
||||
@ -1465,9 +1462,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
|
||||
goto out_unlock;
|
||||
}
|
||||
context[len] = '\0';
|
||||
rc = inode->i_op->getxattr(dentry, inode,
|
||||
XATTR_NAME_SELINUX,
|
||||
context, len);
|
||||
rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
|
||||
}
|
||||
dput(dentry);
|
||||
if (rc < 0) {
|
||||
|
@ -265,14 +265,14 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
|
||||
char *buffer;
|
||||
struct smack_known *skp = NULL;
|
||||
|
||||
if (ip->i_op->getxattr == NULL)
|
||||
if (!(ip->i_opflags & IOP_XATTR))
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
|
||||
if (buffer == NULL)
|
||||
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)
|
||||
skp = ERR_PTR(rc);
|
||||
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
|
||||
* does not match that assigned.
|
||||
*/
|
||||
if (inode->i_op->getxattr == NULL)
|
||||
if (!(inode->i_opflags & IOP_XATTR))
|
||||
break;
|
||||
/*
|
||||
* 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) {
|
||||
isp->smk_flags &= ~SMK_INODE_CHANGED;
|
||||
rc = inode->i_op->setxattr(dp, inode,
|
||||
rc = __vfs_setxattr(dp, inode,
|
||||
XATTR_NAME_SMACKTRANSMUTE,
|
||||
TRANS_TRUE, TRANS_TRUE_SIZE,
|
||||
0);
|
||||
} else {
|
||||
rc = inode->i_op->getxattr(dp, inode,
|
||||
rc = __vfs_getxattr(dp, inode,
|
||||
XATTR_NAME_SMACKTRANSMUTE, trattr,
|
||||
TRANS_TRUE_SIZE);
|
||||
if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
|
||||
|
Loading…
Reference in New Issue
Block a user