[Pkg-samba-maint] [samba] 03/03: Imported Debian patch 2:3.6.6-6+deb7u12

Roberto C. Sanchez roberto at moszumanska.debian.org
Sat May 20 20:32:00 UTC 2017


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

roberto pushed a commit to branch wheezy
in repository samba.

commit 762a3afd8eb45526e44cd0b2ae8a5b1a058ec647
Author: Roberto C. Sanchez <roberto at debian.org>
Date:   Fri Mar 31 17:58:52 2017 -0400

    Imported Debian patch 2:3.6.6-6+deb7u12
---
 debian/changelog                                   |   48 +
 debian/patches/CVE-2017-2619-prerequisites.patch   |  270 +++++
 .../patches/CVE-2017-2619-race-condition-fix.patch | 1150 ++++++++++++++++++++
 .../CVE-2017-2619-regression-bug-12721-fix.patch   |  179 +++
 debian/patches/CVE-2017-2619-tests.patch           |  296 +++++
 debian/patches/series                              |    4 +
 6 files changed, 1947 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index b9b8b2e..db54c6b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,51 @@
+samba (2:3.6.6-6+deb7u12) wheezy-security; urgency=high
+
+  * Non-maintainer upload by the LTS Team.
+    - CVE-2017-2619: symlink race permits opening files outside share directory
+  * Cherry-pick the following upstream changes required for CVE-2017-2619:
+    - s3: smbd: Maintain a back-pointer to the fsp in struct smb_Dir.
+    - s3: vfs: Change vfs_dirsort.c from MALLOC -> TALLOC.
+    - s3: vfs: Protect against early error in SMB_VFS_NEXT_READDIR.
+    - s3: vfs: Use an index i rather than re-using a state variable.
+    - s3: vfs: Protect open_and_sort_dir() from the directory changing size.
+    - s3: vfs: Clean error paths in opendir and fd_opendir.
+    - s3: vfs: Check SMB_VFS_NEXT_OPENDIR return in dirsort_opendir().
+    - s3: vfs: Convert mtime from a time_t to a struct timespec.
+    - s3: vfs: Remove the use of dirfd inside the vfs_dirsort.c.
+  * CVE-2017-2619 requires the following changes:
+    - s3: smbd: re-open directory after dptr_CloseDir()
+    - s3: vfs: dirsort doesn't handle opendir of "." correctly.
+    - s3: VFS: vfs_streams_xattr.c: Make streams_xattr_open() store the same
+      path as streams_xattr_recheck().
+    - vfs_streams_xattr: use fsp, not base_fsp
+    - s3: smbd: Create wrapper function for OpenDir in preparation for making
+      robust.
+    - s3: smbd: Opendir_internal() early return if SMB_VFS_OPENDIR failed.
+    - s3: smbd: Create and use open_dir_safely(). Use from OpenDir().
+    - s3: smbd: OpenDir_fsp() use early returns.
+    - s3: smbd: OpenDir_fsp() - Fix memory leak on error.
+    - s3: smbd: Move the reference counting and destructor setup to just before
+      retuning success.
+    - s3: smbd: Correctly fallback to open_dir_safely if FDOPENDIR not supported
+      on system.
+    - s3: smbd: Remove O_NOFOLLOW guards. We insist on O_NOFOLLOW existing.
+    - s3: smbd: Move special handling of symlink errno's into a utility
+      function.
+    - s3: smbd: Add the core functions to prevent symlink open races.
+    - s3: smbd: Use the new non_widelink_open() function.
+  * The initial CVE-2017-2619 fix caused a regression when the configuration
+    option "follow symlink = no" was set, requiring these changes:
+    - s3: smbd: Fix incorrect logic exposed by fix for the security bug 12496
+      (CVE-2017-2619).
+    - s3: smbd: Fix "follow symlink = no" regression part 2.
+    - s3: smbd: Fix "follow symlink = no" regression part 2.
+  * The regression fix was accompanied by these unit test changes/updates:
+    - s3: Test for CVE-2017-2619 regression with "follow symlinks = no".
+    - s3: Fixup test for CVE-2017-2619 regression with "follow symlinks = no"
+    - s3: Test for CVE-2017-2619 regression with "follow symlinks = no" - part 2
+
+ -- Roberto C. Sanchez <roberto at debian.org>  Fri, 31 Mar 2017 17:58:52 -0400
+
 samba (2:3.6.6-6+deb7u11) wheezy-security; urgency=medium
 
   * Non-maintainer upload by the LTS Team.
