new helper: iterate_mounts()
apply function to vfsmounts in set returned by collect_mounts(), stop if it returns non-zero. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
@@ -1246,6 +1246,21 @@ void drop_collected_mounts(struct vfsmount *mnt)
|
|||||||
release_mounts(&umount_list);
|
release_mounts(&umount_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
|
||||||
|
struct vfsmount *root)
|
||||||
|
{
|
||||||
|
struct vfsmount *mnt;
|
||||||
|
int res = f(root, arg);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
list_for_each_entry(mnt, &root->mnt_list, mnt_list) {
|
||||||
|
res = f(mnt, arg);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
|
static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
|
||||||
{
|
{
|
||||||
struct vfsmount *p;
|
struct vfsmount *p;
|
||||||
|
|||||||
@@ -1794,7 +1794,8 @@ extern int may_umount(struct vfsmount *);
|
|||||||
extern long do_mount(char *, char *, char *, unsigned long, void *);
|
extern long do_mount(char *, char *, char *, unsigned long, void *);
|
||||||
extern struct vfsmount *collect_mounts(struct path *);
|
extern struct vfsmount *collect_mounts(struct path *);
|
||||||
extern void drop_collected_mounts(struct vfsmount *);
|
extern void drop_collected_mounts(struct vfsmount *);
|
||||||
|
extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *,
|
||||||
|
struct vfsmount *);
|
||||||
extern int vfs_statfs(struct dentry *, struct kstatfs *);
|
extern int vfs_statfs(struct dentry *, struct kstatfs *);
|
||||||
|
|
||||||
extern int current_umask(void);
|
extern int current_umask(void);
|
||||||
|
|||||||
@@ -548,6 +548,11 @@ int audit_remove_tree_rule(struct audit_krule *rule)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int compare_root(struct vfsmount *mnt, void *arg)
|
||||||
|
{
|
||||||
|
return mnt->mnt_root->d_inode == arg;
|
||||||
|
}
|
||||||
|
|
||||||
void audit_trim_trees(void)
|
void audit_trim_trees(void)
|
||||||
{
|
{
|
||||||
struct list_head cursor;
|
struct list_head cursor;
|
||||||
@@ -559,7 +564,6 @@ void audit_trim_trees(void)
|
|||||||
struct path path;
|
struct path path;
|
||||||
struct vfsmount *root_mnt;
|
struct vfsmount *root_mnt;
|
||||||
struct node *node;
|
struct node *node;
|
||||||
struct list_head list;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
tree = container_of(cursor.next, struct audit_tree, list);
|
tree = container_of(cursor.next, struct audit_tree, list);
|
||||||
@@ -577,24 +581,16 @@ void audit_trim_trees(void)
|
|||||||
if (!root_mnt)
|
if (!root_mnt)
|
||||||
goto skip_it;
|
goto skip_it;
|
||||||
|
|
||||||
list_add_tail(&list, &root_mnt->mnt_list);
|
|
||||||
spin_lock(&hash_lock);
|
spin_lock(&hash_lock);
|
||||||
list_for_each_entry(node, &tree->chunks, list) {
|
list_for_each_entry(node, &tree->chunks, list) {
|
||||||
struct audit_chunk *chunk = find_chunk(node);
|
struct inode *inode = find_chunk(node)->watch.inode;
|
||||||
struct inode *inode = chunk->watch.inode;
|
|
||||||
struct vfsmount *mnt;
|
|
||||||
node->index |= 1U<<31;
|
node->index |= 1U<<31;
|
||||||
list_for_each_entry(mnt, &list, mnt_list) {
|
if (iterate_mounts(compare_root, inode, root_mnt))
|
||||||
if (mnt->mnt_root->d_inode == inode) {
|
node->index &= ~(1U<<31);
|
||||||
node->index &= ~(1U<<31);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
spin_unlock(&hash_lock);
|
spin_unlock(&hash_lock);
|
||||||
trim_marked(tree);
|
trim_marked(tree);
|
||||||
put_tree(tree);
|
put_tree(tree);
|
||||||
list_del_init(&list);
|
|
||||||
drop_collected_mounts(root_mnt);
|
drop_collected_mounts(root_mnt);
|
||||||
skip_it:
|
skip_it:
|
||||||
mutex_lock(&audit_filter_mutex);
|
mutex_lock(&audit_filter_mutex);
|
||||||
@@ -622,13 +618,17 @@ void audit_put_tree(struct audit_tree *tree)
|
|||||||
put_tree(tree);
|
put_tree(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tag_mount(struct vfsmount *mnt, void *arg)
|
||||||
|
{
|
||||||
|
return tag_chunk(mnt->mnt_root->d_inode, arg);
|
||||||
|
}
|
||||||
|
|
||||||
/* called with audit_filter_mutex */
|
/* called with audit_filter_mutex */
|
||||||
int audit_add_tree_rule(struct audit_krule *rule)
|
int audit_add_tree_rule(struct audit_krule *rule)
|
||||||
{
|
{
|
||||||
struct audit_tree *seed = rule->tree, *tree;
|
struct audit_tree *seed = rule->tree, *tree;
|
||||||
struct path path;
|
struct path path;
|
||||||
struct vfsmount *mnt, *p;
|
struct vfsmount *mnt;
|
||||||
struct list_head list;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
list_for_each_entry(tree, &tree_list, list) {
|
list_for_each_entry(tree, &tree_list, list) {
|
||||||
@@ -654,16 +654,9 @@ int audit_add_tree_rule(struct audit_krule *rule)
|
|||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto Err;
|
goto Err;
|
||||||
}
|
}
|
||||||
list_add_tail(&list, &mnt->mnt_list);
|
|
||||||
|
|
||||||
get_tree(tree);
|
get_tree(tree);
|
||||||
list_for_each_entry(p, &list, mnt_list) {
|
err = iterate_mounts(tag_mount, tree, mnt);
|
||||||
err = tag_chunk(p->mnt_root->d_inode, tree);
|
|
||||||
if (err)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_del(&list);
|
|
||||||
drop_collected_mounts(mnt);
|
drop_collected_mounts(mnt);
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
@@ -700,7 +693,6 @@ int audit_tag_tree(char *old, char *new)
|
|||||||
int failed = 0;
|
int failed = 0;
|
||||||
struct path path1, path2;
|
struct path path1, path2;
|
||||||
struct vfsmount *tagged;
|
struct vfsmount *tagged;
|
||||||
struct list_head list;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = kern_path(new, 0, &path2);
|
err = kern_path(new, 0, &path2);
|
||||||
@@ -717,15 +709,12 @@ int audit_tag_tree(char *old, char *new)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add_tail(&list, &tagged->mnt_list);
|
|
||||||
|
|
||||||
mutex_lock(&audit_filter_mutex);
|
mutex_lock(&audit_filter_mutex);
|
||||||
list_add(&barrier, &tree_list);
|
list_add(&barrier, &tree_list);
|
||||||
list_add(&cursor, &barrier);
|
list_add(&cursor, &barrier);
|
||||||
|
|
||||||
while (cursor.next != &tree_list) {
|
while (cursor.next != &tree_list) {
|
||||||
struct audit_tree *tree;
|
struct audit_tree *tree;
|
||||||
struct vfsmount *p;
|
|
||||||
int good_one = 0;
|
int good_one = 0;
|
||||||
|
|
||||||
tree = container_of(cursor.next, struct audit_tree, list);
|
tree = container_of(cursor.next, struct audit_tree, list);
|
||||||
@@ -746,12 +735,7 @@ int audit_tag_tree(char *old, char *new)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(p, &list, mnt_list) {
|
failed = iterate_mounts(tag_mount, tree, tagged);
|
||||||
failed = tag_chunk(p->mnt_root->d_inode, tree);
|
|
||||||
if (failed)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failed) {
|
if (failed) {
|
||||||
put_tree(tree);
|
put_tree(tree);
|
||||||
mutex_lock(&audit_filter_mutex);
|
mutex_lock(&audit_filter_mutex);
|
||||||
@@ -792,7 +776,6 @@ int audit_tag_tree(char *old, char *new)
|
|||||||
}
|
}
|
||||||
list_del(&barrier);
|
list_del(&barrier);
|
||||||
list_del(&cursor);
|
list_del(&cursor);
|
||||||
list_del(&list);
|
|
||||||
mutex_unlock(&audit_filter_mutex);
|
mutex_unlock(&audit_filter_mutex);
|
||||||
path_put(&path1);
|
path_put(&path1);
|
||||||
drop_collected_mounts(tagged);
|
drop_collected_mounts(tagged);
|
||||||
|
|||||||
Reference in New Issue
Block a user