From bd57c7d64844ca26d80f2b29db470dacd134fc56 Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Wed, 21 Nov 2012 10:39:51 -0600 Subject: [PATCH] LINUX: Dir follow_link should set LAST_BIND 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 Reviewed-by: Marc Dionne Reviewed-by: Derrick Brashear --- src/afs/LINUX/osi_vnodeops.c | 2 ++ src/afs/LINUX24/osi_vnodeops.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index f089f14b3..de1a7039d 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -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 */ diff --git a/src/afs/LINUX24/osi_vnodeops.c b/src/afs/LINUX24/osi_vnodeops.c index 46b82b73d..f3079903a 100644 --- a/src/afs/LINUX24/osi_vnodeops.c +++ b/src/afs/LINUX24/osi_vnodeops.c @@ -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; } -- 2.39.5