diff options
author | Sanoj Unnikrishnan <sunnikri@redhat.com> | 2016-12-18 17:29:47 +0530 |
---|---|---|
committer | Atin Mukherjee <amukherj@redhat.com> | 2016-12-21 22:42:30 -0800 |
commit | 253c43596b9dcf57832a0369b6c4dc01598bd442 (patch) | |
tree | 254322cbe19e4f7e25f36fbb3d4c30fc3fb6a22e /xlators | |
parent | 97bfea234b1c097e7217181e7e6285fbd553d003 (diff) |
Fixes GlusterFS process crashes on deep directory hierarchy
alloca() calls to recusive function posix_make_ancestryfromgfid
consumes the entire stack leading to segfault.
Changed the function to iterative and reused the same linkname
buffer across iterations.
Change-Id: If065c8b9f7f85219bdd2d23259a115fe66f5f60d
BUG: 1405775
Signed-off-by: Sanoj Unnikrishnan <sunnikri@redhat.com>
Reviewed-on: http://review.gluster.org/16192
Smoke: Gluster Build System <jenkins@build.gluster.org>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Diffstat (limited to 'xlators')
-rw-r--r-- | xlators/storage/posix/src/posix-handle.c | 142 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix-messages.h | 10 |
2 files changed, 87 insertions, 65 deletions
diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c index ddafb0d9b04..c8524a69fe5 100644 --- a/xlators/storage/posix/src/posix-handle.c +++ b/xlators/storage/posix/src/posix-handle.c @@ -124,7 +124,6 @@ posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize, char *linkname = NULL; /* "../../<gfid[0]>/<gfid[1]/" "<gfidstr>/<NAME_MAX>" */ char *dir_handle = NULL; - char *dir_name = NULL; char *pgfidstr = NULL; char *saveptr = NULL; ssize_t len = 0; @@ -132,93 +131,106 @@ posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize, struct iatt iabuf = {0, }; int ret = -1; uuid_t tmp_gfid = {0, }; + char *dir_stack[PATH_MAX/2]; /* Since PATH_MAX/2 also gives + an upper bound on depth of + directories tree */ + uuid_t gfid_stack[PATH_MAX/2]; + + char *dir_name = NULL; + char *saved_dir = NULL; + int top = -1; if (!path || !parent || !priv_base_path || gf_uuid_is_null (gfid)) { *op_errno = EINVAL; goto out; } - if (__is_root_gfid (gfid)) { - if (parent) { - if (*parent) { - inode_unref (*parent); - } + dir_handle = alloca (handle_size); + linkname = alloca (PATH_MAX); + gf_uuid_copy(tmp_gfid, gfid); + + while (top < PATH_MAX/2) { + + gf_uuid_copy(gfid_stack[++top], tmp_gfid); + if (__is_root_gfid (tmp_gfid)) { *parent = inode_ref (itable->root); - } + saved_dir = alloca(strlen("/") + 1); + strcpy(saved_dir, "/"); + dir_stack[top] = saved_dir; + break; + } else { + snprintf (dir_handle, handle_size, "%s/%s/%02x/%02x/%s", + priv_base_path, GF_HIDDEN_PATH, tmp_gfid[0], + tmp_gfid[1], uuid_utoa (tmp_gfid)); + + len = sys_readlink (dir_handle, linkname, PATH_MAX); + if (len < 0) { + *op_errno = errno; + gf_msg (this->name, (errno == ENOENT || + errno == ESTALE) + ? GF_LOG_DEBUG:GF_LOG_ERROR, errno, + P_MSG_READLINK_FAILED, "could not read" + " the link from the gfid handle %s ", + dir_handle); + ret = -1; + goto out; + } - inode = posix_resolve (this, itable, *parent, "/", &iabuf); - if (!inode) { - gf_msg (this->name, GF_LOG_ERROR, - P_MSG_INODE_RESOLVE_FAILED, 0, - "posix resolve on the root inode %s failed", - uuid_utoa (gfid)); - *op_errno = ESTALE; - goto out; - } + linkname[len] = '\0'; - ret = posix_make_ancestral_node (priv_base_path, path, pathsize, - head, "/", &iabuf, inode, type, - xdata); - if (ret < 0) - *op_errno = ENOMEM; - return ret; + pgfidstr = strtok_r (linkname + SLEN("../../00/00/"), + "/", &saveptr); + dir_name = strtok_r (NULL, "/", &saveptr); + saved_dir = alloca(strlen(dir_name) + 1); + gf_uuid_parse (pgfidstr, tmp_gfid); + strcpy(saved_dir, dir_name); + dir_stack[top] = saved_dir; + } } - - dir_handle = alloca (handle_size); - linkname = alloca (PATH_MAX); - snprintf (dir_handle, handle_size, "%s/%s/%02x/%02x/%s", - priv_base_path, GF_HIDDEN_PATH, gfid[0], gfid[1], - uuid_utoa (gfid)); - - len = sys_readlink (dir_handle, linkname, PATH_MAX); - if (len < 0) { - gf_msg (this->name, (errno == ENOENT || errno == ESTALE) - ? GF_LOG_DEBUG:GF_LOG_ERROR, errno, - P_MSG_READLINK_FAILED, "could not read the link from " - "the gfid handle %s ", dir_handle); + if (top == PATH_MAX/2) { + gf_msg (this->name, GF_LOG_ERROR, + P_MSG_ANCESTORY_FAILED, + 0, "build ancestory failed due to " + "deep directory hierarchy, depth: %d.", top); + *op_errno = EINVAL; ret = -1; - *op_errno = errno; goto out; } - linkname[len] = '\0'; - - pgfidstr = strtok_r (linkname + SLEN("../../00/00/"), "/", &saveptr); - dir_name = strtok_r (NULL, "/", &saveptr); - - gf_uuid_parse (pgfidstr, tmp_gfid); + while (top >= 0) { - ret = posix_make_ancestryfromgfid (this, path, pathsize, head, type, - tmp_gfid, handle_size, - priv_base_path, itable, parent, - xdata, op_errno); - if (ret < 0) { - goto out; - } + memset (&iabuf, 0, sizeof (iabuf)); + inode = posix_resolve (this, itable, *parent, + dir_stack[top], &iabuf); + if (inode == NULL) { + gf_msg (this->name, GF_LOG_ERROR, + P_MSG_INODE_RESOLVE_FAILED, + 0, "posix resolve on the inode %s failed", + uuid_utoa (gfid_stack[top])); + *op_errno = ESTALE; + ret = -1; + goto out; + } - memset (&iabuf, 0, sizeof (iabuf)); + ret = posix_make_ancestral_node (priv_base_path, path, + pathsize, head, + dir_stack[top], &iabuf, + inode, type, xdata); + if (ret < 0) { + *op_errno = ENOMEM; + goto out; + } - inode = posix_resolve (this, itable, *parent, dir_name, &iabuf); - if (inode == NULL) { - gf_msg (this->name, GF_LOG_ERROR, P_MSG_INODE_RESOLVE_FAILED, - 0, "posix resolve on the root inode %s failed", - uuid_utoa (gfid)); - *op_errno = ESTALE; - ret = -1; - goto out; + inode_unref (*parent); + *parent = inode_ref(inode); + top--; } - - ret = posix_make_ancestral_node (priv_base_path, path, pathsize, head, - dir_name, &iabuf, inode, type, xdata); +out: if (*parent != NULL) { inode_unref (*parent); } - - *parent = inode; - -out: return ret; } diff --git a/xlators/storage/posix/src/posix-messages.h b/xlators/storage/posix/src/posix-messages.h index ba6bf2c43ac..ee06d6f7d85 100644 --- a/xlators/storage/posix/src/posix-messages.h +++ b/xlators/storage/posix/src/posix-messages.h @@ -945,6 +945,16 @@ * */ +#define P_MSG_ANCESTORY_FAILED (POSIX_COMP_BASE + 111) + +/*! + * @messageid + * @diagnosis + * @recommendedaction + * + */ + + /*------------*/ #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages" |