On Tue, 5 May 2015 06:22:21 +0100 Al Viro wrote: > From: Al Viro > > Array of MAX_NESTED_LINKS + 1 elements put into nameidata; > what used to be a local array in link_path_walk() occupies > entries 1 .. MAX_NESTED_LINKS in it, link and cookie from > the trailing symlink handling loops - entry 0. > > This is _not_ the final arrangement; just an easily verified > incremental step. > > Signed-off-by: Al Viro > --- > fs/namei.c | 35 ++++++++++++++++++----------------- > 1 file changed, 18 insertions(+), 17 deletions(-) > > diff --git a/fs/namei.c b/fs/namei.c > index 38ff968..e6d54ec 100644 > --- a/fs/namei.c > +++ b/fs/namei.c > @@ -505,6 +505,11 @@ struct nameidata { > int last_type; > unsigned depth; > struct file *base; > + struct saved { > + struct path link; > + void *cookie; > + const char *name; > + } stack[MAX_NESTED_LINKS + 1]; > }; > > /* > @@ -1703,11 +1708,7 @@ static inline u64 hash_name(const char *name) > */ > static int link_path_walk(const char *name, struct nameidata *nd) > { > - struct saved { > - struct path link; > - void *cookie; > - const char *name; > - } stack[MAX_NESTED_LINKS], *last = stack + nd->depth - 1; > + struct saved *last = nd->stack; This looks wrong. 'last' used to be dependent on nd->depth, now it isn't. Three patches later we have: +const char *get_link(struct nameidata *nd) { - struct dentry *dentry = link->dentry; + struct saved *last = nd->stack + nd->depth; + struct dentry *dentry = nd->link.dentry; struct inode *inode = dentry->d_inode; and static int link_path_walk(const char *name, struct nameidata *nd) { - struct saved *last = nd->stack; int err; .... - last->link = nd->link; - s = get_link(&last->link, nd, &last->cookie); + s = get_link(nd); so the nd->depth offset is restored in get_link() so the next result appears correct, but the intermediate states appear to be wrong. NeilBrown