Skip to content

Commit

Permalink
kernfs: add missing kernfs_active() checks in directory operations
Browse files Browse the repository at this point in the history
kernfs_iop_lookup(), kernfs_dir_pos() and kernfs_dir_next_pos() were
missing kernfs_active() tests before using the found kernfs_node.  As
deactivated state is currently visible only while a node is being
removed, this doesn't pose an actual problem.  e.g. lookup succeeding
on a deactivated node doesn't harm anything as the eventual file
operations are gonna fail and those failures are indistinguishible
from the cases in which the lookups had happened before the node was
deactivated.

However, we're gonna allow new nodes to be created deactivated and
then activated explicitly by the kernfs user when it sees fit.  This
is to support atomically making multiple nodes visible to userland and
thus those nodes must not be visible to userland before activated.

Let's plug the lookup and readdir holes so that deactivated nodes are
invisible to userland.

Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Tejun Heo authored and Greg Kroah-Hartman committed Feb 7, 2014
1 parent 6a7fed4 commit b9c9dad
Showing 1 changed file with 6 additions and 5 deletions.
11 changes: 6 additions & 5 deletions fs/kernfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
kn = kernfs_find_ns(parent, dentry->d_name.name, ns);

/* no such entry */
if (!kn) {
if (!kn || !kernfs_active(kn)) {
ret = NULL;
goto out_unlock;
}
Expand Down Expand Up @@ -1112,8 +1112,8 @@ static struct kernfs_node *kernfs_dir_pos(const void *ns,
break;
}
}
/* Skip over entries in the wrong namespace */
while (pos && pos->ns != ns) {
/* Skip over entries which are dying/dead or in the wrong namespace */
while (pos && (!kernfs_active(pos) || pos->ns != ns)) {
struct rb_node *node = rb_next(&pos->rb);
if (!node)
pos = NULL;
Expand All @@ -1127,14 +1127,15 @@ static struct kernfs_node *kernfs_dir_next_pos(const void *ns,
struct kernfs_node *parent, ino_t ino, struct kernfs_node *pos)
{
pos = kernfs_dir_pos(ns, parent, ino, pos);
if (pos)
if (pos) {
do {
struct rb_node *node = rb_next(&pos->rb);
if (!node)
pos = NULL;
else
pos = rb_to_kn(node);
} while (pos && pos->ns != ns);
} while (pos && (!kernfs_active(pos) || pos->ns != ns));
}
return pos;
}

Expand Down

0 comments on commit b9c9dad

Please sign in to comment.