X-Git-Url: http://git.ipfire.org/?p=ipfire-2.x.git;a=blobdiff_plain;f=src%2Fpatches%2Fsamba%2FCVE-2017-2619.patch;fp=src%2Fpatches%2Fsamba%2FCVE-2017-2619.patch;h=0000000000000000000000000000000000000000;hp=149e085fe1bb1739485e01df370a25530dd397f3;hb=201ad7ff80eb8870aab2b903be6eb7aea2adf563;hpb=f29f169735ff3b431c6dc7cb50b36d0fe644163b diff --git a/src/patches/samba/CVE-2017-2619.patch b/src/patches/samba/CVE-2017-2619.patch deleted file mode 100644 index 149e085fe1..0000000000 --- a/src/patches/samba/CVE-2017-2619.patch +++ /dev/null @@ -1,1328 +0,0 @@ -From a398754c9bb1639f762979765de6c540c714b5cb Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 -Signed-off-by: Jeremy Allison ---- - source3/smbd/open.c | 2 +- - source3/smbd/proto.h | 2 ++ - source3/smbd/smb2_find.c | 17 +++++++++++++++++ - 3 files changed, 20 insertions(+), 1 deletion(-) - -diff --git a/source3/smbd/open.c b/source3/smbd/open.c -index 441b8cd4362..35eee0a1485 100644 ---- a/source3/smbd/open.c -+++ b/source3/smbd/open.c -@@ -197,7 +197,7 @@ static NTSTATUS check_base_file_access(struct connection_struct *conn, - 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) -diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h -index f5fad2bbb50..594edfa1e98 100644 ---- a/source3/smbd/proto.h -+++ b/source3/smbd/proto.h -@@ -603,6 +603,8 @@ NTSTATUS smb1_file_se_access_check(connection_struct *conn, - 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, -diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c -index 6fe6545c128..9dd3176497b 100644 ---- a/source3/smbd/smb2_find.c -+++ b/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, -@@ -301,7 +302,23 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx, - } - - 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); -+ } - } - - wcard_has_wild = ms_has_wild(in_file_name); --- -2.13.5 - - -From a35fa98b99aa60132eb2c083d6393c28905e2045 Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - source3/modules/vfs_dirsort.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c -index 66582e67890..dbcf0b16ed3 100644 ---- a/source3/modules/vfs_dirsort.c -+++ b/source3/modules/vfs_dirsort.c -@@ -153,6 +153,10 @@ static SMB_STRUCT_DIR *dirsort_opendir(vfs_handle_struct *handle, - 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); --- -2.13.5 - - -From 23d2849d724a0f5bdf51dc7d7db438ed9fb4c2a9 Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - source3/modules/vfs_streams_xattr.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c -index 731c813f4d7..be46f8dc1e6 100644 ---- a/source3/modules/vfs_streams_xattr.c -+++ b/source3/modules/vfs_streams_xattr.c -@@ -511,8 +511,15 @@ static int streams_xattr_open(vfs_handle_struct *handle, - - 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; --- -2.13.5 - - -From 91935aaf77c70e3e2436af1d6e4a538d29fd4276 Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - source3/modules/vfs_streams_xattr.c | 205 +++++++++++++++++------------------- - 1 file changed, 99 insertions(+), 106 deletions(-) - -diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c -index be46f8dc1e6..a4ab84bba71 100644 ---- a/source3/modules/vfs_streams_xattr.c -+++ b/source3/modules/vfs_streams_xattr.c -@@ -229,7 +229,7 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp, - 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 @@ static int streams_xattr_open(vfs_handle_struct *handle, - 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 @@ static int streams_xattr_open(vfs_handle_struct *handle, - /* 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; -+ /* 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; -+ } - -- hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp, -- baseflags, mode); -+ /* -+ * 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; - -- TALLOC_FREE(smb_fname_base); -+ hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp, -+ baseflags, mode); - -- /* 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); -- } -+ TALLOC_FREE(smb_fname_base); - -- if (hostfd == -1) { -- goto fail; -- } -+ /* 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); -+ } - -- status = get_ea_value(talloc_tos(), handle->conn, NULL, -- smb_fname->base_name, xattr_name, &ea); -+ if (hostfd == -1) { -+ goto fail; -+ } - -- DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status))); -+ status = get_ea_value(talloc_tos(), handle->conn, NULL, -+ smb_fname->base_name, xattr_name, &ea); - -- 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. -- */ -- DEBUG(10, ("streams_xattr_open: base file %s not around, " -- "returning ENOENT\n", smb_fname->base_name)); -- errno = ENOENT; -- goto fail; -- } -+ DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status))); - -- if (!NT_STATUS_IS_OK(status)) { -- /* -- * The attribute does not exist -- */ -+ 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. -+ */ -+ DEBUG(10, ("streams_xattr_open: base file %s not around, " -+ "returning ENOENT\n", smb_fname->base_name)); -+ errno = ENOENT; -+ goto fail; -+ } - -- if (flags & O_CREAT) { -+ if (!NT_STATUS_IS_OK(status)) { - /* -- * Darn, xattrs need at least 1 byte -+ * The attribute does not exist - */ -- char null = '\0'; - -- DEBUG(10, ("creating attribute %s on file %s\n", -- xattr_name, smb_fname->base_name)); -+ 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) { -@@ -868,7 +861,7 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle, - 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; -@@ -892,13 +885,13 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle, - - 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); - } -@@ -932,7 +925,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle, - 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; -@@ -977,7 +970,7 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle, - 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; -@@ -1002,13 +995,13 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle, - 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); - } --- -2.13.5 - - -From 3f3c731faaa59f4d3ce7e49c12795c40e048d29f Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - 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 18ecf066824..ebe2641f813 100644 ---- a/source3/smbd/dir.c -+++ b/source3/smbd/dir.c -@@ -1367,7 +1367,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 char *name, - const char *mask, - uint32 attr) -@@ -1407,6 +1408,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 char *name, -+ const char *mask, -+ uint32_t attr) -+{ -+ return OpenDir_internal(mem_ctx, -+ conn, -+ name, -+ mask, -+ attr); -+} -+ - /******************************************************************* - Open a directory from an fsp. - ********************************************************************/ --- -2.13.5 - - -From 7efeb067c1586e0f1cfbb775b1efcb3b92005140 Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - source3/smbd/dir.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c -index ebe2641f813..65327dd0dd1 100644 ---- a/source3/smbd/dir.c -+++ b/source3/smbd/dir.c -@@ -1380,6 +1380,13 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx, - return NULL; - } - -+ 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)); - -@@ -1394,13 +1401,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_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: --- -2.13.5 - - -From 49d22a0c51ef1f78f0488a7c35131887704e987b Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - source3/smbd/dir.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++------ - 1 file changed, 59 insertions(+), 7 deletions(-) - -diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c -index 65327dd0dd1..2d168c3ba9f 100644 ---- a/source3/smbd/dir.c -+++ b/source3/smbd/dir.c -@@ -1390,12 +1390,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_path = talloc_strdup(dirp, name); -- if (!dirp->dir_path) { -- errno = ENOMEM; -- goto fail; -- } -- - if (sconn && !sconn->using_smb2) { - sconn->searches.dirhandles_open++; - } -@@ -1408,12 +1402,70 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx, - return NULL; - } - -+/**************************************************************************** -+ Open a directory handle by pathname, ensuring it's under the share path. -+****************************************************************************/ -+ -+static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx, -+ connection_struct *conn, -+ const char *name, -+ const char *wcard, -+ uint32_t attr) -+{ -+ struct smb_Dir *dir_hnd = NULL; -+ char *saved_dir = vfs_GetWd(ctx, conn); -+ NTSTATUS status; -+ -+ if (saved_dir == NULL) { -+ return NULL; -+ } -+ -+ if (vfs_ChDir(conn, name) == -1) { -+ goto out; -+ } -+ -+ /* -+ * Now the directory is pinned, use -+ * REALPATH to ensure we can access it. -+ */ -+ status = check_name(conn, "."); -+ if (!NT_STATUS_IS_OK(status)) { -+ goto out; -+ } -+ -+ dir_hnd = OpenDir_internal(ctx, -+ conn, -+ ".", -+ wcard, -+ attr); -+ -+ if (dir_hnd == NULL) { -+ goto out; -+ } -+ -+ /* -+ * OpenDir_internal only gets "." as the dir name. -+ * Store the real dir name here. -+ */ -+ -+ dir_hnd->dir_path = talloc_strdup(dir_hnd, name); -+ if (!dir_hnd->dir_path) { -+ errno = ENOMEM; -+ } -+ -+ out: -+ -+ vfs_ChDir(conn, saved_dir); -+ TALLOC_FREE(saved_dir); -+ return dir_hnd; -+} -+ - struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, - const char *name, - const char *mask, - uint32_t attr) - { -- return OpenDir_internal(mem_ctx, -+ return open_dir_safely(mem_ctx, - conn, - name, - mask, --- -2.13.5 - - -From 6426ae1f9ef53158a6fbe1912dfec40d834115fe Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - 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 2d168c3ba9f..6aed4a6da46 100644 ---- a/source3/smbd/dir.c -+++ b/source3/smbd/dir.c -@@ -1485,7 +1485,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; -@@ -1502,18 +1512,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_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) { -+ return NULL; - } - } - --- -2.13.5 - - -From f6581858ce665b880c5fea465ec61b1b0c504d89 Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - 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 6aed4a6da46..efd1a73aab6 100644 ---- a/source3/smbd/dir.c -+++ b/source3/smbd/dir.c -@@ -1521,7 +1521,7 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn, - dirp->dir_path, - strerror(errno))); - if (errno != ENOSYS) { -- return NULL; -+ goto fail; - } - } - --- -2.13.5 - - -From bacba6987e58d44886d04b1dd5e36f7781dcd9b0 Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - 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 efd1a73aab6..5eca128c033 100644 ---- a/source3/smbd/dir.c -+++ b/source3/smbd/dir.c -@@ -1507,11 +1507,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; -@@ -1536,6 +1531,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.13.5 - - -From 34b3d05b55f5c40de76ba65d6b028818518a519f Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - source3/smbd/dir.c | 15 +++++++-------- - 1 file changed, 7 insertions(+), 8 deletions(-) - -diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c -index 5eca128c033..7690cb18c1a 100644 ---- a/source3/smbd/dir.c -+++ b/source3/smbd/dir.c -@@ -1521,14 +1521,13 @@ 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_path, mask, attr); -- } -- -- if (!dirp->dir) { -- DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path, -- strerror(errno) )); -- goto fail; -+ /* 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 (sconn && !sconn->using_smb2) { --- -2.13.5 - - -From 84bc8b232a4495bff270b7800833ef6785937576 Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - source3/smbd/open.c | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/source3/smbd/open.c b/source3/smbd/open.c -index 35eee0a1485..8417f8aca4a 100644 ---- a/source3/smbd/open.c -+++ b/source3/smbd/open.c -@@ -205,8 +205,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. - */ -@@ -214,7 +213,6 @@ NTSTATUS fd_open(struct connection_struct *conn, - if (fsp->posix_open || !lp_symlinks(SNUM(conn))) { - flags |= O_NOFOLLOW; - } --#endif - - fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode); - if (fsp->fh->fd == -1) { --- -2.13.5 - - -From af0c5a266ae65ad2a638fe48a7ad7d77417f97d7 Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - source3/smbd/open.c | 30 ++++++++++++++++++++++++++++-- - 1 file changed, 28 insertions(+), 2 deletions(-) - -diff --git a/source3/smbd/open.c b/source3/smbd/open.c -index 8417f8aca4a..e727e89e9d8 100644 ---- a/source3/smbd/open.c -+++ b/source3/smbd/open.c -@@ -194,6 +194,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. - ****************************************************************************/ - -@@ -216,8 +241,9 @@ NTSTATUS fd_open(struct connection_struct *conn, - - 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) { --- -2.13.5 - - -From c3bc4ff0367d7a3ebfd64db6defddea0bc3a5f4a Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - source3/smbd/open.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 242 insertions(+) - -diff --git a/source3/smbd/open.c b/source3/smbd/open.c -index e727e89e9d8..0998adc416a 100644 ---- a/source3/smbd/open.c -+++ b/source3/smbd/open.c -@@ -218,6 +218,248 @@ 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; -+ } -+ -+ 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. - ****************************************************************************/ --- -2.13.5 - - -From 6a88d1cf3deb54a784f50c8eba3b9a24a65c1b34 Mon Sep 17 00:00:00 2001 -From: Jeremy Allison -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 ---- - 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 0998adc416a..65ca14ec8b8 100644 ---- a/source3/smbd/open.c -+++ b/source3/smbd/open.c -@@ -481,7 +481,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.13.5 -