mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
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:
parent
5930122683
commit
3767e255b3
20 changed files with 59 additions and 44 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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,
|
||||||
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)
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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,
|
||||||
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 @@
|
||||||
#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 *);
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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);
|
||||||
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)
|
||||||
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)
|
||||||
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);
|
||||||
/* 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,
|
||||||
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)
|
||||||
* 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
|
||||||
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 {
|
||||||
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 *);
|
||||||
|
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue