Jeremie Courreges-Anglas <[email protected]> writes:

> Hi,
>
> the last security update introduced a regression.
>
> -->8--
> This is a bug fix release to address a regression introduced by the security
> fixes for CVE-2017-2619 (Symlink race allows access outside share definition).
> Please see https://bugzilla.samba.org/show_bug.cgi?id=12721 for details.
>
>
> Changes since 4.5.7:
> --------------------
>
> o  Jeremy Allison <[email protected]>
>    * BUG 12721: Fix regression with "follow symlinks = no".
> --8<--
>
> The actual changes are just:
>
>   http://autogeree.net/~jca/tmp/samba-4.5.8-code-changes.txt
>
> This should go in 6.1.  ok?
>
> I'll try to cook a patch for 6.0 soonish.

Here's the diff, fixes from samba-4.4.13 backported to 4.4.5.
Build-tested only, test reports welcome.


Index: Makefile
===================================================================
RCS file: /d/cvs/ports/net/samba/Makefile,v
retrieving revision 1.227.2.3
diff -u -p -r1.227.2.3 Makefile
--- Makefile    27 Mar 2017 23:26:23 -0000      1.227.2.3
+++ Makefile    31 Mar 2017 23:53:44 -0000
@@ -15,7 +15,7 @@ PKGNAME-tevent =      tevent-${TEVENT_V}
 PKGNAME-util =         samba-util-${VERSION}
 PKGNAME-docs =         samba-docs-${VERSION}
 
-REVISION-main =                2
+REVISION-main =                3
 REVISION-ldb =         0
 REVISION-tevent =      0
 
Index: patches/patch-source3_smbd_filename_c
===================================================================
RCS file: patches/patch-source3_smbd_filename_c
diff -N patches/patch-source3_smbd_filename_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-source3_smbd_filename_c       1 Apr 2017 11:46:06 -0000
@@ -0,0 +1,12 @@
+$OpenBSD$
+--- source3/smbd/filename.c.orig       Sat Apr  1 13:43:13 2017
++++ source3/smbd/filename.c    Sat Apr  1 13:45:32 2017
+@@ -1067,7 +1067,7 @@ NTSTATUS check_name(connection_struct *conn, const cha
+       }
+ 
+       if (!lp_widelinks(SNUM(conn)) || !lp_follow_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)));
Index: patches/patch-source3_smbd_open_c
===================================================================
RCS file: /d/cvs/ports/net/samba/patches/Attic/patch-source3_smbd_open_c,v
retrieving revision 1.2.2.1
diff -u -p -r1.2.2.1 patch-source3_smbd_open_c
--- patches/patch-source3_smbd_open_c   27 Mar 2017 23:26:23 -0000      1.2.2.1
+++ patches/patch-source3_smbd_open_c   1 Apr 2017 11:51:46 -0000
@@ -2,8 +2,8 @@ $OpenBSD: patch-source3_smbd_open_c,v 1.
 
 CVE-2017-2619 (Symlink race allows access outside share definition)
 
---- source3/smbd/open.c.orig   Sat Mar 25 17:19:25 2017
-+++ source3/smbd/open.c        Sat Mar 25 17:19:50 2017
+--- source3/smbd/open.c.orig   Sat Apr  1 13:49:49 2017
++++ source3/smbd/open.c        Sat Apr  1 13:51:43 2017
 @@ -345,6 +345,268 @@ static NTSTATUS check_base_file_access(struct connecti
  }
  
@@ -202,7 +202,7 @@ CVE-2017-2619 (Symlink race allows acces
 +      }
 +
 +      /* 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;
Index: patches/patch-source3_smbd_proto_h
===================================================================
RCS file: patches/patch-source3_smbd_proto_h
diff -N patches/patch-source3_smbd_proto_h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-source3_smbd_proto_h  1 Apr 2017 11:46:06 -0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+--- source3/smbd/proto.h.orig  Sat Apr  1 13:43:13 2017
++++ source3/smbd/proto.h       Sat Apr  1 13:45:32 2017
+@@ -1197,7 +1197,9 @@ const char *vfs_readdirname(connection_struct *conn, v
+                           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);
+ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
+                       const char *fname,
+                       struct smb_request *smbreq);
Index: patches/patch-source3_smbd_vfs_c
===================================================================
RCS file: patches/patch-source3_smbd_vfs_c
diff -N patches/patch-source3_smbd_vfs_c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-source3_smbd_vfs_c    1 Apr 2017 11:46:06 -0000
@@ -0,0 +1,80 @@
+$OpenBSD$
+--- source3/smbd/vfs.c.orig    Sat Apr  1 13:43:13 2017
++++ source3/smbd/vfs.c Sat Apr  1 13:45:32 2017
+@@ -1149,11 +1149,20 @@ NTSTATUS check_reduced_name_with_privilege(connection_
+ /*******************************************************************
+  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;
+ 
+@@ -1277,8 +1286,11 @@ NTSTATUS check_reduced_name(connection_struct *conn, c
+                       /* 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;
+                       }
+ 
+@@ -1292,11 +1304,32 @@ NTSTATUS check_reduced_name(connection_struct *conn, c
+                       }
+ 
+                       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 to %s\n",
+                                         fname, p));
+                               SAFE_FREE(resolved_name);
++                              TALLOC_FREE(new_fname);
+                               return NT_STATUS_ACCESS_DENIED;
+                       }
+               }
+@@ -1306,6 +1339,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, c
+ 
+       DBG_INFO("%s reduced to %s\n", fname, resolved_name);
+       SAFE_FREE(resolved_name);
++      TALLOC_FREE(new_fname);
+       return NT_STATUS_OK;
+ }
+ 


-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to