[Pkg-samba-maint] [samba] 12/17: Patch for CVE-2017-2619

Mathieu Parent sathieu at moszumanska.debian.org
Thu Mar 23 19:02:23 UTC 2017


This is an automated email from the git hooks/post-receive script.

sathieu pushed a commit to branch master
in repository samba.

commit 391e2e7874d02af0efd6309af80e0f818fd2ee3e
Author: Mathieu Parent <math.parent at gmail.com>
Date:   Fri Mar 3 23:10:22 2017 +0100

    Patch for CVE-2017-2619
    
    See https://bugzilla.samba.org/show_bug.cgi?id=12496
---
 debian/patches/CVE-2017-2619.patch | 878 +++++++++++++++++++++++++++++++++++++
 debian/patches/series              |   1 +
 2 files changed, 879 insertions(+)

diff --git a/debian/patches/CVE-2017-2619.patch b/debian/patches/CVE-2017-2619.patch
new file mode 100644
index 0000000..a82218f
--- /dev/null
+++ b/debian/patches/CVE-2017-2619.patch
@@ -0,0 +1,878 @@
+From 2f19e3e9770957112243f9945c7a7dd7bb99ae9f Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 19 Dec 2016 11:55:56 -0800
+Subject: [PATCH 01/11] s3: smbd: Create wrapper function for OpenDir in
+ preparation for making robust.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/dir.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 3c6f00096fa..b22d92d7ba9 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1630,7 +1630,8 @@ static int smb_Dir_destructor(struct smb_Dir *dirp)
+  Open a directory.
+ ********************************************************************/
+ 
+-struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
++static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
++			connection_struct *conn,
+ 			const struct smb_filename *smb_dname,
+ 			const char *mask,
+ 			uint32_t attr)
+@@ -1672,6 +1673,18 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
+ 	return NULL;
+ }
+ 
++struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
++			const struct smb_filename *smb_dname,
++			const char *mask,
++			uint32_t attr)
++{
++	return OpenDir_internal(mem_ctx,
++				conn,
++				smb_dname,
++				mask,
++				attr);
++}
++
+ /*******************************************************************
+  Open a directory from an fsp.
+ ********************************************************************/
+-- 
+2.11.0.483.g087da7b7c-goog
+
+
+From ee91b94ccb2497d24958f877d186a6e691d40c90 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 19 Dec 2016 16:25:26 -0800
+Subject: [PATCH 02/11] s3: smbd: Opendir_internal() early return if
+ SMB_VFS_OPENDIR failed.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/dir.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index b22d92d7ba9..a5d172a86e1 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1643,6 +1643,15 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
+ 		return NULL;
+ 	}
+ 
++	dirp->dir = SMB_VFS_OPENDIR(conn, smb_dname, mask, attr);
++
++	if (!dirp->dir) {
++		DEBUG(5,("OpenDir: Can't open %s. %s\n",
++			smb_dname->base_name,
++			strerror(errno) ));
++		goto fail;
++	}
++
+ 	dirp->conn = conn;
+ 	dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
+ 
+@@ -1657,15 +1666,6 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
+ 	}
+ 	talloc_set_destructor(dirp, smb_Dir_destructor);
+ 
+-	dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_smb_fname, mask, attr);
+-
+-	if (!dirp->dir) {
+-		DEBUG(5,("OpenDir: Can't open %s. %s\n",
+-			dirp->dir_smb_fname->base_name,
+-			strerror(errno) ));
+-		goto fail;
+-	}
+-
+ 	return dirp;
+ 
+   fail:
+-- 
+2.11.0.483.g087da7b7c-goog
+
+
+From 3bb7362356dfc1574544027a506f25a00dd83afe Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 19 Dec 2016 16:35:00 -0800
+Subject: [PATCH 03/11] s3: smbd: Create and use open_dir_safely(). Use from
+ OpenDir().
+
+Hardens OpenDir against TOC/TOU races.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/dir.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 70 insertions(+), 7 deletions(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index a5d172a86e1..2b107a9b69b 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1655,12 +1655,6 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
+ 	dirp->conn = conn;
+ 	dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
+ 
+-	dirp->dir_smb_fname = cp_smb_filename(dirp, smb_dname);
+-	if (!dirp->dir_smb_fname) {
+-		errno = ENOMEM;
+-		goto fail;
+-	}
+-
+ 	if (sconn && !sconn->using_smb2) {
+ 		sconn->searches.dirhandles_open++;
+ 	}
+@@ -1673,12 +1667,81 @@ 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 struct smb_filename *smb_dname,
++					const char *wcard,
++					uint32_t attr)
++{
++	struct smb_Dir *dir_hnd = NULL;
++	struct smb_filename *smb_fname_cwd = NULL;
++	char *saved_dir = vfs_GetWd(ctx, conn);
++	NTSTATUS status;
++
++	if (saved_dir == NULL) {
++		return NULL;
++	}
++
++	if (vfs_ChDir(conn, smb_dname->base_name) == -1) {
++		goto out;
++	}
++
++	smb_fname_cwd = synthetic_smb_fname(talloc_tos(),
++					".",
++					NULL,
++					NULL,
++					smb_dname->flags);
++	if (smb_fname_cwd == NULL) {
++		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,
++				smb_fname_cwd,
++				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_smb_fname = cp_smb_filename(dir_hnd, smb_dname);
++	if (!dir_hnd->dir_smb_fname) {
++		TALLOC_FREE(dir_hnd);
++		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 struct smb_filename *smb_dname,
+ 			const char *mask,
+ 			uint32_t attr)
+ {
+-	return OpenDir_internal(mem_ctx,
++	return open_dir_safely(mem_ctx,
+ 				conn,
+ 				smb_dname,
+ 				mask,
+-- 
+2.11.0.483.g087da7b7c-goog
+
+
+From 01bb5f73735699380a8ffedbd0f0cb0881989bd1 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 19 Dec 2016 12:13:20 -0800
+Subject: [PATCH 04/11] s3: smbd: OpenDir_fsp() use early returns.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/dir.c | 34 +++++++++++++++++++++-------------
+ 1 file changed, 21 insertions(+), 13 deletions(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 2b107a9b69b..12edf80ee02 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1761,7 +1761,17 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+ 	struct smbd_server_connection *sconn = conn->sconn;
+ 
+ 	if (!dirp) {
+-		return NULL;
++		goto fail;
++	}
++
++	if (!fsp->is_directory) {
++		errno = EBADF;
++		goto fail;
++	}
++
++	if (fsp->fh->fd == -1) {
++		errno = EBADF;
++		goto fail;
+ 	}
+ 
+ 	dirp->conn = conn;
+@@ -1778,18 +1788,16 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+ 	}
+ 	talloc_set_destructor(dirp, smb_Dir_destructor);
+ 
+-	if (fsp->is_directory && fsp->fh->fd != -1) {
+-		dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
+-		if (dirp->dir != NULL) {
+-			dirp->fsp = fsp;
+-		} else {
+-			DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
+-				"NULL (%s)\n",
+-				dirp->dir_smb_fname->base_name,
+-				strerror(errno)));
+-			if (errno != ENOSYS) {
+-				return NULL;
+-			}
++	dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
++	if (dirp->dir != NULL) {
++		dirp->fsp = fsp;
++	} else {
++		DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
++			"NULL (%s)\n",
++			dirp->dir_smb_fname->base_name,
++			strerror(errno)));
++		if (errno != ENOSYS) {
++			return NULL;
+ 		}
+ 	}
+ 
+-- 
+2.11.0.483.g087da7b7c-goog
+
+
+From 908b2e1afb7941326ea2073c6af50090c3684e8c Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 19 Dec 2016 12:15:59 -0800
+Subject: [PATCH 05/11] s3: smbd: OpenDir_fsp() - Fix memory leak on error.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/dir.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 12edf80ee02..42e787bed6c 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1797,7 +1797,7 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+ 			dirp->dir_smb_fname->base_name,
+ 			strerror(errno)));
+ 		if (errno != ENOSYS) {
+-			return NULL;
++			goto fail;
+ 		}
+ 	}
+ 
+-- 
+2.11.0.483.g087da7b7c-goog
+
+
+From 7accabaf866922852c58dc32483829803446ad64 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 19 Dec 2016 12:32:07 -0800
+Subject: [PATCH 06/11] s3: smbd: Move the reference counting and destructor
+ setup to just before retuning success.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/dir.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 42e787bed6c..2fd50850665 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1783,11 +1783,6 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+ 		goto fail;
+ 	}
+ 
+-	if (sconn && !sconn->using_smb2) {
+-		sconn->searches.dirhandles_open++;
+-	}
+-	talloc_set_destructor(dirp, smb_Dir_destructor);
+-
+ 	dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
+ 	if (dirp->dir != NULL) {
+ 		dirp->fsp = fsp;
+@@ -1816,6 +1811,11 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+ 		goto fail;
+ 	}
+ 
++	if (sconn && !sconn->using_smb2) {
++		sconn->searches.dirhandles_open++;
++	}
++	talloc_set_destructor(dirp, smb_Dir_destructor);
++
+ 	return dirp;
+ 
+   fail:
+-- 
+2.11.0.483.g087da7b7c-goog
+
+
+From 7a8f9a3634713827d8f75efb4e744eb01e7bd122 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 19 Dec 2016 12:35:32 -0800
+Subject: [PATCH 07/11] s3: smbd: Correctly fallback to open_dir_safely if
+ FDOPENDIR not supported on system.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/dir.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 2fd50850665..1348d12298c 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1797,20 +1797,15 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+ 	}
+ 
+ 	if (dirp->dir == NULL) {
+-		/* FDOPENDIR didn't work. Use OPENDIR instead. */
+-		dirp->dir = SMB_VFS_OPENDIR(conn,
+-					dirp->dir_smb_fname,
++		/* FDOPENDIR is not supported. Use OPENDIR instead. */
++		TALLOC_FREE(dirp);
++		return open_dir_safely(mem_ctx,
++					conn,
++					fsp->fsp_name,
+ 					mask,
+ 					attr);
+ 	}
+ 
+-	if (!dirp->dir) {
+-		DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n",
+-			dirp->dir_smb_fname->base_name,
+-			strerror(errno) ));
+-		goto fail;
+-	}
+-
+ 	if (sconn && !sconn->using_smb2) {
+ 		sconn->searches.dirhandles_open++;
+ 	}
+-- 
+2.11.0.483.g087da7b7c-goog
+
+
+From deb5684e98f0bde36bd288643f41c9555e399406 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Thu, 15 Dec 2016 12:52:13 -0800
+Subject: [PATCH 08/11] s3: smbd: Remove O_NOFOLLOW guards. We insist on
+ O_NOFOLLOW existing.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/open.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/source3/smbd/open.c b/source3/smbd/open.c
+index f0a68c9d75c..9828c9981d5 100644
+--- a/source3/smbd/open.c
++++ b/source3/smbd/open.c
+@@ -366,8 +366,7 @@ NTSTATUS fd_open(struct connection_struct *conn,
+ 	struct smb_filename *smb_fname = fsp->fsp_name;
+ 	NTSTATUS status = NT_STATUS_OK;
+ 
+-#ifdef O_NOFOLLOW
+-	/* 
++	/*
+ 	 * Never follow symlinks on a POSIX client. The
+ 	 * client should be doing this.
+ 	 */
+@@ -375,12 +374,10 @@ NTSTATUS fd_open(struct connection_struct *conn,
+ 	if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) || !lp_follow_symlinks(SNUM(conn))) {
+ 		flags |= O_NOFOLLOW;
+ 	}
+-#endif
+ 
+ 	fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode);
+ 	if (fsp->fh->fd == -1) {
+ 		int posix_errno = errno;
+-#ifdef O_NOFOLLOW
+ #if defined(ENOTSUP) && defined(OSF1)
+ 		/* handle special Tru64 errno */
+ 		if (errno == ENOTSUP) {
+@@ -397,7 +394,6 @@ NTSTATUS fd_open(struct connection_struct *conn,
+ 		if (errno == EMLINK) {
+ 			posix_errno = ELOOP;
+ 		}
+-#endif /* O_NOFOLLOW */
+ 		status = map_nt_error_from_unix(posix_errno);
+ 		if (errno == EMFILE) {
+ 			static time_t last_warned = 0L;
+-- 
+2.11.0.483.g087da7b7c-goog
+
+
+From f6c258802e4bf58722dc089ee10186391b3367c1 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Thu, 15 Dec 2016 12:56:08 -0800
+Subject: [PATCH 09/11] s3: smbd: Move special handling of symlink errno's into
+ a utility function.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/open.c | 43 ++++++++++++++++++++++++++-----------------
+ 1 file changed, 26 insertions(+), 17 deletions(-)
+
+diff --git a/source3/smbd/open.c b/source3/smbd/open.c
+index 9828c9981d5..a72b4836376 100644
+--- a/source3/smbd/open.c
++++ b/source3/smbd/open.c
+@@ -355,6 +355,31 @@ static NTSTATUS check_base_file_access(struct connection_struct *conn,
+ }
+ 
+ /****************************************************************************
++ Handle differing symlink errno's
++****************************************************************************/
++
++static int link_errno_convert(int err)
++{
++#if defined(ENOTSUP) && defined(OSF1)
++	/* handle special Tru64 errno */
++	if (err == ENOTSUP) {
++		err = ELOOP;
++	}
++#endif /* ENOTSUP */
++#ifdef EFTYPE
++	/* fix broken NetBSD errno */
++	if (err == EFTYPE) {
++		err = ELOOP;
++	}
++#endif /* EFTYPE */
++	/* fix broken FreeBSD errno */
++	if (err == EMLINK) {
++		err = ELOOP;
++	}
++	return err;
++}
++
++/****************************************************************************
+  fd support routines - attempt to do a dos_open.
+ ****************************************************************************/
+ 
+@@ -377,23 +402,7 @@ NTSTATUS fd_open(struct connection_struct *conn,
+ 
+ 	fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode);
+ 	if (fsp->fh->fd == -1) {
+-		int posix_errno = errno;
+-#if defined(ENOTSUP) && defined(OSF1)
+-		/* handle special Tru64 errno */
+-		if (errno == ENOTSUP) {
+-			posix_errno = ELOOP;
+-		}
+-#endif /* ENOTSUP */
+-#ifdef EFTYPE
+-		/* fix broken NetBSD errno */
+-		if (errno == EFTYPE) {
+-			posix_errno = ELOOP;
+-		}
+-#endif /* EFTYPE */
+-		/* fix broken FreeBSD errno */
+-		if (errno == EMLINK) {
+-			posix_errno = ELOOP;
+-		}
++		int posix_errno = link_errno_convert(errno);
+ 		status = map_nt_error_from_unix(posix_errno);
+ 		if (errno == EMFILE) {
+ 			static time_t last_warned = 0L;
+-- 
+2.11.0.483.g087da7b7c-goog
+
+
+From c80b0c1320fe68ac4bd0888af97713feecde8b3e Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Thu, 15 Dec 2016 13:04:46 -0800
+Subject: [PATCH 10/11] s3: smbd: Add the core functions to prevent symlink
+ open races.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/open.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 238 insertions(+)
+
+diff --git a/source3/smbd/open.c b/source3/smbd/open.c
+index a72b4836376..d628d0be0d7 100644
+--- a/source3/smbd/open.c
++++ b/source3/smbd/open.c
+@@ -379,6 +379,244 @@ static int link_errno_convert(int err)
+ 	return err;
+ }
+ 
++static int non_widelink_open(struct connection_struct *conn,
++			const char *conn_rootdir,
++			files_struct *fsp,
++			struct smb_filename *smb_fname,
++			int flags,
++			mode_t mode,
++			unsigned int link_depth);
++
++/****************************************************************************
++ Follow a symlink in userspace.
++****************************************************************************/
++
++static int process_symlink_open(struct connection_struct *conn,
++			const char *conn_rootdir,
++			files_struct *fsp,
++			struct smb_filename *smb_fname,
++			int flags,
++			mode_t mode,
++			unsigned int link_depth)
++{
++	int fd = -1;
++	char *link_target = NULL;
++	int link_len = -1;
++	char *oldwd = NULL;
++	size_t rootdir_len = 0;
++	char *resolved_name = NULL;
++	bool matched = false;
++	int saved_errno = 0;
++
++	/*
++	 * Ensure we don't get stuck in a symlink loop.
++	 */
++	link_depth++;
++	if (link_depth >= 20) {
++		errno = ELOOP;
++		goto out;
++	}
++
++	/* Allocate space for the link target. */
++	link_target = talloc_array(talloc_tos(), char, PATH_MAX);
++	if (link_target == NULL) {
++		errno = ENOMEM;
++		goto out;
++	}
++
++	/* Read the link target. */
++	link_len = SMB_VFS_READLINK(conn,
++				smb_fname->base_name,
++				link_target,
++				PATH_MAX - 1);
++	if (link_len == -1) {
++		goto out;
++	}
++
++	/* Ensure it's at least null terminated. */
++	link_target[link_len] = '\0';
++
++	/* Convert to an absolute path. */
++	resolved_name = SMB_VFS_REALPATH(conn, link_target);
++	if (resolved_name == NULL) {
++		goto out;
++	}
++
++	/*
++	 * We know conn_rootdir starts with '/' and
++	 * does not end in '/'. FIXME ! Should we
++	 * smb_assert this ?
++	 */
++	rootdir_len = strlen(conn_rootdir);
++
++	matched = (strncmp(conn_rootdir, resolved_name, rootdir_len) == 0);
++	if (!matched) {
++		errno = EACCES;
++		goto out;
++	}
++
++	/*
++	 * Turn into a path relative to the share root.
++	 */
++	if (resolved_name[rootdir_len] == '\0') {
++		/* Link to the root of the share. */
++		smb_fname->base_name = talloc_strdup(talloc_tos(), ".");
++		if (smb_fname->base_name == NULL) {
++			errno = ENOMEM;
++			goto out;
++		}
++	} else if (resolved_name[rootdir_len] == '/') {
++		smb_fname->base_name = &resolved_name[rootdir_len+1];
++	} else {
++		errno = EACCES;
++		goto out;
++	}
++
++	oldwd = vfs_GetWd(talloc_tos(), conn);
++	if (oldwd == NULL) {
++		goto out;
++	}
++
++	/* Ensure we operate from the root of the share. */
++	if (vfs_ChDir(conn, conn_rootdir) == -1) {
++		goto out;
++	}
++
++	/* And do it all again.. */
++	fd = non_widelink_open(conn,
++				conn_rootdir,
++				fsp,
++				smb_fname,
++				flags,
++				mode,
++				link_depth);
++	if (fd == -1) {
++		saved_errno = errno;
++	}
++
++  out:
++
++	SAFE_FREE(resolved_name);
++	TALLOC_FREE(link_target);
++	if (oldwd != NULL) {
++		int ret = vfs_ChDir(conn, oldwd);
++		if (ret == -1) {
++			smb_panic("unable to get back to old directory\n");
++		}
++		TALLOC_FREE(oldwd);
++	}
++	if (saved_errno != 0) {
++		errno = saved_errno;
++	}
++	return fd;
++}
++
++/****************************************************************************
++ Non-widelink open.
++****************************************************************************/
++
++static int non_widelink_open(struct connection_struct *conn,
++			const char *conn_rootdir,
++			files_struct *fsp,
++			struct smb_filename *smb_fname,
++			int flags,
++			mode_t mode,
++			unsigned int link_depth)
++{
++	NTSTATUS status;
++	int fd = -1;
++	struct smb_filename *smb_fname_rel = NULL;
++	int saved_errno = 0;
++	char *oldwd = NULL;
++	char *parent_dir = NULL;
++	const char *final_component = NULL;
++
++	if (!parent_dirname(talloc_tos(),
++			smb_fname->base_name,
++			&parent_dir,
++			&final_component)) {
++		goto out;
++	}
++
++	oldwd = vfs_GetWd(talloc_tos(), conn);
++	if (oldwd == NULL) {
++		goto out;
++	}
++
++	/* Pin parent directory in place. */
++	if (vfs_ChDir(conn, parent_dir) == -1) {
++		goto out;
++	}
++
++	/* Ensure the relative path is below the share. */
++	status = check_reduced_name(conn, final_component);
++	if (!NT_STATUS_IS_OK(status)) {
++		saved_errno = map_errno_from_nt_status(status);
++		goto out;
++	}
++
++	smb_fname_rel = synthetic_smb_fname(talloc_tos(),
++				final_component,
++				smb_fname->stream_name,
++				&smb_fname->st,
++				smb_fname->flags);
++
++	flags |= O_NOFOLLOW;
++
++	{
++		struct smb_filename *tmp_name = fsp->fsp_name;
++		fsp->fsp_name = smb_fname_rel;
++		fd = SMB_VFS_OPEN(conn, smb_fname_rel, fsp, flags, mode);
++		fsp->fsp_name = tmp_name;
++	}
++
++	if (fd == -1) {
++		saved_errno = link_errno_convert(errno);
++		if (saved_errno == ELOOP) {
++			if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
++				/* Never follow symlinks on posix open. */
++				goto out;
++			}
++			if (!lp_follow_symlinks(SNUM(conn))) {
++				/* Explicitly no symlinks. */
++				goto out;
++			}
++			/*
++			 * We have a symlink. Follow in userspace
++			 * to ensure it's under the share definition.
++			 */
++			fd = process_symlink_open(conn,
++					conn_rootdir,
++					fsp,
++					smb_fname_rel,
++					flags,
++					mode,
++					link_depth);
++			if (fd == -1) {
++				saved_errno =
++					link_errno_convert(errno);
++			}
++		}
++	}
++
++  out:
++
++	TALLOC_FREE(parent_dir);
++	TALLOC_FREE(smb_fname_rel);
++
++	if (oldwd != NULL) {
++		int ret = vfs_ChDir(conn, oldwd);
++		if (ret == -1) {
++			smb_panic("unable to get back to old directory\n");
++		}
++		TALLOC_FREE(oldwd);
++	}
++	if (saved_errno != 0) {
++		errno = saved_errno;
++	}
++	return fd;
++}
++
+ /****************************************************************************
+  fd support routines - attempt to do a dos_open.
+ ****************************************************************************/
+-- 
+2.11.0.483.g087da7b7c-goog
+
+
+From cf5b572ff620231732acfc1fab8c4459f7887229 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Thu, 15 Dec 2016 13:06:31 -0800
+Subject: [PATCH 11/11] s3: smbd: Use the new non_widelink_open() function.
+
+CVE-2017-2619
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/open.c | 23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/source3/smbd/open.c b/source3/smbd/open.c
+index d628d0be0d7..006be91f09e 100644
+--- a/source3/smbd/open.c
++++ b/source3/smbd/open.c
+@@ -638,7 +638,28 @@ NTSTATUS fd_open(struct connection_struct *conn,
+ 		flags |= O_NOFOLLOW;
+ 	}
+ 
+-	fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode);
++	/* Ensure path is below share definition. */
++	if (!lp_widelinks(SNUM(conn))) {
++		const char *conn_rootdir = SMB_VFS_CONNECTPATH(conn,
++						smb_fname->base_name);
++		if (conn_rootdir == NULL) {
++			return NT_STATUS_NO_MEMORY;
++		}
++		/*
++		 * Only follow symlinks within a share
++		 * definition.
++		 */
++		fsp->fh->fd = non_widelink_open(conn,
++					conn_rootdir,
++					fsp,
++					smb_fname,
++					flags,
++					mode,
++					0);
++	} else {
++		fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode);
++	}
++
+ 	if (fsp->fh->fd == -1) {
+ 		int posix_errno = link_errno_convert(errno);
+ 		status = map_nt_error_from_unix(posix_errno);
+-- 
+2.11.0.483.g087da7b7c-goog
+
diff --git a/debian/patches/series b/debian/patches/series
index 3788884..4a5dc45 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -15,3 +15,4 @@ systemd-syslog.target-is-obsolete.patch
 Add-documentation-to-systemd-Unit-files.patch
 fix_kill_path_in_units.patch
 nmbd-requires-a-working-network.patch
+CVE-2017-2619.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-samba/samba.git




More information about the Pkg-samba-maint mailing list