Commit 3767e255 authored by Al Viro's avatar Al Viro

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 ce23e640.  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: default avatarSeung-Woo Kim <sw0312.kim@samsung.com>
Tested-by: default avatarCasey Schaufler <casey@schaufler-ca.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 59301226
...@@ -578,3 +578,10 @@ in your dentry operations instead. ...@@ -578,3 +578,10 @@ in your dentry operations instead.
-- --
[mandatory] [mandatory]
->atomic_open() calls without O_CREAT may happen in parallel. ->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) ...@@ -976,8 +976,8 @@ static inline __u64 ll_file_maxbytes(struct inode *inode)
} }
/* llite/xattr.c */ /* llite/xattr.c */
int ll_setxattr(struct dentry *dentry, const char *name, int ll_setxattr(struct dentry *dentry, struct inode *inode,
const void *value, size_t size, int flags); const char *name, const void *value, size_t size, int flags);
ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode, ssize_t ll_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *buffer, size_t size); const char *name, void *buffer, size_t size);
ssize_t ll_listxattr(struct dentry *dentry, char *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, ...@@ -211,11 +211,9 @@ int ll_setxattr_common(struct inode *inode, const char *name,
return 0; return 0;
} }
int ll_setxattr(struct dentry *dentry, const char *name, int ll_setxattr(struct dentry *dentry, struct inode *inode,
const void *value, size_t size, int flags) const char *name, const void *value, size_t size, int flags)
{ {
struct inode *inode = d_inode(dentry);
LASSERT(inode); LASSERT(inode);
LASSERT(name); LASSERT(name);
......
...@@ -100,8 +100,8 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -100,8 +100,8 @@ static int bad_inode_setattr(struct dentry *direntry, struct iattr *attrs)
return -EIO; return -EIO;
} }
static int bad_inode_setxattr(struct dentry *dentry, const char *name, static int bad_inode_setxattr(struct dentry *dentry, struct inode *inode,
const void *value, size_t size, int flags) const char *name, const void *value, size_t size, int flags)
{ {
return -EIO; return -EIO;
} }
......
...@@ -1141,12 +1141,13 @@ ecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode, ...@@ -1141,12 +1141,13 @@ ecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode,
static int static int
ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
struct inode *ecryptfs_inode,
char *page_virt, size_t size) char *page_virt, size_t size)
{ {
int rc; int rc;
rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt, rc = ecryptfs_setxattr(ecryptfs_dentry, ecryptfs_inode,
size, 0); ECRYPTFS_XATTR_NAME, page_virt, size, 0);
return rc; return rc;
} }
...@@ -1215,8 +1216,8 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, ...@@ -1215,8 +1216,8 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
goto out_free; goto out_free;
} }
if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt, rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, ecryptfs_inode,
size); virt, size);
else else
rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt, rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt,
virt_len); virt_len);
......
...@@ -609,8 +609,8 @@ ssize_t ...@@ -609,8 +609,8 @@ ssize_t
ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode, ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
const char *name, void *value, size_t size); const char *name, void *value, size_t size);
int int
ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, ecryptfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
size_t size, int flags); const void *value, size_t size, int flags);
int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode); int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode);
#ifdef CONFIG_ECRYPT_FS_MESSAGING #ifdef CONFIG_ECRYPT_FS_MESSAGING
int ecryptfs_process_response(struct ecryptfs_daemon *daemon, int ecryptfs_process_response(struct ecryptfs_daemon *daemon,
......
...@@ -1001,7 +1001,8 @@ static int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry, ...@@ -1001,7 +1001,8 @@ static int ecryptfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
} }
int 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) size_t size, int flags)
{ {
int rc = 0; int rc = 0;
...@@ -1014,8 +1015,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, ...@@ -1014,8 +1015,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
} }
rc = vfs_setxattr(lower_dentry, name, value, size, flags); rc = vfs_setxattr(lower_dentry, name, value, size, flags);
if (!rc && d_really_is_positive(dentry)) if (!rc && inode)
fsstack_copy_attr_all(d_inode(dentry), d_inode(lower_dentry)); fsstack_copy_attr_all(inode, d_inode(lower_dentry));
out: out:
return rc; return rc;
} }
......
...@@ -442,7 +442,8 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode) ...@@ -442,7 +442,8 @@ static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
if (size < 0) if (size < 0)
size = 8; size = 8;
put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt); put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
rc = lower_inode->i_op->setxattr(lower_dentry, ECRYPTFS_XATTR_NAME, rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode,
ECRYPTFS_XATTR_NAME,
xattr_virt, size, 0); xattr_virt, size, 0);
inode_unlock(lower_inode); inode_unlock(lower_inode);
if (rc) if (rc)
......
...@@ -1719,10 +1719,10 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, ...@@ -1719,10 +1719,10 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
return fuse_update_attributes(inode, stat, NULL, NULL); return fuse_update_attributes(inode, stat, NULL, NULL);
} }
static int fuse_setxattr(struct dentry *entry, const char *name, static int fuse_setxattr(struct dentry *unused, struct inode *inode,
const void *value, size_t size, int flags) 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); struct fuse_conn *fc = get_fuse_conn(inode);
FUSE_ARGS(args); FUSE_ARGS(args);
struct fuse_setxattr_in inarg; struct fuse_setxattr_in inarg;
......
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
#include "hfs_fs.h" #include "hfs_fs.h"
#include "btree.h" #include "btree.h"
int hfs_setxattr(struct dentry *dentry, const char *name, int hfs_setxattr(struct dentry *unused, struct inode *inode,
const void *value, size_t size, int flags) const char *name, const void *value,
size_t size, int flags)
{ {
struct inode *inode = d_inode(dentry);
struct hfs_find_data fd; struct hfs_find_data fd;
hfs_cat_rec rec; hfs_cat_rec rec;
struct hfs_cat_file *file; struct hfs_cat_file *file;
......
...@@ -212,7 +212,7 @@ extern void hfs_evict_inode(struct inode *); ...@@ -212,7 +212,7 @@ extern void hfs_evict_inode(struct inode *);
extern void hfs_delete_inode(struct inode *); extern void hfs_delete_inode(struct inode *);
/* attr.c */ /* attr.c */
extern int hfs_setxattr(struct dentry *dentry, const char *name, extern int hfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
const void *value, size_t size, int flags); const void *value, size_t size, int flags);
extern ssize_t hfs_getxattr(struct dentry *dentry, struct inode *inode, extern ssize_t hfs_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size); const char *name, void *value, size_t size);
......
...@@ -160,10 +160,11 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata, ...@@ -160,10 +160,11 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
return 0; return 0;
} }
int kernfs_iop_setxattr(struct dentry *dentry, const char *name, int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode,
const void *value, size_t size, int flags) 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; struct kernfs_iattrs *attrs;
void *secdata; void *secdata;
int error; int error;
...@@ -175,11 +176,11 @@ int kernfs_iop_setxattr(struct dentry *dentry, const char *name, ...@@ -175,11 +176,11 @@ int kernfs_iop_setxattr(struct dentry *dentry, const char *name,
if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) { if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
const char *suffix = name + 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); value, size, flags);
if (error) if (error)
return error; return error;
error = security_inode_getsecctx(d_inode(dentry), error = security_inode_getsecctx(inode,
&secdata, &secdata_len); &secdata, &secdata_len);
if (error) if (error)
return error; return error;
......
...@@ -81,7 +81,8 @@ int kernfs_iop_permission(struct inode *inode, int mask); ...@@ -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_setattr(struct dentry *dentry, struct iattr *iattr);
int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry, int kernfs_iop_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat); struct kstat *stat);
int kernfs_iop_setxattr(struct dentry *dentry, 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); size_t size, int flags);
int kernfs_iop_removexattr(struct dentry *dentry, const char *name); int kernfs_iop_removexattr(struct dentry *dentry, const char *name);
ssize_t kernfs_iop_getxattr(struct dentry *dentry, struct inode *inode, 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) ...@@ -1118,8 +1118,9 @@ static int empty_dir_setattr(struct dentry *dentry, struct iattr *attr)
return -EPERM; return -EPERM;
} }
static int empty_dir_setxattr(struct dentry *dentry, const char *name, static int empty_dir_setxattr(struct dentry *dentry, struct inode *inode,
const void *value, size_t size, int flags) const char *name, const void *value,
size_t size, int flags)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -210,8 +210,9 @@ static bool ovl_is_private_xattr(const char *name) ...@@ -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; return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0;
} }
int ovl_setxattr(struct dentry *dentry, const char *name, int ovl_setxattr(struct dentry *dentry, struct inode *inode,
const void *value, size_t size, int flags) const char *name, const void *value,
size_t size, int flags)
{ {
int err; int err;
struct dentry *upperdentry; struct dentry *upperdentry;
......
...@@ -171,8 +171,9 @@ int ovl_check_d_type_supported(struct path *realpath); ...@@ -171,8 +171,9 @@ int ovl_check_d_type_supported(struct path *realpath);
/* inode.c */ /* inode.c */
int ovl_setattr(struct dentry *dentry, struct iattr *attr); int ovl_setattr(struct dentry *dentry, struct iattr *attr);
int ovl_permission(struct inode *inode, int mask); int ovl_permission(struct inode *inode, int mask);
int ovl_setxattr(struct dentry *dentry, const char *name, int ovl_setxattr(struct dentry *dentry, struct inode *inode,
const void *value, size_t size, int flags); const char *name, const void *value,
size_t size, int flags);
ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
const char *name, void *value, size_t size); const char *name, void *value, size_t size);
ssize_t ovl_listxattr(struct dentry *dentry, char *list, 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, ...@@ -100,7 +100,7 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
if (issec) if (issec)
inode->i_flags &= ~S_NOSEC; inode->i_flags &= ~S_NOSEC;
if (inode->i_op->setxattr) { if (inode->i_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) { if (!error) {
fsnotify_xattr(dentry); fsnotify_xattr(dentry);
security_inode_post_setxattr(dentry, name, value, security_inode_post_setxattr(dentry, name, value,
...@@ -745,7 +745,8 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) ...@@ -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. * Find the handler for the prefix and dispatch its set() operation.
*/ */
int 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; const struct xattr_handler *handler;
...@@ -754,8 +755,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz ...@@ -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); handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
if (IS_ERR(handler)) if (IS_ERR(handler))
return PTR_ERR(handler); return PTR_ERR(handler);
return handler->set(handler, dentry, d_inode(dentry), name, value, return handler->set(handler, dentry, inode, name, value, size, flags);
size, flags);
} }
/* /*
......
...@@ -1730,7 +1730,8 @@ struct inode_operations { ...@@ -1730,7 +1730,8 @@ struct inode_operations {
struct inode *, struct dentry *, unsigned int); struct inode *, struct dentry *, unsigned int);
int (*setattr) (struct dentry *, struct iattr *); int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, 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 *, ssize_t (*getxattr) (struct dentry *, struct inode *,
const char *, void *, size_t); const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t);
......
...@@ -54,7 +54,8 @@ int vfs_removexattr(struct dentry *, const char *); ...@@ -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_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size);
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size); ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
int generic_setxattr(struct dentry *dentry, 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); int generic_removexattr(struct dentry *dentry, const char *name);
ssize_t vfs_getxattr_alloc(struct dentry *dentry, const char *name, ssize_t vfs_getxattr_alloc(struct dentry *dentry, const char *name,
char **xattr_value, size_t size, gfp_t flags); char **xattr_value, size_t size, gfp_t flags);
......
...@@ -3514,7 +3514,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) ...@@ -3514,7 +3514,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
*/ */
if (isp->smk_flags & SMK_INODE_CHANGED) { if (isp->smk_flags & SMK_INODE_CHANGED) {
isp->smk_flags &= ~SMK_INODE_CHANGED; isp->smk_flags &= ~SMK_INODE_CHANGED;
rc = inode->i_op->setxattr(dp, rc = inode->i_op->setxattr(dp, inode,
XATTR_NAME_SMACKTRANSMUTE, XATTR_NAME_SMACKTRANSMUTE,
TRANS_TRUE, TRANS_TRUE_SIZE, TRANS_TRUE, TRANS_TRUE_SIZE,
0); 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment