From 12fd096719b2cb41a69d6442276b60e5a40d4f78 Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Tue, 21 Aug 2012 17:03:30 -0500 Subject: [PATCH] LINUX: Avoid symlink-y resolution limits Implementing the d_automount or follow_link function pointers for our directories means that we can hit symlink resolution limits during lookup, since we look like a "symlink". We can hit these limits pretty easily if there are just too many directories in the lookup path. Our pseudo-symlink directories cannot contribute to an infinite resolution loop, since our destination is always an actual directory, not a symlink that will result in more redirection. So, decrement the total_link_count counter when our d_automount or follow_link code is reached, so we do not contribute to hitting the max resolution limit. Note that this is not related to recursive symlink lookup (link_count) but only to the iterative symlink limit (total_link_count). Our lookups are not recursive here, and we are not causing more recursive lookups like a normal text-based symlink would do. Reviewed-on: http://gerrit.openafs.org/8009 Reviewed-by: Derrick Brashear Tested-by: BuildBot (cherry picked from commit 238b88624a8fef39557d397cc336c88bd8efc5b1) Change-Id: Ib14ee9d160189da658f36578e21bd458e6e7832a Reviewed-on: http://gerrit.openafs.org/8195 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- src/afs/LINUX/osi_vnodeops.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 9748846942..478eb7efd6 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -1082,6 +1082,10 @@ afs_dentry_automount(struct path *path) { struct dentry *target; + /* avoid symlink resolution limits when resolving; we cannot contribute to + * an infinite symlink loop */ + current->total_link_count--; + target = canonical_dentry(path->dentry->d_inode); if (target == path->dentry) { @@ -2017,6 +2021,17 @@ afs_linux_dir_follow_link(struct dentry *dentry, struct nameidata *nd) struct dentry **dpp; struct dentry *target; + if (current->total_link_count > 0) { + /* avoid symlink resolution limits when resolving; we cannot contribute to + * an infinite symlink loop */ + /* only do this for follow_link when total_link_count is positive to be + * on the safe side; there is at least one code path in the Linux + * kernel where it seems like it may be possible to get here without + * total_link_count getting incremented. it is not clear on how that + * path is actually reached, but guard against it just to be safe */ + current->total_link_count--; + } + target = canonical_dentry(dentry->d_inode); # ifdef STRUCT_NAMEIDATA_HAS_PATH