summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
authorSanoj Unnikrishnan <sunnikri@redhat.com>2016-12-18 17:29:47 +0530
committerAtin Mukherjee <amukherj@redhat.com>2016-12-21 22:42:30 -0800
commit253c43596b9dcf57832a0369b6c4dc01598bd442 (patch)
tree254322cbe19e4f7e25f36fbb3d4c30fc3fb6a22e /xlators
parent97bfea234b1c097e7217181e7e6285fbd553d003 (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.c142
-rw-r--r--xlators/storage/posix/src/posix-messages.h10
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"