[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