summarylogtreecommitdiffstats
path: root/ntfs-3g_fix.patch
blob: 517d5bedfcfc95f74d4c75070f005b9954977d7e (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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
diff --git a/include/ntfs-3g/layout.h b/include/ntfs-3g/layout.h
index 98380de..564167c 100644
--- a/include/ntfs-3g/layout.h
+++ b/include/ntfs-3g/layout.h
@@ -1406,28 +1406,52 @@ typedef enum {
  * enum ACE_TYPES - The predefined ACE types (8-bit, see below).
  */
 typedef enum {
-	ACCESS_MIN_MS_ACE_TYPE		= 0,
-	ACCESS_ALLOWED_ACE_TYPE		= 0,
-	ACCESS_DENIED_ACE_TYPE		= 1,
-	SYSTEM_AUDIT_ACE_TYPE		= 2,
-	SYSTEM_ALARM_ACE_TYPE		= 3, /* Not implemented as of Win2k. */
-	ACCESS_MAX_MS_V2_ACE_TYPE	= 3,
-
-	ACCESS_ALLOWED_COMPOUND_ACE_TYPE= 4,
-	ACCESS_MAX_MS_V3_ACE_TYPE	= 4,
-
-	/* The following are Win2k only. */
-	ACCESS_MIN_MS_OBJECT_ACE_TYPE	= 5,
-	ACCESS_ALLOWED_OBJECT_ACE_TYPE	= 5,
-	ACCESS_DENIED_OBJECT_ACE_TYPE	= 6,
-	SYSTEM_AUDIT_OBJECT_ACE_TYPE	= 7,
-	SYSTEM_ALARM_OBJECT_ACE_TYPE	= 8,
-	ACCESS_MAX_MS_OBJECT_ACE_TYPE	= 8,
-
-	ACCESS_MAX_MS_V4_ACE_TYPE	= 8,
-
-	/* This one is for WinNT&2k. */
-	ACCESS_MAX_MS_ACE_TYPE		= 8,
+	ACCESS_MIN_MS_ACE_TYPE			= 0,
+	ACCESS_ALLOWED_ACE_TYPE			= 0,
+	ACCESS_DENIED_ACE_TYPE			= 1,
+	SYSTEM_AUDIT_ACE_TYPE			= 2,
+	SYSTEM_ALARM_ACE_TYPE			= 3, /* reserved */
+	ACCESS_MAX_MS_V2_ACE_TYPE		= 3,
+
+	ACCESS_ALLOWED_COMPOUND_ACE_TYPE	= 4, /* reserved */
+	ACCESS_MAX_MS_V3_ACE_TYPE		= 4,
+
+	/* Win2k and later */
+	ACCESS_MIN_MS_OBJECT_ACE_TYPE		= 5,
+	ACCESS_ALLOWED_OBJECT_ACE_TYPE		= 5,
+	ACCESS_DENIED_OBJECT_ACE_TYPE		= 6,
+	SYSTEM_AUDIT_OBJECT_ACE_TYPE		= 7,
+	SYSTEM_ALARM_OBJECT_ACE_TYPE		= 8, /* reserved */
+	ACCESS_MAX_MS_OBJECT_ACE_TYPE		= 8,
+
+	ACCESS_MAX_MS_V4_ACE_TYPE		= 8,
+
+	/* Apparently, this was the max type in Win2k, but for some reason MS
+	 * chose not to update this constant in later Windows versions */
+	ACCESS_MAX_MS_ACE_TYPE			= 8,
+
+	/* Windows XP and later */
+	ACCESS_ALLOWED_CALLBACK_ACE_TYPE	= 9,
+	ACCESS_DENIED_CALLBACK_ACE_TYPE		= 10,
+	ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE	= 11,
+	ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE	= 12,
+	SYSTEM_AUDIT_CALLBACK_ACE_TYPE		= 13,
+	SYSTEM_ALARM_CALLBACK_ACE_TYPE		= 14, /* reserved */
+	SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE   = 15,
+	SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE   = 16, /* reserved */
+
+	/* Windows Vista and later */
+	SYSTEM_MANDATORY_LABEL_ACE_TYPE		= 17,
+
+	/* Windows 8 and later */
+	SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE	= 18,
+	SYSTEM_SCOPED_POLICY_ID_ACE_TYPE	= 19,
+
+	/* Windows 10 and later */
+	SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE	= 20,
+
+	ACCESS_MAX_MS_V5_ACE_TYPE		= 20,
+
 } __attribute__((__packed__)) ACE_TYPES;
 
 /**
@@ -1628,9 +1652,7 @@ typedef struct {
  */
 
 /**
- * struct ACCESS_DENIED_ACE -
- *
- * ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE, SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE
+ * struct ACCESS_ALLOWED_ACE, etc. - Base structure for all regular ACEs
  */
 typedef struct {
 /*  0	ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */
@@ -1641,7 +1663,15 @@ typedef struct {
 /*  4*/	ACCESS_MASK mask;	/* Access mask associated with the ACE. */
 /*  8*/	SID sid;		/* The SID associated with the ACE. */
 } __attribute__((__packed__)) ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE,
-			       SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE;
+			       SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE,
+			       ACCESS_ALLOWED_CALLBACK_ACE,
+			       ACCESS_DENIED_CALLBACK_ACE,
+			       SYSTEM_AUDIT_CALLBACK_ACE,
+			       SYSTEM_ALARM_CALLBACK_ACE,
+			       SYSTEM_MANDATORY_LABEL_ACE,
+			       SYSTEM_RESOURCE_ATTRIBUTE_ACE,
+			       SYSTEM_SCOPED_POLICY_ID_ACE,
+			       SYSTEM_PROCESS_TRUST_LABEL_ACE;
 
 /**
  * enum OBJECT_ACE_FLAGS - The object ACE flags (32-bit).
@@ -1652,7 +1682,7 @@ typedef enum {
 } OBJECT_ACE_FLAGS;
 
 /**
- * struct ACCESS_ALLOWED_OBJECT_ACE -
+ * struct ACCESS_ALLOWED_OBJECT_ACE, etc. - Base structure for all object ACEs
  */
 typedef struct {
 /*  0	ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */
@@ -1668,7 +1698,11 @@ typedef struct {
 } __attribute__((__packed__)) ACCESS_ALLOWED_OBJECT_ACE,
 			       ACCESS_DENIED_OBJECT_ACE,
 			       SYSTEM_AUDIT_OBJECT_ACE,
-			       SYSTEM_ALARM_OBJECT_ACE;
+			       SYSTEM_ALARM_OBJECT_ACE,
+			       ACCESS_ALLOWED_CALLBACK_OBJECT_ACE,
+			       ACCESS_DENIED_CALLBACK_OBJECT_ACE,
+			       SYSTEM_AUDIT_CALLBACK_OBJECT_ACE,
+			       SYSTEM_ALARM_CALLBACK_OBJECT_ACE;
 
 /**
  * struct ACL - An ACL is an access-control list (ACL).
diff --git a/libntfs-3g/acls.c b/libntfs-3g/acls.c
index b91e041..06c44d9 100644
--- a/libntfs-3g/acls.c
+++ b/libntfs-3g/acls.c
@@ -536,45 +536,95 @@ gid_t ntfs_find_group(const struct MAPPING* groupmapping, const SID * gsid)
 }
 
 /*
+ *		Does the ACE have the same format as ACCESS_ALLOWED_ACE?
+ */
+
+static BOOL is_regular_ace(const ACE_HEADER *pace)
+{
+	switch (pace->type) {
+	case ACCESS_ALLOWED_ACE_TYPE:
+	case ACCESS_DENIED_ACE_TYPE:
+	case SYSTEM_AUDIT_ACE_TYPE:
+	case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
+	case ACCESS_DENIED_CALLBACK_ACE_TYPE:
+	case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
+	case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
+	case SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE:
+	case SYSTEM_SCOPED_POLICY_ID_ACE_TYPE:
+	case SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE:
+		return TRUE;
+	default:
+		return FALSE;
+	}
+}
+
+/*
+ *		Does the ACE have the same format as ACCESS_ALLOWED_OBJECT_ACE?
+ */
+
+static BOOL is_object_ace(const ACE_HEADER *pace)
+{
+	switch (pace->type) {
+	case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
+	case ACCESS_DENIED_OBJECT_ACE_TYPE:
+	case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
+	case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
+	case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
+	case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
+		return TRUE;
+	default:
+		return FALSE;
+	}
+}
+
+/*
  *		Check the validity of the ACEs in a DACL or SACL
+ *
+ *	If an ACE is recognized, we validate its SID.
+ *	Otherwise, we validate its size only.
  */
 
 static BOOL valid_acl(const ACL *pacl, unsigned int end)
 {
-	const ACCESS_ALLOWED_ACE *pace;
-	unsigned int offace;
-	unsigned int acecnt;
-	unsigned int acesz;
-	unsigned int nace;
-	unsigned int wantsz;
-	BOOL ok;
+	unsigned int ace_count;
+	unsigned int ace_offset;
+	unsigned int ace_size;
+	unsigned int sid_offset;
+	const ACE_HEADER *pace;
+	const SID *psid;
 
-	ok = TRUE;
-	acecnt = le16_to_cpu(pacl->ace_count);
-	offace = sizeof(ACL);
-	for (nace = 0; (nace < acecnt) && ok; nace++) {
-		/* be sure the beginning is within range */
-		if ((offace + sizeof(ACCESS_ALLOWED_ACE)) > end)
-			ok = FALSE;
-		else {
-			pace = (const ACCESS_ALLOWED_ACE*)
-				&((const char*)pacl)[offace];
-			acesz = le16_to_cpu(pace->size);
-			if (((offace + acesz) > end)
-			   || !ntfs_valid_sid(&pace->sid))
-				 ok = FALSE;
-			else {
-				/* Win10 may insert garbage in the last ACE */
-				wantsz = ntfs_sid_size(&pace->sid) + 8;
-				if (((nace < (acecnt - 1))
-					&& (wantsz != acesz))
-				    || (wantsz > acesz))
-					ok = FALSE;
-			}
-			offace += acesz;
-		}
+	for (ace_count = le16_to_cpu(pacl->ace_count), ace_offset = sizeof(ACL);
+	     ace_count != 0;
+	     ace_count--, ace_offset += ace_size)
+	{
+		if (sizeof(ACE_HEADER) > end - ace_offset)
+			return FALSE;
+
+		pace = (const ACE_HEADER *)((char *)pacl + ace_offset);
+		ace_size = le16_to_cpu(pace->size);
+		if (ace_size < sizeof(ACE_HEADER) ||
+		    ace_size > end - ace_offset)
+			return FALSE;
+
+		if (is_regular_ace(pace))
+			sid_offset = offsetof(ACCESS_ALLOWED_ACE, sid);
+		else if (is_object_ace(pace))
+			sid_offset = offsetof(ACCESS_ALLOWED_OBJECT_ACE, sid);
+		else
+			continue;
+
+		if (ace_size < sid_offset + sizeof(SID))
+			return FALSE;
+
+		psid = (const SID *)((char *)pace + sid_offset);
+
+		/* Note: there may be additional data after the SID. */
+		if (!ntfs_valid_sid(psid) ||
+		    ace_size < sid_offset + ntfs_sid_size(psid))
+			return FALSE;
 	}
-	return (ok);
+
+	return TRUE;
 }
 
 /*