Merge branch 'work.audit' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull RCU-safe common_lsm_audit() from Al Viro: "Make common_lsm_audit() non-blocking and usable from RCU pathwalk context. We don't really need to grab/drop dentry in there - rcu_read_lock() is enough. There's a couple of followups using that to simplify the logics in selinux, but those hadn't soaked in -next yet, so they'll have to go in next window" * 'work.audit' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: make dump_common_audit_data() safe to be called from RCU pathwalk new helper: d_find_alias_rcu()
This commit is contained in:
commit
250a25e7a1
25
fs/dcache.c
25
fs/dcache.c
@ -1043,6 +1043,31 @@ struct dentry *d_find_alias(struct inode *inode)
|
||||
}
|
||||
EXPORT_SYMBOL(d_find_alias);
|
||||
|
||||
/*
|
||||
* Caller MUST be holding rcu_read_lock() and be guaranteed
|
||||
* that inode won't get freed until rcu_read_unlock().
|
||||
*/
|
||||
struct dentry *d_find_alias_rcu(struct inode *inode)
|
||||
{
|
||||
struct hlist_head *l = &inode->i_dentry;
|
||||
struct dentry *de = NULL;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
// ->i_dentry and ->i_rcu are colocated, but the latter won't be
|
||||
// used without having I_FREEING set, which means no aliases left
|
||||
if (likely(!(inode->i_state & I_FREEING) && !hlist_empty(l))) {
|
||||
if (S_ISDIR(inode->i_mode)) {
|
||||
de = hlist_entry(l->first, struct dentry, d_u.d_alias);
|
||||
} else {
|
||||
hlist_for_each_entry(de, l, d_u.d_alias)
|
||||
if (!d_unhashed(de))
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
return de;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to kill dentries associated with this inode.
|
||||
* WARNING: you must own a reference to inode.
|
||||
|
@ -262,6 +262,8 @@ extern void d_tmpfile(struct dentry *, struct inode *);
|
||||
extern struct dentry *d_find_alias(struct inode *);
|
||||
extern void d_prune_aliases(struct inode *);
|
||||
|
||||
extern struct dentry *d_find_alias_rcu(struct inode *);
|
||||
|
||||
/* test whether we have any submounts in a subdir tree */
|
||||
extern int path_has_submounts(const struct path *);
|
||||
|
||||
|
@ -291,18 +291,19 @@ static void dump_common_audit_data(struct audit_buffer *ab,
|
||||
struct dentry *dentry;
|
||||
struct inode *inode;
|
||||
|
||||
rcu_read_lock();
|
||||
inode = a->u.inode;
|
||||
dentry = d_find_alias(inode);
|
||||
dentry = d_find_alias_rcu(inode);
|
||||
if (dentry) {
|
||||
audit_log_format(ab, " name=");
|
||||
spin_lock(&dentry->d_lock);
|
||||
audit_log_untrustedstring(ab, dentry->d_name.name);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
dput(dentry);
|
||||
}
|
||||
audit_log_format(ab, " dev=");
|
||||
audit_log_untrustedstring(ab, inode->i_sb->s_id);
|
||||
audit_log_format(ab, " ino=%lu", inode->i_ino);
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
}
|
||||
case LSM_AUDIT_DATA_TASK: {
|
||||
|
Loading…
Reference in New Issue
Block a user