aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/services/samba36/patches/015-patch-cve-2015-7560.patch
blob: 6ce8e2f9b74c109c8ebfc9940b16f00d58d08adf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
From eb27f9b7bf9c1dc902d9545eecf805831bd4e46c Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Tue, 5 Jan 2016 11:18:12 -0800
Subject: [PATCH 1/8] CVE-2015-7560: s3: smbd: Add refuse_symlink() function
 that can be used to prevent operations on a symlink.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11648

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
---
 source3/smbd/trans2.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -51,6 +51,34 @@ static char *store_file_unix_basic_info2
 				files_struct *fsp,
 				const SMB_STRUCT_STAT *psbuf);
 
+/****************************************************************************
+ Check if an open file handle or pathname is a symlink.
+****************************************************************************/
+
+static NTSTATUS refuse_symlink(connection_struct *conn,
+			const files_struct *fsp,
+			const char *name)
+{
+	SMB_STRUCT_STAT sbuf;
+	const SMB_STRUCT_STAT *pst = NULL;
+
+	if (fsp) {
+		pst = &fsp->fsp_name->st;
+	} else {
+		int ret = vfs_stat_smb_fname(conn,
+				name,
+				&sbuf);
+		if (ret == -1) {
+			return map_nt_error_from_unix(errno);
+		}
+		pst = &sbuf;
+	}
+	if (S_ISLNK(pst->st_ex_mode)) {
+		return NT_STATUS_ACCESS_DENIED;
+	}
+	return NT_STATUS_OK;
+}
+
 /********************************************************************
  Roundup a value to the nearest allocation roundup size boundary.
  Only do this for Windows clients.
@@ -181,12 +209,22 @@ NTSTATUS get_ea_names_from_file(TALLOC_C
 	char **names, **tmp;
 	size_t num_names;
 	ssize_t sizeret = -1;
+	NTSTATUS status;
+
+	if (pnames) {
+		*pnames = NULL;
+	}
+	*pnum_names = 0;
 
 	if (!lp_ea_support(SNUM(conn))) {
-		if (pnames) {
-			*pnames = NULL;
-		}
-		*pnum_names = 0;
+		return NT_STATUS_OK;
+	}
+
+	status = refuse_symlink(conn, fsp, fname);
+	if (!NT_STATUS_IS_OK(status)) {
+		/*
+		 * Just return no EA's on a symlink.
+		 */
 		return NT_STATUS_OK;
 	}
 
@@ -236,10 +274,6 @@ NTSTATUS get_ea_names_from_file(TALLOC_C
 
 	if (sizeret == 0) {
 		TALLOC_FREE(names);
-		if (pnames) {
-			*pnames = NULL;
-		}
-		*pnum_names = 0;
 		return NT_STATUS_OK;
 	}
 
@@ -550,6 +584,7 @@ NTSTATUS set_ea(connection_struct *conn,
 		const struct smb_filename *smb_fname, struct ea_list *ea_list)
 {
 	char *fname = NULL;
+	NTSTATUS status;
 
 	if (!lp_ea_support(SNUM(conn))) {
 		return NT_STATUS_EAS_NOT_SUPPORTED;
@@ -559,6 +594,12 @@ NTSTATUS set_ea(connection_struct *conn,
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
+	status = refuse_symlink(conn, fsp, smb_fname->base_name);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+
 	/* For now setting EAs on streams isn't supported. */
 	fname = smb_fname->base_name;
 
@@ -4931,6 +4972,13 @@ NTSTATUS smbd_do_qfilepathinfo(connectio
 				uint16 num_file_acls = 0;
 				uint16 num_def_acls = 0;
 
+				status = refuse_symlink(conn,
+						fsp,
+						smb_fname->base_name);
+				if (!NT_STATUS_IS_OK(status)) {
+					return status;
+				}
+
 				if (fsp && fsp->fh->fd != -1) {
 					file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
 				} else {
@@ -6452,6 +6500,7 @@ static NTSTATUS smb_set_posix_acl(connec
 	uint16 num_def_acls;
 	bool valid_file_acls = True;
 	bool valid_def_acls = True;
+	NTSTATUS status;
 
 	if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
 		return NT_STATUS_INVALID_PARAMETER;
@@ -6479,6 +6528,11 @@ static NTSTATUS smb_set_posix_acl(connec
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
+	status = refuse_symlink(conn, fsp, smb_fname->base_name);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
 	DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
 		smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
 		(unsigned int)num_file_acls,
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -877,6 +877,12 @@ NTSTATUS set_sd(files_struct *fsp, struc
 		return NT_STATUS_OK;
 	}
 
+	if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
+		DEBUG(10, ("ACL set on symlink %s denied.\n",
+			fsp_str_dbg(fsp)));
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
 	if (psd->owner_sid == NULL) {
 		security_info_sent &= ~SECINFO_OWNER;
 	}
@@ -1925,6 +1931,12 @@ NTSTATUS smbd_do_query_security_desc(con
 		return NT_STATUS_ACCESS_DENIED;
 	}
 
+	if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
+		DEBUG(10, ("ACL get on symlink %s denied.\n",
+			fsp_str_dbg(fsp)));
+		return NT_STATUS_ACCESS_DENIED;
+	}
+
 	if (security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|
 			SECINFO_GROUP|SECINFO_SACL)) {
 		/* Don't return SECINFO_LABEL if anything else was