]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
CVE-2017-2619: s3: smbd: Create and use open_dir_safely(). Use from OpenDir().
authorJeremy Allison <jra@samba.org>
Tue, 20 Dec 2016 00:35:00 +0000 (16:35 -0800)
committerKarolin Seeger <kseeger@samba.org>
Wed, 22 Mar 2017 09:45:16 +0000 (10:45 +0100)
Hardens OpenDir against TOC/TOU races.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Uri Simchoni <uri@samba.org>
source3/smbd/dir.c

index ea4b301642b0c2b2b86f29a412dd67976895c2d0..39a6e677738624896d683e1038165caadcbf6032 100644 (file)
@@ -1601,15 +1601,9 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
-       dirp->dir_path = talloc_strdup(dirp, name);
-       if (!dirp->dir_path) {
-               errno = ENOMEM;
-               goto fail;
-       }
-
-       dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
+       dirp->dir = SMB_VFS_OPENDIR(conn, name, mask, attr);
        if (!dirp->dir) {
-               DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path,
+               DEBUG(5,("OpenDir: Can't open %s. %s\n", name,
                         strerror(errno) ));
                goto fail;
        }
@@ -1629,12 +1623,70 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
        return NULL;
 }
 
+/****************************************************************************
+ Open a directory handle by pathname, ensuring it's under the share path.
+****************************************************************************/
+
+static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
+                                       connection_struct *conn,
+                                       const char *name,
+                                       const char *wcard,
+                                       uint32_t attr)
+{
+       struct smb_Dir *dir_hnd = NULL;
+       char *saved_dir = vfs_GetWd(ctx, conn);
+       NTSTATUS status;
+
+       if (saved_dir == NULL) {
+               return NULL;
+       }
+
+       if (vfs_ChDir(conn, name) == -1) {
+               goto out;
+       }
+
+       /*
+        * Now the directory is pinned, use
+        * REALPATH to ensure we can access it.
+        */
+       status = check_name(conn, ".");
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+
+       dir_hnd = OpenDir_internal(ctx,
+                               conn,
+                               ".",
+                               wcard,
+                               attr);
+
+       if (dir_hnd == NULL) {
+               goto out;
+       }
+
+       /*
+        * OpenDir_internal only gets "." as the dir name.
+        * Store the real dir name here.
+        */
+
+       dir_hnd->dir_path = talloc_strdup(dir_hnd, name);
+       if (!dir_hnd->dir_path) {
+               errno = ENOMEM;
+       }
+
+  out:
+
+       vfs_ChDir(conn, saved_dir);
+       TALLOC_FREE(saved_dir);
+       return dir_hnd;
+}
+
 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
                        const char *name,
                        const char *mask,
                        uint32_t attr)
 {
-       return OpenDir_internal(mem_ctx,
+       return open_dir_safely(mem_ctx,
                                conn,
                                name,
                                mask,