New helper: path_is_under(path1, path2)

Analog of is_subdir for vfsmount,dentry pairs, moved from audit_tree.c

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2010-01-30 13:16:21 -05:00
parent 495d6c9c65
commit 2096f759ab
3 changed files with 37 additions and 39 deletions

View File

@ -2191,6 +2191,30 @@ int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
return result; return result;
} }
int path_is_under(struct path *path1, struct path *path2)
{
struct vfsmount *mnt = path1->mnt;
struct dentry *dentry = path1->dentry;
int res;
spin_lock(&vfsmount_lock);
if (mnt != path2->mnt) {
for (;;) {
if (mnt->mnt_parent == mnt) {
spin_unlock(&vfsmount_lock);
return 0;
}
if (mnt->mnt_parent == path2->mnt)
break;
mnt = mnt->mnt_parent;
}
dentry = mnt->mnt_mountpoint;
}
res = is_subdir(dentry, path2->dentry);
spin_unlock(&vfsmount_lock);
return res;
}
EXPORT_SYMBOL(path_is_under);
void d_genocide(struct dentry *root) void d_genocide(struct dentry *root)
{ {
struct dentry *this_parent = root; struct dentry *this_parent = root;

View File

@ -2126,6 +2126,7 @@ extern struct file * open_exec(const char *);
/* fs/dcache.c -- generic fs support functions */ /* fs/dcache.c -- generic fs support functions */
extern int is_subdir(struct dentry *, struct dentry *); extern int is_subdir(struct dentry *, struct dentry *);
extern int path_is_under(struct path *, struct path *);
extern ino_t find_inode_number(struct dentry *, struct qstr *); extern ino_t find_inode_number(struct dentry *, struct qstr *);
#include <linux/err.h> #include <linux/err.h>

View File

@ -603,22 +603,6 @@ skip_it:
mutex_unlock(&audit_filter_mutex); mutex_unlock(&audit_filter_mutex);
} }
static int is_under(struct vfsmount *mnt, struct dentry *dentry,
struct path *path)
{
if (mnt != path->mnt) {
for (;;) {
if (mnt->mnt_parent == mnt)
return 0;
if (mnt->mnt_parent == path->mnt)
break;
mnt = mnt->mnt_parent;
}
dentry = mnt->mnt_mountpoint;
}
return is_subdir(dentry, path->dentry);
}
int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op)
{ {
@ -714,29 +698,24 @@ int audit_tag_tree(char *old, char *new)
{ {
struct list_head cursor, barrier; struct list_head cursor, barrier;
int failed = 0; int failed = 0;
struct path path; struct path path1, path2;
struct vfsmount *tagged; struct vfsmount *tagged;
struct list_head list; struct list_head list;
struct vfsmount *mnt;
struct dentry *dentry;
int err; int err;
err = kern_path(new, 0, &path); err = kern_path(new, 0, &path2);
if (err) if (err)
return err; return err;
tagged = collect_mounts(&path); tagged = collect_mounts(&path2);
path_put(&path); path_put(&path2);
if (!tagged) if (!tagged)
return -ENOMEM; return -ENOMEM;
err = kern_path(old, 0, &path); err = kern_path(old, 0, &path1);
if (err) { if (err) {
drop_collected_mounts(tagged); drop_collected_mounts(tagged);
return err; return err;
} }
mnt = mntget(path.mnt);
dentry = dget(path.dentry);
path_put(&path);
list_add_tail(&list, &tagged->mnt_list); list_add_tail(&list, &tagged->mnt_list);
@ -747,6 +726,7 @@ int audit_tag_tree(char *old, char *new)
while (cursor.next != &tree_list) { while (cursor.next != &tree_list) {
struct audit_tree *tree; struct audit_tree *tree;
struct vfsmount *p; struct vfsmount *p;
int good_one = 0;
tree = container_of(cursor.next, struct audit_tree, list); tree = container_of(cursor.next, struct audit_tree, list);
get_tree(tree); get_tree(tree);
@ -754,23 +734,17 @@ int audit_tag_tree(char *old, char *new)
list_add(&cursor, &tree->list); list_add(&cursor, &tree->list);
mutex_unlock(&audit_filter_mutex); mutex_unlock(&audit_filter_mutex);
err = kern_path(tree->pathname, 0, &path); err = kern_path(tree->pathname, 0, &path2);
if (err) { if (!err) {
put_tree(tree); good_one = path_is_under(&path1, &path2);
mutex_lock(&audit_filter_mutex); path_put(&path2);
continue;
} }
spin_lock(&vfsmount_lock); if (!good_one) {
if (!is_under(mnt, dentry, &path)) {
spin_unlock(&vfsmount_lock);
path_put(&path);
put_tree(tree); put_tree(tree);
mutex_lock(&audit_filter_mutex); mutex_lock(&audit_filter_mutex);
continue; continue;
} }
spin_unlock(&vfsmount_lock);
path_put(&path);
list_for_each_entry(p, &list, mnt_list) { list_for_each_entry(p, &list, mnt_list) {
failed = tag_chunk(p->mnt_root->d_inode, tree); failed = tag_chunk(p->mnt_root->d_inode, tree);
@ -820,8 +794,7 @@ int audit_tag_tree(char *old, char *new)
list_del(&cursor); list_del(&cursor);
list_del(&list); list_del(&list);
mutex_unlock(&audit_filter_mutex); mutex_unlock(&audit_filter_mutex);
dput(dentry); path_put(&path1);
mntput(mnt);
drop_collected_mounts(tagged); drop_collected_mounts(tagged);
return failed; return failed;
} }