1From eb27f9b7bf9c1dc902d9545eecf805831bd4e46c Mon Sep 17 00:00:00 2001 2From: Jeremy Allison <jra@samba.org> 3Date: Tue, 5 Jan 2016 11:18:12 -0800 4Subject: [PATCH 1/8] CVE-2015-7560: s3: smbd: Add refuse_symlink() function 5 that can be used to prevent operations on a symlink. 6 7BUG: https://bugzilla.samba.org/show_bug.cgi?id=11648 8 9Signed-off-by: Jeremy Allison <jra@samba.org> 10Reviewed-by: Michael Adam <obnox@samba.org> 11--- 12 source3/smbd/trans2.c | 28 ++++++++++++++++++++++++++++ 13 1 file changed, 28 insertions(+) 14 15--- a/source3/smbd/trans2.c 16+++ b/source3/smbd/trans2.c 17@@ -51,6 +51,34 @@ static char *store_file_unix_basic_info2 18 files_struct *fsp, 19 const SMB_STRUCT_STAT *psbuf); 20 21+/**************************************************************************** 22+ Check if an open file handle or pathname is a symlink. 23+****************************************************************************/ 24+ 25+static NTSTATUS refuse_symlink(connection_struct *conn, 26+ const files_struct *fsp, 27+ const char *name) 28+{ 29+ SMB_STRUCT_STAT sbuf; 30+ const SMB_STRUCT_STAT *pst = NULL; 31+ 32+ if (fsp) { 33+ pst = &fsp->fsp_name->st; 34+ } else { 35+ int ret = vfs_stat_smb_fname(conn, 36+ name, 37+ &sbuf); 38+ if (ret == -1) { 39+ return map_nt_error_from_unix(errno); 40+ } 41+ pst = &sbuf; 42+ } 43+ if (S_ISLNK(pst->st_ex_mode)) { 44+ return NT_STATUS_ACCESS_DENIED; 45+ } 46+ return NT_STATUS_OK; 47+} 48+ 49 /******************************************************************** 50 Roundup a value to the nearest allocation roundup size boundary. 51 Only do this for Windows clients. 52@@ -181,12 +209,22 @@ NTSTATUS get_ea_names_from_file(TALLOC_C 53 char **names, **tmp; 54 size_t num_names; 55 ssize_t sizeret = -1; 56+ NTSTATUS status; 57+ 58+ if (pnames) { 59+ *pnames = NULL; 60+ } 61+ *pnum_names = 0; 62 63 if (!lp_ea_support(SNUM(conn))) { 64- if (pnames) { 65- *pnames = NULL; 66- } 67- *pnum_names = 0; 68+ return NT_STATUS_OK; 69+ } 70+ 71+ status = refuse_symlink(conn, fsp, fname); 72+ if (!NT_STATUS_IS_OK(status)) { 73+ /* 74+ * Just return no EA's on a symlink. 75+ */ 76 return NT_STATUS_OK; 77 } 78 79@@ -236,10 +274,6 @@ NTSTATUS get_ea_names_from_file(TALLOC_C 80 81 if (sizeret == 0) { 82 TALLOC_FREE(names); 83- if (pnames) { 84- *pnames = NULL; 85- } 86- *pnum_names = 0; 87 return NT_STATUS_OK; 88 } 89 90@@ -550,6 +584,7 @@ NTSTATUS set_ea(connection_struct *conn, 91 const struct smb_filename *smb_fname, struct ea_list *ea_list) 92 { 93 char *fname = NULL; 94+ NTSTATUS status; 95 96 if (!lp_ea_support(SNUM(conn))) { 97 return NT_STATUS_EAS_NOT_SUPPORTED; 98@@ -559,6 +594,12 @@ NTSTATUS set_ea(connection_struct *conn, 99 return NT_STATUS_ACCESS_DENIED; 100 } 101 102+ status = refuse_symlink(conn, fsp, smb_fname->base_name); 103+ if (!NT_STATUS_IS_OK(status)) { 104+ return status; 105+ } 106+ 107+ 108 /* For now setting EAs on streams isn't supported. */ 109 fname = smb_fname->base_name; 110 111@@ -4931,6 +4972,13 @@ NTSTATUS smbd_do_qfilepathinfo(connectio 112 uint16 num_file_acls = 0; 113 uint16 num_def_acls = 0; 114 115+ status = refuse_symlink(conn, 116+ fsp, 117+ smb_fname->base_name); 118+ if (!NT_STATUS_IS_OK(status)) { 119+ return status; 120+ } 121+ 122 if (fsp && fsp->fh->fd != -1) { 123 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp); 124 } else { 125@@ -6452,6 +6500,7 @@ static NTSTATUS smb_set_posix_acl(connec 126 uint16 num_def_acls; 127 bool valid_file_acls = True; 128 bool valid_def_acls = True; 129+ NTSTATUS status; 130 131 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) { 132 return NT_STATUS_INVALID_PARAMETER; 133@@ -6479,6 +6528,11 @@ static NTSTATUS smb_set_posix_acl(connec 134 return NT_STATUS_INVALID_PARAMETER; 135 } 136 137+ status = refuse_symlink(conn, fsp, smb_fname->base_name); 138+ if (!NT_STATUS_IS_OK(status)) { 139+ return status; 140+ } 141+ 142 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n", 143 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp), 144 (unsigned int)num_file_acls, 145--- a/source3/smbd/nttrans.c 146+++ b/source3/smbd/nttrans.c 147@@ -877,6 +877,12 @@ NTSTATUS set_sd(files_struct *fsp, struc 148 return NT_STATUS_OK; 149 } 150 151+ if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) { 152+ DEBUG(10, ("ACL set on symlink %s denied.\n", 153+ fsp_str_dbg(fsp))); 154+ return NT_STATUS_ACCESS_DENIED; 155+ } 156+ 157 if (psd->owner_sid == NULL) { 158 security_info_sent &= ~SECINFO_OWNER; 159 } 160@@ -1925,6 +1931,12 @@ NTSTATUS smbd_do_query_security_desc(con 161 return NT_STATUS_ACCESS_DENIED; 162 } 163 164+ if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) { 165+ DEBUG(10, ("ACL get on symlink %s denied.\n", 166+ fsp_str_dbg(fsp))); 167+ return NT_STATUS_ACCESS_DENIED; 168+ } 169+ 170 if (security_info_wanted & (SECINFO_DACL|SECINFO_OWNER| 171 SECINFO_GROUP|SECINFO_SACL)) { 172 /* Don't return SECINFO_LABEL if anything else was 173