LINUX: Dir follow_link should set LAST_BIND
authorAndrew Deason <adeason@sinenomine.net>
Wed, 21 Nov 2012 16:39:51 +0000 (10:39 -0600)
committerDerrick Brashear <shadow@your-file-system.com>
Mon, 26 Nov 2012 19:48:48 +0000 (11:48 -0800)
For our faux-symlink directory follow_link operation, we leave the
given nameidata struct with an invalid 'last' component. That is,
nd->last is not changed or set to anything meaningful.

Usually the callers of our follow_link op do not care about the last
component of the nameidata. However, at least one caller does: the
caller near the do_link label in open_namei(). This is called during
processing for O_CREAT operations on symlinks, and since our
directories look like symlinks, it gets called. It tries to use
nd->last to look up the last component of the dereferenced path (so it
can try to create it, as necessary), but since our nd->last is not
set, this will not work.

Specifically, our nd->last.name is not pointing into the names cache,
so the subsequent putname/__putname on it will corrupt the names
cache. However, even if this were not a problem, the actual contents
of the last component do not seem meaningful so this would probably
result in incorrect behavior anyway.

To avoid all of this, set nd->last_type to LAST_BIND, so any callers
know that the last component of the given nd is not valid, and we are
pointing directly to the target component with a dentry.

Change-Id: I9cebc3b63ae7a2410295392a08aa8fc738549234
Reviewed-on: http://gerrit.openafs.org/8489
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Marc Dionne <marc.c.dionne@gmail.com>
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>

src/afs/LINUX/osi_vnodeops.c
src/afs/LINUX24/osi_vnodeops.c

index f089f14..de1a703 100644 (file)
@@ -2763,6 +2763,8 @@ afs_linux_dir_follow_link(struct dentry *dentry, struct nameidata *nd)
        *dpp = dget(dentry);
     }
 
+    nd->last_type = LAST_BIND;
+
     return NULL;
 }
 #endif /* !STRUCT_DENTRY_OPERATIONS_HAS_D_AUTOMOUNT */
index 46b82b7..f307990 100644 (file)
@@ -2085,6 +2085,8 @@ afs_linux_dir_follow_link(struct dentry *dentry, struct nameidata *nd)
        *dpp = dget(dentry);
     }
 
+    nd->last_type = LAST_BIND;
+
     return 0;
 }