From 0f7dadac5b712f706c6d08765ac5bf02a4550ae5 Mon Sep 17 00:00:00 2001 From: Sam Lang Date: Mon, 5 Nov 2012 17:17:22 -0600 Subject: [PATCH] client: Add symlink loop checking in path_walk() If a loop exists in directories due to a symlink: /a/b/c -> /a We now return -ELOOP from path_walk() instead of looping forever. Signed-off-by: Sam Lang --- src/client/Client.cc | 8 ++++++++ src/client/Inode.h | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/client/Client.cc b/src/client/Client.cc index f259182977941..830ab8c9c07ef 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -3719,6 +3719,7 @@ int Client::path_walk(const filepath& origpath, Inode **final, bool followsym) ldout(cct, 10) << "path_walk " << path << dendl; + set visited; unsigned i=0; while (i < path.depth() && cur) { const string &dname = path[i]; @@ -3731,6 +3732,13 @@ int Client::path_walk(const filepath& origpath, Inode **final, bool followsym) // 'directory' symlinks. if (next && next->is_symlink()) { if (i < path.depth() - 1) { + // check for loops + if(visited.find(next) != visited.end()) { + // already hit this one, return error + return -ELOOP; + } + visited.insert(next); + // dir symlink // replace consumed components of path with symlink dir target filepath resolved(next->symlink.c_str()); diff --git a/src/client/Inode.h b/src/client/Inode.h index ff5e96c6f9fc9..6bda720d5a320 100644 --- a/src/client/Inode.h +++ b/src/client/Inode.h @@ -211,6 +211,14 @@ class Inode { vinodeno_t vino() { return vinodeno_t(ino, snapid); } + struct Compare { + bool operator() (Inode* const & left, Inode* const & right) { + if (left->ino.val < right->ino.val) { + return (left->snapid.val < right->snapid.val); + } + return false; + } + }; bool check_mode(uid_t uid, gid_t gid, gid_t *sgids, int sgid_count, uint32_t flags); -- 2.39.5