switch ->setxattr() to passing dentry and inode separately
smack ->d_instantiate() uses ->setxattr(), so to be able to call it before
we'd hashed the new dentry and attached it to inode, we need ->setxattr()
instances getting the inode as an explicit argument rather than obtaining
it from dentry.
Similar change for ->getxattr() had been done in commit ce23e64
. Unlike
->getxattr() (which is used by both selinux and smack instances of
->d_instantiate()) ->setxattr() is used only by smack one and unfortunately
it got missed back then.
Reported-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Tested-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Родитель
5930122683
Коммит
3767e255b3
|
@ -578,3 +578,10 @@ in your dentry operations instead.
|
|||
--
|
||||
[mandatory]
|
||||
->atomic_open() calls without O_CREAT may happen in parallel.
|
||||
--
|
||||
[mandatory]
|
||||
->setxattr() and xattr_handler.set() get dentry and inode passed separately.
|
||||
dentry might be yet to be attached to inode, so do _not_ use its ->d_inode
|
||||
in the instances. Rationale: !@#!@# security_d_instantiate() needs to be
|
||||
called before we attach dentry to inode and !@#!@##!@$!$#!@#$!@$!@$ smack
|
||||
->d_instantiate() uses not just ->getxattr() but ->setxattr() as well.
|
||||
|
|
|
@ -976,8 +976,8 @@ static inline __u64 ll_file_maxbytes(struct inode *inode)
|
|||
}
|
||||
|
||||
/* llite/xattr.c */
|
||||
int ll_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
int ll_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value, size_t size, int flags);
|
||||
ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *buffer, size_t size);
|
||||
ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size);
|
||||
|
|
|
@ -211,11 +211,9 @@ int ll_setxattr_common(struct inode *inode, const char *name,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ll_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
int ll_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value, size_t size, int flags)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
LASSERT(inode);
|
||||
LASSERT(name);
|
||||
|
||||
|
|
|
@ -100,8 +100,8 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static int bad_inode_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
static int bad_inode_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value, size_t size, int flags)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
|
|
@ -1141,12 +1141,13 @@ ecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode,
|
|||
|
||||
static int
|
||||
ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
|
||||
struct inode *ecryptfs_inode,
|
||||
char *page_virt, size_t size)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt,
|
||||
size, 0);
|
||||
rc = ecryptfs_setxattr(ecryptfs_dentry, ecryptfs_inode,
|
||||
ECRYPTFS_XATTR_NAME, page_virt, size, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1215,8 +1216,8 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
|
|||
goto out_free;
|
||||
}
|
||||
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
|
||||
rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt,
|
||||
size);
|
||||
rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, ecryptfs_inode,
|
||||
virt, size);
|
||||
else
|
||||
rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt,
|
||||
virt_len);
|
||||
|
|
|
@ -609,8 +609,8 @@ ssize_t
|
|||
ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
|
||||
const char *name, void *value, size_t size);
|
||||
int
|
||||
ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
ecryptfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode);
|
||||
#ifdef CONFIG_ECRYPT_FS_MESSAGING
|
||||
int ecryptfs_process_response(struct ecryptfs_daemon *daemon,
|
||||
|
|
|
@ -1001,7 +1001,8 @@ static int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
|||
}
|
||||
|
||||
int
|
||||
ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
||||
ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
int rc = 0;
|
||||
|
@ -1014,8 +1015,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
|||
}
|
||||
|
||||
rc = vfs_setxattr(lower_dentry, name, value, size, flags);
|
||||
if (!rc && d_really_is_positive(dentry))
|
||||
fsstack_copy_attr_all(d_inode(dentry), d_inode(lower_dentry));
|
||||
if (!rc && inode)
|
||||
fsstack_copy_attr_all(inode, d_inode(lower_dentry));
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -442,7 +442,8 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
|
|||
if (size < 0)
|
||||
size = 8;
|
||||
put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
|
||||
rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME,
|
||||
rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode,
|
||||
ECRYPTFS_XATTR_NAME,
|
||||
xattr_virt, size, 0);
|
||||
inode_unlock(lower_inode);
|
||||
if (rc)
|
||||
|
|
|
@ -1719,10 +1719,10 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
|
|||
return fuse_update_attributes(inode, stat, NULL, NULL);
|
||||
}
|
||||
|
||||
static int fuse_setxattr(struct dentry *entry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
static int fuse_setxattr(struct dentry *unused, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
struct inode *inode = d_inode(entry);
|
||||
struct fuse_conn *fc = get_fuse_conn(inode);
|
||||
FUSE_ARGS(args);
|
||||
struct fuse_setxattr_in inarg;
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
#include "hfs_fs.h"
|
||||
#include "btree.h"
|
||||
|
||||
int hfs_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
int hfs_setxattr(struct dentry *unused, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct hfs_find_data fd;
|
||||
hfs_cat_rec rec;
|
||||
struct hfs_cat_file *file;
|
||||
|
|
|
@ -212,7 +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, const char *name,
|
||||
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);
|
||||
|
|
|
@ -160,10 +160,11 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int kernfs_iop_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
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 = dentry->d_fsdata;
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
struct kernfs_iattrs *attrs;
|
||||
void *secdata;
|
||||
int error;
|
||||
|
@ -175,11 +176,11 @@ int kernfs_iop_setxattr(struct dentry *dentry, const char *name,
|
|||
|
||||
if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
|
||||
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
|
||||
error = security_inode_setsecurity(d_inode(dentry), suffix,
|
||||
error = security_inode_setsecurity(inode, suffix,
|
||||
value, size, flags);
|
||||
if (error)
|
||||
return error;
|
||||
error = security_inode_getsecctx(d_inode(dentry),
|
||||
error = security_inode_getsecctx(inode,
|
||||
&secdata, &secdata_len);
|
||||
if (error)
|
||||
return error;
|
||||
|
|
|
@ -81,7 +81,8 @@ 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, const char *name, const void *value,
|
||||
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,
|
||||
|
|
|
@ -1118,8 +1118,9 @@ static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr)
|
|||
return -EPERM;
|
||||
}
|
||||
|
||||
static int empty_dir_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
static int empty_dir_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
|
|
@ -210,8 +210,9 @@ static bool ovl_is_private_xattr(const char *name)
|
|||
return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0;
|
||||
}
|
||||
|
||||
int ovl_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
int ovl_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
int err;
|
||||
struct dentry *upperdentry;
|
||||
|
|
|
@ -171,8 +171,9 @@ int ovl_check_d_type_supported(struct path *realpath);
|
|||
/* inode.c */
|
||||
int ovl_setattr(struct dentry *dentry, struct iattr *attr);
|
||||
int ovl_permission(struct inode *inode, int mask);
|
||||
int ovl_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
int ovl_setxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags);
|
||||
ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
|
||||
const char *name, void *value, size_t size);
|
||||
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
|
||||
|
|
|
@ -100,7 +100,7 @@ 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, name, value, size, flags);
|
||||
error = inode->i_op->setxattr(dentry, inode, name, value, size, flags);
|
||||
if (!error) {
|
||||
fsnotify_xattr(dentry);
|
||||
security_inode_post_setxattr(dentry, name, value,
|
||||
|
@ -745,7 +745,8 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
|||
* Find the handler for the prefix and dispatch its set() operation.
|
||||
*/
|
||||
int
|
||||
generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
|
||||
generic_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
|
@ -754,8 +755,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
|
|||
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, value,
|
||||
size, flags);
|
||||
return handler->set(handler, dentry, inode, name, value, size, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1730,7 +1730,8 @@ 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 *, const char *,const void *,size_t,int);
|
||||
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);
|
||||
|
|
|
@ -54,7 +54,8 @@ 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, const char *name, const void *value, size_t size, int flags);
|
||||
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);
|
||||
|
|
|
@ -3514,7 +3514,7 @@ 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,
|
||||
rc = inode->i_op->setxattr(dp, inode,
|
||||
XATTR_NAME_SMACKTRANSMUTE,
|
||||
TRANS_TRUE, TRANS_TRUE_SIZE,
|
||||
0);
|
||||
|
|
Загрузка…
Ссылка в новой задаче