diff --git a/debian/patches/CVE-2017-2619-prerequisites.patch b/debian/patches/CVE-2017-2619-prerequisites.patch
new file mode 100644
index 0000000..0fa8bf3
--- /dev/null
+++ b/debian/patches/CVE-2017-2619-prerequisites.patch
@@ -0,0 +1,270 @@
+Description: This patch is a consolidation of several commits (8234c6a, 629e302, 0a3b024, bc3714f, d302cb6, 94f7d0c, 33ead72, 66ee839, 77cacee) cherry-picked from Samba's upstream Git repository (v3-6-stable branch) because they contain changes which are dependencies of the CVE-2017-2619 patch (which upstream based upon version 3.6.25); this was done in lieu of upgrading wheezy from Samba 3.6.6 to 3.6.25
+origin: upstream , https://git.samba.org/?p=samba.git;a=commitdiff;h=8234c6a , https://git.samba.org/?p=samba.git;a=commitdiff;h=629e302 , https://git.samba.org/?p=samba.git;a=commitdiff;h=0a3b024 , https://git.samba.org/?p=samba.git;a=commitdiff;h=bc3714f , https://git.samba.org/?p=samba.git;a=commitdiff;h=d302cb6 , https://git.samba.org/?p=samba.git;a=commitdiff;h=94f7d0c , https://git.samba.org/?p=samba.git;a=commitdiff;h=33ead72 , https://git.samba.org/?p=samba.git;a=commitdiff;h=66e [...]
+
+--- samba-3.6.6.orig/source3/smbd/dir.c
++++ samba-3.6.6/source3/smbd/dir.c
+@@ -50,6 +50,8 @@
+ 	struct name_cache_entry *name_cache;
+ 	unsigned int name_cache_index;
+ 	unsigned int file_number;
++	files_struct *fsp; /* Back pointer to containing fsp, only
++			      set from OpenDir_fsp(). */
+ };
+ 
+ struct dptr_struct {
+@@ -1428,7 +1430,9 @@
+ 
+ 	if (fsp->is_directory && fsp->fh->fd != -1) {
+ 		dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
+-		if (dirp->dir == NULL) {
++		if (dirp->dir != NULL) {
++			dirp->fsp = fsp;
++		} else {
+ 			DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
+ 				"NULL (%s)\n",
+ 				dirp->dir_path,
+--- samba-3.6.6.orig/source3/modules/vfs_dirsort.c
++++ samba-3.6.6/source3/modules/vfs_dirsort.c
+@@ -30,40 +30,60 @@
+ struct dirsort_privates {
+ 	long pos;
+ 	SMB_STRUCT_DIRENT *directory_list;
+-	long number_of_entries;
+-	time_t mtime;
++	unsigned int number_of_entries;
++	struct timespec mtime;
+ 	SMB_STRUCT_DIR *source_directory;
+-	int fd;
++	files_struct *fsp; /* If open via FDOPENDIR. */
++	struct smb_filename *smb_fname; /* If open via OPENDIR */
+ };
+ 
+ static void free_dirsort_privates(void **datap) {
+-	struct dirsort_privates *data = (struct dirsort_privates *) *datap;
+-	SAFE_FREE(data->directory_list);
+-	SAFE_FREE(data);
+-	*datap = NULL;
+-
+-	return;
++	TALLOC_FREE(*datap);
+ }
+ 
+-static bool open_and_sort_dir (vfs_handle_struct *handle)
++static bool get_sorted_dir_mtime(vfs_handle_struct *handle,
++				struct dirsort_privates *data,
++				struct timespec *ret_mtime)
+ {
+-	SMB_STRUCT_DIRENT *dp;
+-	struct stat dir_stat;
+-	long current_pos;
+-	struct dirsort_privates *data = NULL;
++	int ret;
++	struct timespec mtime;
+ 
+-	SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates,
+-				return false);
++	if (data->fsp) {
++		ret = fsp_stat(data->fsp);
++		mtime = data->fsp->fsp_name->st.st_ex_mtime;
++	} else {
++		ret = SMB_VFS_STAT(handle->conn, data->smb_fname);
++		mtime = data->smb_fname->st.st_ex_mtime;
++	}
++
++	if (ret == -1) {
++		return false;
++	}
++
++	*ret_mtime = mtime;
++
++	return true;
++}
++
++static bool open_and_sort_dir(vfs_handle_struct *handle,
++				struct dirsort_privates *data)
++{
++	unsigned int i = 0;
++	unsigned int total_count = 0;
+ 
+ 	data->number_of_entries = 0;
+ 
+-	if (fstat(data->fd, &dir_stat) == 0) {
+-		data->mtime = dir_stat.st_mtime;
++	if (get_sorted_dir_mtime(handle, data, &data->mtime) == false) {
++		return false;
+ 	}
+ 
+ 	while (SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL)
+ 	       != NULL) {
+-		data->number_of_entries++;
++		total_count++;
++	}
++
++	if (total_count == 0) {
++		return false;
+ 	}
+ 
+ 	/* Open the underlying directory and count the number of entries
+@@ -71,21 +91,26 @@
+ 	SMB_VFS_NEXT_REWINDDIR(handle, data->source_directory);
+ 
+ 	/* Set up an array and read the directory entries into it */
+-	SAFE_FREE(data->directory_list); /* destroy previous cache if needed */
+-	data->directory_list = (SMB_STRUCT_DIRENT *)SMB_MALLOC(
+-		data->number_of_entries * sizeof(SMB_STRUCT_DIRENT));
++	TALLOC_FREE(data->directory_list); /* destroy previous cache if needed */
++	data->directory_list = talloc_zero_array(data,
++						 SMB_STRUCT_DIRENT,
++						 total_count);
+ 	if (!data->directory_list) {
+ 		return false;
+ 	}
+-	current_pos = data->pos;
+-	data->pos = 0;
+-	while ((dp = SMB_VFS_NEXT_READDIR(handle, data->source_directory,
+-					  NULL)) != NULL) {
+-		data->directory_list[data->pos++] = *dp;
++	for (i = 0; i < total_count; i++) {
++		SMB_STRUCT_DIRENT *dp = SMB_VFS_NEXT_READDIR(handle,
++						data->source_directory,
++						NULL);
++		if (dp == NULL) {
++			break;
++		}
++		data->directory_list[i] = *dp;
+ 	}
+ 
++	data->number_of_entries = i;
++
+ 	/* Sort the directory entries by name */
+-	data->pos = current_pos;
+ 	TYPESAFE_QSORT(data->directory_list, data->number_of_entries, compare_dirent);
+ 	return true;
+ }
+@@ -94,12 +119,11 @@
+ 				       const char *fname, const char *mask,
+ 				       uint32 attr)
+ {
++	NTSTATUS status;
+ 	struct dirsort_privates *data = NULL;
+ 
+ 	/* set up our private data about this directory */
+-	data = (struct dirsort_privates *)SMB_MALLOC(
+-		sizeof(struct dirsort_privates));
+-
++	data = talloc_zero(handle->conn, struct dirsort_privates);
+ 	if (!data) {
+ 		return NULL;
+ 	}
+@@ -107,20 +131,34 @@
+ 	data->directory_list = NULL;
+ 	data->pos = 0;
+ 
++	status = create_synthetic_smb_fname(data,
++					fname,
++					NULL,
++					NULL,
++					&data->smb_fname);
++	if (!NT_STATUS_IS_OK(status)) {
++		TALLOC_FREE(data);
++		return NULL;
++	}
++
+ 	/* Open the underlying directory and count the number of entries */
+ 	data->source_directory = SMB_VFS_NEXT_OPENDIR(handle, fname, mask,
+ 						      attr);
+ 
+-	data->fd = dirfd(data->source_directory);
+-
+-	SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates,
+-				struct dirsort_privates, return NULL);
++	if (data->source_directory == NULL) {
++		TALLOC_FREE(data);
++		return NULL;
++	}
+ 
+-	if (!open_and_sort_dir(handle)) {
++	if (!open_and_sort_dir(handle, data)) {
+ 		SMB_VFS_NEXT_CLOSEDIR(handle,data->source_directory);
++		TALLOC_FREE(data);
+ 		return NULL;
+ 	}
+ 
++	SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates,
++				struct dirsort_privates, return NULL);
++
+ 	return data->source_directory;
+ }
+ 
+@@ -132,37 +170,35 @@
+ 	struct dirsort_privates *data = NULL;
+ 
+ 	/* set up our private data about this directory */
+-	data = (struct dirsort_privates *)SMB_MALLOC(
+-		sizeof(struct dirsort_privates));
+-
++	data = talloc_zero(handle->conn, struct dirsort_privates);
+ 	if (!data) {
+ 		return NULL;
+ 	}
+ 
+ 	data->directory_list = NULL;
+ 	data->pos = 0;
++	data->fsp = fsp;
+ 
+ 	/* Open the underlying directory and count the number of entries */
+ 	data->source_directory = SMB_VFS_NEXT_FDOPENDIR(handle, fsp, mask,
+ 						      attr);
+ 
+ 	if (data->source_directory == NULL) {
+-		SAFE_FREE(data);
++		TALLOC_FREE(data);
+ 		return NULL;
+ 	}
+ 
+-	data->fd = dirfd(data->source_directory);
+-
+-	SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates,
+-				struct dirsort_privates, return NULL);
+-
+-	if (!open_and_sort_dir(handle)) {
++	if (!open_and_sort_dir(handle, data)) {
+ 		SMB_VFS_NEXT_CLOSEDIR(handle,data->source_directory);
++		TALLOC_FREE(data);
+ 		/* fd is now closed. */
+ 		fsp->fh->fd = -1;
+ 		return NULL;
+ 	}
+ 
++	SMB_VFS_HANDLE_SET_DATA(handle, data, free_dirsort_privates,
++				struct dirsort_privates, return NULL);
++
+ 	return data->source_directory;
+ }
+ 
+@@ -171,21 +207,18 @@
+ 					  SMB_STRUCT_STAT *sbuf)
+ {
+ 	struct dirsort_privates *data = NULL;
+-	time_t current_mtime;
+-	struct stat dir_stat;
++	struct timespec current_mtime;
+ 
+ 	SMB_VFS_HANDLE_GET_DATA(handle, data, struct dirsort_privates,
+ 				return NULL);
+ 
+-	if (fstat(data->fd, &dir_stat) == -1) {
++	if (get_sorted_dir_mtime(handle, data, &current_mtime) == false) {
+ 		return NULL;
+ 	}
+ 
+-	current_mtime = dir_stat.st_mtime;
+-
+ 	/* throw away cache and re-read the directory if we've changed */
+-	if (current_mtime > data->mtime) {
+-		open_and_sort_dir(handle);
++	if (timespec_compare(&current_mtime, &data->mtime) > 1) {
++		open_and_sort_dir(handle, data);
+ 	}
+ 
+ 	if (data->pos >= data->number_of_entries) {
diff --git a/debian/patches/CVE-2017-2619-race-condition-fix.patch b/debian/patches/CVE-2017-2619-race-condition-fix.patch
new file mode 100644
index 0000000..a96d6be
--- /dev/null
+++ b/debian/patches/CVE-2017-2619-race-condition-fix.patch
@@ -0,0 +1,1150 @@
+Description: This patch is a consolidation of several patches described by the Git commit summaries below
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-2619
+bug: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+From ec1bca1d5315549e945c93cbf5e3abdb695de782 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 20 Mar 2017 11:32:19 -0700
+Subject: [PATCH 01/15] CVE-2017-2619: s3/smbd: re-open directory after
+ dptr_CloseDir()
+
+dptr_CloseDir() will close and invalidate the fsp's file descriptor, we
+have to reopen it.
+
+Bug: https://bugzilla.samba.org/show_bug.cgi?id=12496
+
+Signed-off-by: Ralph Bohme <slow at samba.org>
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/smbd/open.c      |  2 +-
+ source3/smbd/proto.h     |  2 ++
+ source3/smbd/smb2_find.c | 17 +++++++++++++++++
+ 3 files changed, 20 insertions(+), 1 deletion(-)
+
+From 2bb9a3d35f6a0cc43a30638594969c4860ffd5a5 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Tue, 28 Feb 2017 09:24:07 -0800
+Subject: [PATCH 02/15] s3: vfs: dirsort doesn't handle opendir of "."
+ correctly.
+
+Needs to store $cwd path for correct sorting.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12499
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/modules/vfs_dirsort.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+From 327d09ba641046f68daa5b2bb98f09530294cb0d Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 13 Mar 2017 13:44:42 -0700
+Subject: [PATCH 03/15] s3: VFS: vfs_streams_xattr.c: Make streams_xattr_open()
+ store the same path as streams_xattr_recheck().
+
+If the open is changing directories, fsp->fsp_name->base_name
+will be the full path from the share root, whilst
+smb_fname will be relative to the $cwd.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12546
+
+Back-ported from a24ba3e4083200ec9885363efc5769f43183fb6b
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/modules/vfs_streams_xattr.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+From 27871d3bfb0857ad3306aabdce6f9b55e32fff3d Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 13 Mar 2017 13:54:04 -0700
+Subject: [PATCH 04/15] vfs_streams_xattr: use fsp, not base_fsp
+
+The base_fsp's fd is always -1 as it's closed after being openend in
+create_file_unixpath().
+
+Additionally in streams_xattr_open force using of SMB_VFS_FSETXATTR() by
+sticking the just created fd into the fsp (and removing it afterwards).
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12591
+
+Back-ported from 021189e32ba507832b5e821e5cda8a2889225955.
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+---
+ source3/modules/vfs_streams_xattr.c | 205 +++++++++++++++++-------------------
+ 1 file changed, 99 insertions(+), 106 deletions(-)
+
+From a419b277c5994459c956ebdd324679e728ebae10 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 05/15] 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(-)
+
+From e47e3c40b5fc8f52fe70c3e1edf5489ac8b4badf 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 06/15] 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 | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+From 45e41b709b6c2e67acb99f29aa05b61b53091e57 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 07/15] 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 | 66 ++++++++++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 59 insertions(+), 7 deletions(-)
+
+From 720abcec65b04fdac1052a14898180c8cc816464 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 08/15] 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(-)
+
+From 5070f319bbb7dda87766621a83691910414d06a1 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 09/15] 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(-)
+
+From 65d37759f8b4979bc0c0833e0a5eecd277dfa604 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 10/15] 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(-)
+
+From 5a821d791aba90643ddf7a3c29dad4f6621ef185 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 11/15] 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, 7 insertions(+), 8 deletions(-)
+
+From 597aa3b99a2790133a4839260607b0a8df41c8e3 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 12/15] 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 | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+From 563af2ffec05a2c0b54897e2d28ac7e1adb66e0f 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 13/15] 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 | 30 ++++++++++++++++++++++++++++--
+ 1 file changed, 28 insertions(+), 2 deletions(-)
+
+From b34a67cd3a996804ba7bf90e86cf9e22edf60eb3 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 14/15] 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 | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 242 insertions(+)
+
+From 5920309d2f62dd24fc50530c92dd68077f96a6d2 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 15/15] 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(-)
+
+
+--- samba-3.6.6.orig/source3/smbd/open.c
++++ samba-3.6.6/source3/smbd/open.c
+@@ -187,10 +187,277 @@
+ }
+ 
+ /****************************************************************************
++ 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;
++}
++
++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;
++	}
++
++	status = create_synthetic_smb_fname(talloc_tos(),
++				final_component,
++				smb_fname->stream_name,
++				&smb_fname->st,
++				&smb_fname_rel);
++	if (!NT_STATUS_IS_OK(status)) {
++		saved_errno = map_errno_from_nt_status(status);
++		goto out;
++	}
++
++	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_open) {
++				/* Never follow symlinks on posix open. */
++				goto out;
++			}
++			if (!lp_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.
+ ****************************************************************************/
+ 
+-static NTSTATUS fd_open(struct connection_struct *conn,
++NTSTATUS fd_open(struct connection_struct *conn,
+ 		    files_struct *fsp,
+ 		    int flags,
+ 		    mode_t mode)
+@@ -198,8 +465,7 @@
+ 	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.
+ 	 */
+@@ -207,12 +473,33 @@
+ 	if (fsp->posix_open || !lp_symlinks(SNUM(conn))) {
+ 		flags |= O_NOFOLLOW;
+ 	}
+-#endif
+ 
+-	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) {
+-		status = map_nt_error_from_unix(errno);
+-		if (errno == EMFILE) {
++		int posix_errno = link_errno_convert(errno);
++		status = map_nt_error_from_unix(posix_errno);
++		if (posix_errno == EMFILE) {
+ 			static time_t last_warned = 0L;
+ 
+ 			if (time((time_t *) NULL) > last_warned) {
+--- samba-3.6.6.orig/source3/smbd/proto.h
++++ samba-3.6.6/source3/smbd/proto.h
+@@ -592,6 +592,8 @@
+ 				const struct security_token *token,
+ 				uint32_t access_desired,
+ 				uint32_t *access_granted);
++NTSTATUS fd_open(struct connection_struct *conn, files_struct *fsp,
++		int flags, mode_t mode);
+ NTSTATUS fd_close(files_struct *fsp);
+ void change_file_owner_to_parent(connection_struct *conn,
+ 				 const char *inherit_from_dir,
+--- samba-3.6.6.orig/source3/smbd/smb2_find.c
++++ samba-3.6.6/source3/smbd/smb2_find.c
+@@ -24,6 +24,7 @@
+ #include "../libcli/smb/smb_common.h"
+ #include "trans2.h"
+ #include "../lib/util/tevent_ntstatus.h"
++#include "system/filesys.h"
+ 
+ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
+ 					      struct tevent_context *ev,
+@@ -300,7 +301,23 @@
+ 	}
+ 
+ 	if (in_flags & SMB2_CONTINUE_FLAG_REOPEN) {
++		int flags;
++
+ 		dptr_CloseDir(fsp);
++
++		/*
++		 * dptr_CloseDir() will close and invalidate the fsp's file
++		 * descriptor, we have to reopen it.
++		 */
++
++		flags = O_RDONLY;
++#ifdef O_DIRECTORY
++		flags |= O_DIRECTORY;
++#endif
++		status = fd_open(conn, fsp, flags, 0);
++		if (tevent_req_nterror(req, status)) {
++			return tevent_req_post(req, ev);
++		}
+ 	}
+ 
+ 	if (fsp->dptr == NULL) {
+--- samba-3.6.6.orig/source3/modules/vfs_dirsort.c
++++ samba-3.6.6/source3/modules/vfs_dirsort.c
+@@ -141,6 +141,10 @@
+ 		return NULL;
+ 	}
+ 
++	if (ISDOT(data->smb_fname->base_name)) {
++		data->smb_fname->base_name = vfs_GetWd(data, handle->conn);
++	}
++
+ 	/* Open the underlying directory and count the number of entries */
+ 	data->source_directory = SMB_VFS_NEXT_OPENDIR(handle, fname, mask,
+ 						      attr);
+--- samba-3.6.6.orig/source3/modules/vfs_streams_xattr.c
++++ samba-3.6.6/source3/modules/vfs_streams_xattr.c
+@@ -229,7 +229,7 @@
+ 		return -1;
+ 	}
+ 
+-	sbuf->st_ex_size = get_xattr_size(handle->conn, fsp->base_fsp,
++	sbuf->st_ex_size = get_xattr_size(handle->conn, fsp,
+ 					io->base, io->xattr_name);
+ 	if (sbuf->st_ex_size == -1) {
+ 		return -1;
+@@ -364,6 +364,7 @@
+ 	char *xattr_name = NULL;
+ 	int baseflags;
+ 	int hostfd = -1;
++	int ret;
+ 
+ 	DEBUG(10, ("streams_xattr_open called for %s\n",
+ 		   smb_fname_str_dbg(smb_fname)));
+@@ -375,133 +376,125 @@
+ 	/* If the default stream is requested, just open the base file. */
+ 	if (is_ntfs_default_stream_smb_fname(smb_fname)) {
+ 		char *tmp_stream_name;
+-		int ret;
+ 
+ 		tmp_stream_name = smb_fname->stream_name;
+ 		smb_fname->stream_name = NULL;
+ 
+ 		ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+ 
+-		smb_fname->stream_name = tmp_stream_name;
+-
+-		return ret;
+-	}
++			smb_fname->stream_name = tmp_stream_name;
+ 
+-	status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name,
+-					&xattr_name);
+-	if (!NT_STATUS_IS_OK(status)) {
+-		errno = map_errno_from_nt_status(status);
+-		goto fail;
+-	}
++			return ret;
++		}
+ 
+-	/* Create an smb_filename with stream_name == NULL. */
+-	status = create_synthetic_smb_fname(talloc_tos(),
+-					    smb_fname->base_name,
+-					    NULL, NULL,
+-					    &smb_fname_base);
+-	if (!NT_STATUS_IS_OK(status)) {
+-		errno = map_errno_from_nt_status(status);
+-		goto fail;
+-	}
++		status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name,
++						&xattr_name);
++		if (!NT_STATUS_IS_OK(status)) {
++			errno = map_errno_from_nt_status(status);
++			goto fail;
++		}
+ 
+-	/*
+-	 * We use baseflags to turn off nasty side-effects when opening the
+-	 * underlying file.
+-         */
+-        baseflags = flags;
+-        baseflags &= ~O_TRUNC;
+-        baseflags &= ~O_EXCL;
+-        baseflags &= ~O_CREAT;
+-
+-        hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp,
+-			      baseflags, mode);
+-
+-	TALLOC_FREE(smb_fname_base);
+-
+-        /* It is legit to open a stream on a directory, but the base
+-         * fd has to be read-only.
+-         */
+-        if ((hostfd == -1) && (errno == EISDIR)) {
+-                baseflags &= ~O_ACCMODE;
+-                baseflags |= O_RDONLY;
+-                hostfd = SMB_VFS_OPEN(handle->conn, smb_fname, fsp, baseflags,
+-				      mode);
+-        }
++		/* Create an smb_filename with stream_name == NULL. */
++		status = create_synthetic_smb_fname(talloc_tos(),
++						    smb_fname->base_name,
++						    NULL, NULL,
++						    &smb_fname_base);
++		if (!NT_STATUS_IS_OK(status)) {
++			errno = map_errno_from_nt_status(status);
++			goto fail;
++		}
+ 
+-        if (hostfd == -1) {
+-		goto fail;
+-        }
++		/*
++		 * We use baseflags to turn off nasty side-effects when opening the
++		 * underlying file.
++		 */
++		baseflags = flags;
++		baseflags &= ~O_TRUNC;
++		baseflags &= ~O_EXCL;
++		baseflags &= ~O_CREAT;
+ 
+-	status = get_ea_value(talloc_tos(), handle->conn, NULL,
+-			      smb_fname->base_name, xattr_name, &ea);
++		hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp,
++				      baseflags, mode);
+ 
+-	DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status)));
++		TALLOC_FREE(smb_fname_base);
+ 
+-	if (!NT_STATUS_IS_OK(status)
+-	    && !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+-		/*
+-		 * The base file is not there. This is an error even if we got
+-		 * O_CREAT, the higher levels should have created the base
+-		 * file for us.
++		/* It is legit to open a stream on a directory, but the base
++		 * fd has to be read-only.
+ 		 */
+-		DEBUG(10, ("streams_xattr_open: base file %s not around, "
+-			   "returning ENOENT\n", smb_fname->base_name));
+-		errno = ENOENT;
+-		goto fail;
+-	}
++		if ((hostfd == -1) && (errno == EISDIR)) {
++			baseflags &= ~O_ACCMODE;
++			baseflags |= O_RDONLY;
++			hostfd = SMB_VFS_OPEN(handle->conn, smb_fname, fsp, baseflags,
++					      mode);
++		}
+ 
+-	if (!NT_STATUS_IS_OK(status)) {
+-		/*
+-		 * The attribute does not exist
+-		 */
++		if (hostfd == -1) {
++			goto fail;
++		}
++
++		status = get_ea_value(talloc_tos(), handle->conn, NULL,
++				      smb_fname->base_name, xattr_name, &ea);
+ 
+-                if (flags & O_CREAT) {
++		DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status)));
++
++		if (!NT_STATUS_IS_OK(status)
++		    && !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ 			/*
+-			 * Darn, xattrs need at least 1 byte
++			 * The base file is not there. This is an error even if we got
++			 * O_CREAT, the higher levels should have created the base
++			 * file for us.
+ 			 */
+-                        char null = '\0';
++			DEBUG(10, ("streams_xattr_open: base file %s not around, "
++				   "returning ENOENT\n", smb_fname->base_name));
++			errno = ENOENT;
++			goto fail;
++		}
+ 
+-			DEBUG(10, ("creating attribute %s on file %s\n",
+-				   xattr_name, smb_fname->base_name));
++		if (!NT_STATUS_IS_OK(status)) {
++			/*
++			 * The attribute does not exist
++			 */
+ 
++			if (flags & O_CREAT) {
++				/*
++				 * Darn, xattrs need at least 1 byte
++				 */
++				char null = '\0';
++
++				DEBUG(10, ("creating attribute %s on file %s\n",
++					   xattr_name, smb_fname->base_name));
++
++				fsp->fh->fd = hostfd;
++				ret = SMB_VFS_FSETXATTR(fsp, xattr_name,
++						&null, sizeof(null),
++						flags & O_EXCL ? XATTR_CREATE : 0);
++				fsp->fh->fd = -1;
++				if (ret != 0) {
++					goto fail;
++				}
++			}
++		}
++
++		if (flags & O_TRUNC) {
++			char null = '\0';
+ 			if (fsp->base_fsp->fh->fd != -1) {
+-                        	if (SMB_VFS_FSETXATTR(
+-					fsp->base_fsp, xattr_name,
+-					&null, sizeof(null),
+-					flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
++				if (SMB_VFS_FSETXATTR(
++						fsp->base_fsp, xattr_name,
++						&null, sizeof(null),
++						flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
+ 					goto fail;
+ 				}
+ 			} else {
+-	                        if (SMB_VFS_SETXATTR(
+-					handle->conn, smb_fname->base_name,
+-					xattr_name, &null, sizeof(null),
+-					flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
++				if (SMB_VFS_SETXATTR(
++						handle->conn, smb_fname->base_name,
++						xattr_name, &null, sizeof(null),
++						flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
+ 					goto fail;
+ 				}
+ 			}
+ 		}
+-	}
+-
+-	if (flags & O_TRUNC) {
+-		char null = '\0';
+-		if (fsp->base_fsp->fh->fd != -1) {
+-			if (SMB_VFS_FSETXATTR(
+-					fsp->base_fsp, xattr_name,
+-					&null, sizeof(null),
+-					flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
+-				goto fail;
+-			}
+-		} else {
+-			if (SMB_VFS_SETXATTR(
+-					handle->conn, smb_fname->base_name,
+-					xattr_name, &null, sizeof(null),
+-					flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
+-				goto fail;
+-			}
+-		}
+-	}
+ 
+-        sio = (struct stream_io *)VFS_ADD_FSP_EXTENSION(handle, fsp,
++		sio = (struct stream_io *)VFS_ADD_FSP_EXTENSION(handle, fsp,
+ 							struct stream_io,
+ 							NULL);
+         if (sio == NULL) {
+@@ -511,8 +504,15 @@
+ 
+         sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
+ 					xattr_name);
++	/*
++	 * sio->base needs to be a copy of fsp->fsp_name->base_name,
++	 * making it identical to streams_xattr_recheck(). If the
++	 * open is changing directories, fsp->fsp_name->base_name
++	 * will be the full path from the share root, whilst
++	 * smb_fname will be relative to the $cwd.
++	 */
+         sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
+-				  smb_fname->base_name);
++				  fsp->fsp_name->base_name);
+ 	sio->fsp_name_ptr = fsp->fsp_name;
+ 	sio->handle = handle;
+ 	sio->fsp = fsp;
+@@ -861,7 +861,7 @@
+ 		return -1;
+ 	}
+ 
+-	status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp,
++	status = get_ea_value(talloc_tos(), handle->conn, fsp,
+ 			      sio->base, sio->xattr_name, &ea);
+ 	if (!NT_STATUS_IS_OK(status)) {
+ 		return -1;
+@@ -885,13 +885,13 @@
+ 
+         memcpy(ea.value.data + offset, data, n);
+ 
+-	if (fsp->base_fsp->fh->fd != -1) {
+-		ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
++	if (fsp->fh->fd != -1) {
++		ret = SMB_VFS_FSETXATTR(fsp,
+ 				sio->xattr_name,
+ 				ea.value.data, ea.value.length, 0);
+ 	} else {
+ 		ret = SMB_VFS_SETXATTR(fsp->conn,
+-				       fsp->base_fsp->fsp_name->base_name,
++				       fsp->fsp_name->base_name,
+ 				sio->xattr_name,
+ 				ea.value.data, ea.value.length, 0);
+ 	}
+@@ -925,7 +925,7 @@
+ 		return -1;
+ 	}
+ 
+-	status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp,
++	status = get_ea_value(talloc_tos(), handle->conn, fsp,
+ 			      sio->base, sio->xattr_name, &ea);
+ 	if (!NT_STATUS_IS_OK(status)) {
+ 		return -1;
+@@ -970,7 +970,7 @@
+ 		return -1;
+ 	}
+ 
+-	status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp,
++	status = get_ea_value(talloc_tos(), handle->conn, fsp,
+ 			      sio->base, sio->xattr_name, &ea);
+ 	if (!NT_STATUS_IS_OK(status)) {
+ 		return -1;
+@@ -995,13 +995,13 @@
+ 	ea.value.length = offset + 1;
+ 	ea.value.data[offset] = 0;
+ 
+-	if (fsp->base_fsp->fh->fd != -1) {
+-		ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
++	if (fsp->fh->fd != -1) {
++		ret = SMB_VFS_FSETXATTR(fsp,
+ 				sio->xattr_name,
+ 				ea.value.data, ea.value.length, 0);
+ 	} else {
+ 		ret = SMB_VFS_SETXATTR(fsp->conn,
+-				       fsp->base_fsp->fsp_name->base_name,
++			        fsp->fsp_name->base_name,
+ 				sio->xattr_name,
+ 				ea.value.data, ea.value.length, 0);
+ 	}
+--- samba-3.6.6.orig/source3/smbd/dir.c
++++ samba-3.6.6/source3/smbd/dir.c
+@@ -1358,7 +1358,8 @@
+  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 char *name,
+ 			const char *mask,
+ 			uint32 attr)
+@@ -1370,27 +1371,21 @@
+ 		return NULL;
+ 	}
+ 
+-	dirp->conn = conn;
+-	dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
+-
+-	dirp->dir_path = talloc_strdup(dirp, name);
+-	if (!dirp->dir_path) {
+-		errno = ENOMEM;
++	dirp->dir = SMB_VFS_OPENDIR(conn, name, mask, attr);
++	if (!dirp->dir) {
++		DEBUG(5,("OpenDir: Can't open %s. %s\n", name,
++			 strerror(errno) ));
+ 		goto fail;
+ 	}
+ 
++	dirp->conn = conn;
++	dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
++
+ 	if (sconn && !sconn->using_smb2) {
+ 		sconn->searches.dirhandles_open++;
+ 	}
+ 	talloc_set_destructor(dirp, smb_Dir_destructor);
+ 
+-	dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
+-	if (!dirp->dir) {
+-		DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path,
+-			 strerror(errno) ));
+-		goto fail;
+-	}
+-
+ 	return dirp;
+ 
+   fail:
+@@ -1398,6 +1393,76 @@
+ 	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 open_dir_safely(mem_ctx,
++				conn,
++				name,
++				mask,
++				attr);
++}
++
+ /*******************************************************************
+  Open a directory from an fsp.
+ ********************************************************************/
+@@ -1411,7 +1476,17 @@
+ 	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;
+@@ -1423,36 +1498,33 @@
+ 		goto fail;
+ 	}
+ 
+-	if (sconn && !sconn->using_smb2) {
+-		sconn->searches.dirhandles_open++;
+-	}
+-	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_path,
+-				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_path,
++			strerror(errno)));
++		if (errno != ENOSYS) {
++			goto fail;
+ 		}
+ 	}
+ 
+ 	if (dirp->dir == NULL) {
+-		/* FDOPENDIR didn't work. Use OPENDIR instead. */
+-		dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
++		/* FDOPENDIR is not supported. Use OPENDIR instead. */
++		TALLOC_FREE(dirp);
++		return open_dir_safely(mem_ctx,
++					conn,
++					fsp->fsp_name->base_name,
++					mask,
++					attr);
+ 	}
+ 
+-	if (!dirp->dir) {
+-		DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path,
+-			 strerror(errno) ));
+-		goto fail;
++	if (sconn && !sconn->using_smb2) {
++		sconn->searches.dirhandles_open++;
+ 	}
++	talloc_set_destructor(dirp, smb_Dir_destructor);
+ 
+ 	return dirp;
+ 
diff --git a/debian/patches/CVE-2017-2619-regression-bug-12721-fix.patch b/debian/patches/CVE-2017-2619-regression-bug-12721-fix.patch
new file mode 100644
index 0000000..cefdd86
--- /dev/null
+++ b/debian/patches/CVE-2017-2619-regression-bug-12721-fix.patch
@@ -0,0 +1,179 @@
+bug: https://bugzilla.samba.org/show_bug.cgi?id=12721
+Description: This patch is a consolidation of several patches described by the Git commit summaries below
+
+From 5d4ef6ff0970c93fed49e51a01e63cb67d49d087 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 27 Mar 2017 10:46:47 -0700
+Subject: [PATCH 1/3] s3: smbd: Fix incorrect logic exposed by fix for the
+ security bug 12496 (CVE-2017-2619).
+
+In a UNIX filesystem, the names "." and ".." by definition can *never*
+be symlinks - they are already reserved names.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+Reviewed-by: Uri Simchoni <uri at samba.org>
+(cherry picked from commit ae17bebd250bdde5614b2ac17e53512f19fe9b68)
+---
+ source3/smbd/vfs.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+From 71500662d1098d17657b0148a0aa06cd69482c7d Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 27 Mar 2017 17:04:58 -0700
+Subject: [PATCH 2/3] s3: smbd: Fix "follow symlink = no" regression part 2.
+
+Add an extra paramter to cwd_name to check_reduced_name().
+
+If cwd_name == NULL then fname is a client given path relative
+to the root path of the share.
+
+If cwd_name != NULL then fname is a client given path relative
+to cwd_name. cwd_name is relative to the root path of the share.
+
+Not yet used, logic added in the next commit.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+Reviewed-by: Ralph Boehme <slow at samba.org>
+(cherry picked from commit 83e30cb48859b412b76572b6a3ba84d8fde167af)
+---
+ source3/smbd/filename.c |  2 +-
+ source3/smbd/open.c     |  2 +-
+ source3/smbd/proto.h    |  4 +++-
+ source3/smbd/vfs.c      | 10 +++++++++-
+ 4 files changed, 14 insertions(+), 4 deletions(-)
+
+From e3fd46264b82ffc22424ee7364b3fd2c0fc14a7e Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 27 Mar 2017 17:09:38 -0700
+Subject: [PATCH 3/3] s3: smbd: Fix "follow symlink = no" regression part 2.
+
+Use the cwd_name parameter to reconstruct the original
+client name for symlink testing.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+Reviewed-by: Ralph Boehme <slow at samba.org>
+(cherry picked from commit e182a4d39e86c9694e255efdf6ee2ea3ccb9af4a)
+---
+ source3/smbd/vfs.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+--- samba-3.6.6.orig/source3/smbd/vfs.c
++++ samba-3.6.6/source3/smbd/vfs.c
+@@ -894,11 +894,20 @@
+ /*******************************************************************
+  Reduce a file name, removing .. elements and checking that
+  it is below dir in the heirachy. This uses realpath.
++
++ If cwd_name == NULL then fname is a client given path relative
++ to the root path of the share.
++
++ If cwd_name != NULL then fname is a client given path relative
++ to cwd_name. cwd_name is relative to the root path of the share.
+ ********************************************************************/
+ 
+-NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
++NTSTATUS check_reduced_name(connection_struct *conn,
++				const char *cwd_name,
++				const char *fname)
+ {
+ 	char *resolved_name = NULL;
++	char *new_fname = NULL;
+ 	bool allow_symlinks = true;
+ 	bool allow_widelinks = false;
+ 
+@@ -1026,8 +1035,11 @@
+ 			/* fname can't have changed in resolved_path. */
+ 			const char *p = &resolved_name[rootdir_len];
+ 
+-			/* *p can be '\0' if fname was "." */
+-			if (*p == '\0' && ISDOT(fname)) {
++			/*
++			 * UNIX filesystem semantics, names consisting
++			 * only of "." or ".." CANNOT be symlinks.
++			 */
++			if (ISDOT(fname) || ISDOTDOT(fname)) {
+ 				goto out;
+ 			}
+ 
+@@ -1041,11 +1053,32 @@
+ 			}
+ 
+ 			p++;
++
++			/*
++			 * If cwd_name is present and not ".",
++			 * then fname is relative to that, not
++			 * the root of the share. Make sure the
++			 * path we check is the one the client
++			 * sent (cwd_name+fname).
++			 */
++			if (cwd_name != NULL && !ISDOT(cwd_name)) {
++				new_fname = talloc_asprintf(talloc_tos(),
++							"%s/%s",
++							cwd_name,
++							fname);
++				if (new_fname == NULL) {
++					SAFE_FREE(resolved_name);
++					return NT_STATUS_NO_MEMORY;
++				}
++				fname = new_fname;
++			}
++
+ 			if (strcmp(fname, p)!=0) {
+ 				DEBUG(2, ("check_reduced_name: Bad access "
+ 					"attempt: %s is a symlink\n",
+ 					fname));
+ 				SAFE_FREE(resolved_name);
++				TALLOC_FREE(new_fname);
+ 				return NT_STATUS_ACCESS_DENIED;
+ 			}
+ 		}
+@@ -1056,6 +1089,7 @@
+ 	DEBUG(3,("check_reduced_name: %s reduced to %s\n", fname,
+ 		 resolved_name));
+ 	SAFE_FREE(resolved_name);
++	TALLOC_FREE(new_fname);
+ 	return NT_STATUS_OK;
+ }
+ 
+--- samba-3.6.6.orig/source3/smbd/filename.c
++++ samba-3.6.6/source3/smbd/filename.c
+@@ -1009,7 +1009,7 @@
+ 	}
+ 
+ 	if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
+-		status = check_reduced_name(conn,name);
++		status = check_reduced_name(conn, NULL, name);
+ 		if (!NT_STATUS_IS_OK(status)) {
+ 			DEBUG(5,("check_name: name %s failed with %s\n",name,
+ 						nt_errstr(status)));
+--- samba-3.6.6.orig/source3/smbd/open.c
++++ samba-3.6.6/source3/smbd/open.c
+@@ -381,7 +381,7 @@
+ 	}
+ 
+ 	/* Ensure the relative path is below the share. */
+-	status = check_reduced_name(conn, final_component);
++	status = check_reduced_name(conn, parent_dir, final_component);
+ 	if (!NT_STATUS_IS_OK(status)) {
+ 		saved_errno = map_errno_from_nt_status(status);
+ 		goto out;
+--- samba-3.6.6.orig/source3/smbd/proto.h
++++ samba-3.6.6/source3/smbd/proto.h
+@@ -1179,7 +1179,9 @@
+ 			    SMB_STRUCT_STAT *sbuf, char **talloced);
+ int vfs_ChDir(connection_struct *conn, const char *path);
+ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
+-NTSTATUS check_reduced_name(connection_struct *conn, const char *fname);
++NTSTATUS check_reduced_name(connection_struct *conn,
++			const char *cwd_name,
++			const char *fname);
+ int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname,
+ 		       SMB_STRUCT_STAT *psbuf);
+ int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
diff --git a/debian/patches/CVE-2017-2619-tests.patch b/debian/patches/CVE-2017-2619-tests.patch
new file mode 100644
index 0000000..41c8461
--- /dev/null
+++ b/debian/patches/CVE-2017-2619-tests.patch
@@ -0,0 +1,296 @@
+Description: Patches to unit tests associated with CVE-2017-2619 regression
+origin: https://attachments.samba.org/attachment.cgi?id=13130
+
+From 2c6de8584779e413f1e6ff9c933f9281693bfbc0 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 27 Mar 2017 11:48:25 -0700
+Subject: [PATCH 2/6] s3: Test for CVE-2017-2619 regression with "follow
+ symlinks = no".
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+Reviewed-by: Uri Simchoni <uri at samba.org>
+
+Back-ported from commit 782172a9bef0040981d20e49519b13dd744df6a0
+---
+ selftest/target/Samba3.pm                 |  7 +++
+ source3/script/tests/test_smbclient_s3.sh | 73 +++++++++++++++++++++++++++++++
+ 2 files changed, 80 insertions(+)
+
+diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
+index 01a1c470af0..7765b9efbb2 100644
+--- a/selftest/target/Samba3.pm
++++ b/selftest/target/Samba3.pm
+@@ -481,6 +481,9 @@ sub provision($$$$$$)
+ 	my $msdfs_deeppath="$msdfs_shrdir/deeppath";
+ 	push(@dirs,$msdfs_deeppath);
+ 
++	my $nosymlinks_shrdir="$shrdir/nosymlinks";
++	push(@dirs,$nosymlinks_shrdir);
++
+ 	# this gets autocreated by winbindd
+ 	my $wbsockdir="$prefix_abs/winbindd";
+ 	my $wbsockprivdir="$lockdir/winbindd_privileged";
+@@ -695,6 +698,10 @@ sub provision($$$$$$)
+ 	copy = print1
+ [print\$]
+ 	copy = tmp
++[nosymlinks]
++       copy = tmp
++       path = $nosymlinks_shrdir
++       follow symlinks = no
+ 	";
+ 	close(CONF);
+ 
+diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh
+index 772802f77b1..57ef87e4949 100755
+--- a/source3/script/tests/test_smbclient_s3.sh
++++ b/source3/script/tests/test_smbclient_s3.sh
+@@ -401,6 +401,75 @@ done
+ 
+ LOGDIR=$(mktemp -d ${PREFIX}/${LOGDIR_PREFIX}_XXXXXX)
+ 
++# Test follow symlinks can't access symlinks
++test_nosymlinks()
++{
++# Setup test dirs.
++    slink_name="$LOCAL_PATH/nosymlinks/source"
++    slink_target="$LOCAL_PATH/nosymlinks/target"
++    mkdir_target="$LOCAL_PATH/nosymlinks/a"
++
++    rm -f $slink_target
++    rm -f $slink_name
++    rm -rf $mkdir_target
++
++    touch $slink_target
++    ln -s $slink_target $slink_name
++
++# Getting a file through a symlink name should fail.
++    tmpfile=$PREFIX/smbclient_interactive_prompt_commands
++    cat > $tmpfile <<EOF
++get source
++quit
++EOF
++    cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=`eval $cmd`
++    ret=$?
++    rm -f $tmpfile
++
++    if [ $ret != 0 ] ; then
++       echo "$out"
++       echo "failed accessing nosymlinks with error $ret"
++       false
++       return
++    fi
++
++    echo "$out" | grep 'NT_STATUS_ACCESS_DENIED'
++    ret=$?
++    if [ $ret != 0 ] ; then
++       echo "$out"
++       echo "failed - should get NT_STATUS_ACCESS_DENIED getting \\nosymlinks\\source"
++       false
++    fi
++
++# But we should be able to create and delete directories.
++    cat > $tmpfile <<EOF
++mkdir a
++mkdir a\\b
++quit
++EOF
++    cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=`eval $cmd`
++    ret=$?
++    rm -f $tmpfile
++
++    if [ $ret != 0 ] ; then
++       echo "$out"
++       echo "failed accessing nosymlinks with error $ret"
++       false
++       return
++    fi
++
++    echo "$out" | grep 'NT_STATUS'
++    ret=$?
++    if [ $ret == 0 ] ; then
++	echo "$out"
++	echo "failed - NT_STATUS_XXXX doing mkdir a; mkdir a\\b on \\nosymlinks"
++	false
++    fi
++}
+ 
+ testit "smbclient -L $SERVER_IP" $SMBCLIENT -L $SERVER_IP -N -p 139 || failed=`expr $failed + 1`
+ testit "smbclient -L $SERVER -I $SERVER_IP" $SMBCLIENT -L $SERVER -I $SERVER_IP -N -p 139 -c quit || failed=`expr $failed + 1`
+@@ -445,6 +514,10 @@ testit "ccache access works for smbclient" \
+     test_ccache_access || \
+     failed=`expr $failed + 1`
+ 
++testit "follow symlinks = no" \
++    test_nosymlinks || \
++    failed=`expr $failed + 1`
++
+ testit "rm -rf $LOGDIR" \
+     rm -rf $LOGDIR || \
+     failed=`expr $failed + 1`
+-- 
+2.12.0
+
+
+From 17865cf188f42850f18f46514643a5b3a43e5707 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 27 Mar 2017 22:07:50 -0700
+Subject: [PATCH 3/6] s3: Fixup test for CVE-2017-2619 regression with "follow
+ symlinks = no"
+
+Use correct bash operators (not string operators).
+Add missing "return".
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+Reviewed-by: Ralph Boehme <slow at samba.org>
+(cherry picked from commit 037297a1c50e90a0092e3b94f472623f41ccc015)
+---
+ source3/script/tests/test_smbclient_s3.sh | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh
+index 57ef87e4949..bd5714fca6e 100755
+--- a/source3/script/tests/test_smbclient_s3.sh
++++ b/source3/script/tests/test_smbclient_s3.sh
+@@ -428,7 +428,7 @@ EOF
+     ret=$?
+     rm -f $tmpfile
+ 
+-    if [ $ret != 0 ] ; then
++    if [ $ret -ne 0 ] ; then
+        echo "$out"
+        echo "failed accessing nosymlinks with error $ret"
+        false
+@@ -437,10 +437,11 @@ EOF
+ 
+     echo "$out" | grep 'NT_STATUS_ACCESS_DENIED'
+     ret=$?
+-    if [ $ret != 0 ] ; then
++    if [ $ret -ne 0 ] ; then
+        echo "$out"
+        echo "failed - should get NT_STATUS_ACCESS_DENIED getting \\nosymlinks\\source"
+        false
++       return
+     fi
+ 
+ # But we should be able to create and delete directories.
+@@ -455,7 +456,7 @@ EOF
+     ret=$?
+     rm -f $tmpfile
+ 
+-    if [ $ret != 0 ] ; then
++    if [ $ret -ne 0 ] ; then
+        echo "$out"
+        echo "failed accessing nosymlinks with error $ret"
+        false
+@@ -464,7 +465,7 @@ EOF
+ 
+     echo "$out" | grep 'NT_STATUS'
+     ret=$?
+-    if [ $ret == 0 ] ; then
++    if [ $ret -eq 0 ] ; then
+ 	echo "$out"
+ 	echo "failed - NT_STATUS_XXXX doing mkdir a; mkdir a\\b on \\nosymlinks"
+ 	false
+-- 
+2.12.0
+
+
+From 9b573af39f3d4995464e30771fa06e0709b5e57b Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra at samba.org>
+Date: Mon, 27 Mar 2017 22:10:29 -0700
+Subject: [PATCH 6/6] s3: Test for CVE-2017-2619 regression with "follow
+ symlinks = no" - part 2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add tests for regular access.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+
+Signed-off-by: Jeremy Allison <jra at samba.org>
+Reviewed-by: Ralph Boehme <slow at samba.org>
+
+Autobuild-User(master): Ralph Böhme <slow at samba.org>
+Autobuild-Date(master): Tue Mar 28 17:05:27 CEST 2017 on sn-devel-144
+
+(cherry picked from commit 4e734fcd1bf82c08aa303ce44e9735acccffcf06)
+---
+ source3/script/tests/test_smbclient_s3.sh | 37 +++++++++++++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
+
+diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh
+index bd5714fca6e..885766f6c16 100755
+--- a/source3/script/tests/test_smbclient_s3.sh
++++ b/source3/script/tests/test_smbclient_s3.sh
+@@ -408,14 +408,22 @@ test_nosymlinks()
+     slink_name="$LOCAL_PATH/nosymlinks/source"
+     slink_target="$LOCAL_PATH/nosymlinks/target"
+     mkdir_target="$LOCAL_PATH/nosymlinks/a"
++    dir1="$LOCAL_PATH/nosymlinks/foo"
++    dir2="$LOCAL_PATH/nosymlinks/foo/bar"
++    get_target="$LOCAL_PATH/nosymlinks/foo/bar/testfile"
+ 
+     rm -f $slink_target
+     rm -f $slink_name
+     rm -rf $mkdir_target
++    rm -rf $dir1
+ 
+     touch $slink_target
+     ln -s $slink_target $slink_name
+ 
++    mkdir $dir1
++    mkdir $dir2
++    touch $get_target
++
+ # Getting a file through a symlink name should fail.
+     tmpfile=$PREFIX/smbclient_interactive_prompt_commands
+     cat > $tmpfile <<EOF
+@@ -470,6 +478,35 @@ EOF
+ 	echo "failed - NT_STATUS_XXXX doing mkdir a; mkdir a\\b on \\nosymlinks"
+ 	false
+     fi
++
++# Ensure regular file/directory access also works.
++    cat > $tmpfile <<EOF
++cd foo\\bar
++ls
++get testfile -
++quit
++EOF
++    cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=`eval $cmd`
++    ret=$?
++    rm -f $tmpfile
++
++    if [ $ret -ne 0 ] ; then
++       echo "$out"
++       echo "failed accessing nosymlinks with error $ret"
++       false
++       return
++    fi
++
++    echo "$out" | grep 'NT_STATUS'
++    ret=$?
++    if [ $ret -eq 0 ] ; then
++       echo "$out"
++       echo "failed - NT_STATUS_XXXX doing cd foo\\bar; get testfile on \\nosymlinks"
++       false
++       return
++    fi
+ }
+ 
+ testit "smbclient -L $SERVER_IP" $SMBCLIENT -L $SERVER_IP -N -p 139 || failed=`expr $failed + 1`
+-- 
+2.12.0
+
diff --git a/debian/patches/series b/debian/patches/series
index e576e83..5774787 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -53,3 +53,7 @@ netlogon_credentials_regression.patch
 bug9669_regression.patch
 fix_netapp.patch
 security-CVE-2016-2125-Don-t-pass-GSS_C_DELEG_FLAG-by-def.patch
+CVE-2017-2619-prerequisites.patch
+CVE-2017-2619-race-condition-fix.patch
+CVE-2017-2619-regression-bug-12721-fix.patch
+CVE-2017-2619-tests.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