e7a346
From fe704e0f997444d74966aa7c5bfca484ce54f6a4 Mon Sep 17 00:00:00 2001
e7a346
From: Amar Tumballi <amarts@redhat.com>
e7a346
Date: Thu, 27 Sep 2018 09:55:19 +0530
e7a346
Subject: [PATCH 389/399] server: don't allow '/' in basename
e7a346
e7a346
Server stack needs to have all the sort of validation, assuming
e7a346
clients can be compromized. It is possible for a compromized
e7a346
client to send basenames with paths with '/', and with that
e7a346
create files without permission on server. By sanitizing the basename,
e7a346
and not allowing anything other than actual directory as the parent
e7a346
for any entry creation, we can mitigate the effects of clients
e7a346
not able to exploit the server.
e7a346
e7a346
Fixes: CVE-2018-14651
e7a346
e7a346
BUG: 1633013
e7a346
Change-Id: I98d042a9f8e300161fbc3ee5b6e8de755c9765f9
e7a346
Signed-off-by: Amar Tumballi <amarts@redhat.com>
e7a346
Reviewed-on: https://code.engineering.redhat.com/gerrit/151169
e7a346
Reviewed-by: Xavi Hernandez <xhernandez@redhat.com>
e7a346
Reviewed-by: Shyam Ranganathan <srangana@redhat.com>
e7a346
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
e7a346
---
e7a346
 xlators/protocol/server/src/server-resolve.c | 31 ++++++++++++++++++++--------
e7a346
 xlators/storage/posix/src/posix-handle.h     |  5 +++--
e7a346
 2 files changed, 25 insertions(+), 11 deletions(-)
e7a346
e7a346
diff --git a/xlators/protocol/server/src/server-resolve.c b/xlators/protocol/server/src/server-resolve.c
e7a346
index b3eda0e..25db43f 100644
e7a346
--- a/xlators/protocol/server/src/server-resolve.c
e7a346
+++ b/xlators/protocol/server/src/server-resolve.c
e7a346
@@ -307,22 +307,35 @@ resolve_entry_simple (call_frame_t *frame)
e7a346
                 ret = 1;
e7a346
                 goto out;
e7a346
         }
e7a346
-
e7a346
-        /* expected @parent was found from the inode cache */
e7a346
-        gf_uuid_copy (state->loc_now->pargfid, resolve->pargfid);
e7a346
-        state->loc_now->parent = inode_ref (parent);
e7a346
-
e7a346
-        if (strstr (resolve->bname, "../")) {
e7a346
-                /* Resolving outside the parent's tree is not allowed */
e7a346
+        if (parent->ia_type != IA_IFDIR) {
e7a346
+                /* Parent type should be 'directory', and nothing else */
e7a346
                 gf_msg (this->name, GF_LOG_ERROR, EPERM,
e7a346
                         PS_MSG_GFID_RESOLVE_FAILED,
e7a346
-                        "%s: path sent by client not allowed",
e7a346
-                        resolve->bname);
e7a346
+                        "%s: parent type not directory (%d)",
e7a346
+                        uuid_utoa (parent->gfid), parent->ia_type);
e7a346
                 resolve->op_ret   = -1;
e7a346
                 resolve->op_errno = EPERM;
e7a346
                 ret = 1;
e7a346
                 goto out;
e7a346
         }
e7a346
+
e7a346
+        /* expected @parent was found from the inode cache */
e7a346
+        gf_uuid_copy (state->loc_now->pargfid, resolve->pargfid);
e7a346
+        state->loc_now->parent = inode_ref (parent);
e7a346
+
e7a346
+        if (strchr (resolve->bname, '/')) {
e7a346
+               /* basename should be a string (without '/') in a directory,
e7a346
+                  it can't span multiple levels. This can also lead to
e7a346
+                  resolving outside the parent's tree, which is not allowed */
e7a346
+               gf_msg (this->name, GF_LOG_ERROR, EPERM,
e7a346
+                       PS_MSG_GFID_RESOLVE_FAILED,
e7a346
+                       "%s: basename sent by client not allowed",
e7a346
+                       resolve->bname);
e7a346
+               resolve->op_ret   = -1;
e7a346
+               resolve->op_errno = EPERM;
e7a346
+               ret = 1;
e7a346
+               goto out;
e7a346
+        }
e7a346
         state->loc_now->name = resolve->bname;
e7a346
 
e7a346
         inode = inode_grep (state->itable, parent, resolve->bname);
e7a346
diff --git a/xlators/storage/posix/src/posix-handle.h b/xlators/storage/posix/src/posix-handle.h
e7a346
index a0f82ec..45ca1d1 100644
e7a346
--- a/xlators/storage/posix/src/posix-handle.h
e7a346
+++ b/xlators/storage/posix/src/posix-handle.h
e7a346
@@ -223,9 +223,10 @@
e7a346
                 break;                                                  \
e7a346
         }                                                               \
e7a346
                                                                         \
e7a346
-        if (strstr (loc->name, "../")) {                                \
e7a346
+        if (strchr (loc->name, '/')) {                                  \
e7a346
                 gf_msg (this->name, GF_LOG_ERROR, 0, P_MSG_ENTRY_HANDLE_CREATE, \
e7a346
-                        "'../' in name not allowed: (%s)", loc->name); \
e7a346
+                        "'/' in name not allowed: (%s)", loc->name);    \
e7a346
+                op_ret = -1;                                            \
e7a346
                 break;                                                  \
e7a346
         }                                                               \
e7a346
         if (LOC_HAS_ABSPATH (loc)) {                                    \
e7a346
-- 
e7a346
1.8.3.1
e7a346