From 238b88624a8fef39557d397cc336c88bd8efc5b1 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. Change-Id: Id6d2edd614388ac0890eb7591caec25d375964ce Reviewed-on: http://gerrit.openafs.org/8009 Reviewed-by: Derrick Brashear Tested-by: BuildBot --- 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 1a4602ed6e..581438688b 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -1257,6 +1257,10 @@ afs_dentry_automount(afs_linux_path_t *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) { @@ -2721,6 +2725,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