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:
Al Viro 2016-05-27 11:06:05 -04:00
parent 5930122683
commit 3767e255b3
20 changed files with 59 additions and 44 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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;
}

View File

@ -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)

View File

@ -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;

View File

@ -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;

View 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);

View File

@ -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;

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}
/*

View File

@ -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);

View File

@ -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);

View File

@ -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);