aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo/file.c')
-rw-r--r--security/tomoyo/file.c954
1 files changed, 389 insertions, 565 deletions
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index d64e8ecb6fb..743c35f5084 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -1,80 +1,51 @@
1/* 1/*
2 * security/tomoyo/file.c 2 * security/tomoyo/file.c
3 * 3 *
4 * Pathname restriction functions. 4 * Copyright (C) 2005-2011 NTT DATA CORPORATION
5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 */ 5 */
8 6
9#include "common.h" 7#include "common.h"
10#include <linux/slab.h> 8#include <linux/slab.h>
11 9
12/* Keyword array for operations with one pathname. */ 10/*
13const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { 11 * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
14 [TOMOYO_TYPE_READ_WRITE] = "read/write", 12 */
15 [TOMOYO_TYPE_EXECUTE] = "execute",
16 [TOMOYO_TYPE_READ] = "read",
17 [TOMOYO_TYPE_WRITE] = "write",
18 [TOMOYO_TYPE_UNLINK] = "unlink",
19 [TOMOYO_TYPE_RMDIR] = "rmdir",
20 [TOMOYO_TYPE_TRUNCATE] = "truncate",
21 [TOMOYO_TYPE_SYMLINK] = "symlink",
22 [TOMOYO_TYPE_REWRITE] = "rewrite",
23 [TOMOYO_TYPE_CHROOT] = "chroot",
24 [TOMOYO_TYPE_UMOUNT] = "unmount",
25};
26
27/* Keyword array for operations with one pathname and three numbers. */
28const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION] = {
29 [TOMOYO_TYPE_MKBLOCK] = "mkblock",
30 [TOMOYO_TYPE_MKCHAR] = "mkchar",
31};
32
33/* Keyword array for operations with two pathnames. */
34const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = {
35 [TOMOYO_TYPE_LINK] = "link",
36 [TOMOYO_TYPE_RENAME] = "rename",
37 [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root",
38};
39
40/* Keyword array for operations with one pathname and one number. */
41const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
42 [TOMOYO_TYPE_CREATE] = "create",
43 [TOMOYO_TYPE_MKDIR] = "mkdir",
44 [TOMOYO_TYPE_MKFIFO] = "mkfifo",
45 [TOMOYO_TYPE_MKSOCK] = "mksock",
46 [TOMOYO_TYPE_IOCTL] = "ioctl",
47 [TOMOYO_TYPE_CHMOD] = "chmod",
48 [TOMOYO_TYPE_CHOWN] = "chown",
49 [TOMOYO_TYPE_CHGRP] = "chgrp",
50};
51
52static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { 13static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
53 [TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN,
54 [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, 14 [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE,
55 [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, 15 [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN,
56 [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, 16 [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN,
17 [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN,
57 [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, 18 [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK,
19 [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR,
58 [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, 20 [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR,
59 [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, 21 [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE,
60 [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, 22 [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK,
61 [TOMOYO_TYPE_REWRITE] = TOMOYO_MAC_FILE_REWRITE,
62 [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, 23 [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT,
63 [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, 24 [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT,
64}; 25};
65 26
66static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { 27/*
28 * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
29 */
30const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
67 [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, 31 [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
68 [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, 32 [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR,
69}; 33};
70 34
71static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { 35/*
36 * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
37 */
38const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
72 [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, 39 [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK,
73 [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, 40 [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME,
74 [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, 41 [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
75}; 42};
76 43
77static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { 44/*
45 * Mapping table from "enum tomoyo_path_number_acl_index" to
46 * "enum tomoyo_mac_index".
47 */
48const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
78 [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, 49 [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
79 [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, 50 [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR,
80 [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO, 51 [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
@@ -85,41 +56,76 @@ static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
85 [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, 56 [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP,
86}; 57};
87 58
59/**
60 * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union".
61 *
62 * @ptr: Pointer to "struct tomoyo_name_union".
63 *
64 * Returns nothing.
65 */
88void tomoyo_put_name_union(struct tomoyo_name_union *ptr) 66void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
89{ 67{
90 if (!ptr) 68 tomoyo_put_group(ptr->group);
91 return; 69 tomoyo_put_name(ptr->filename);
92 if (ptr->is_group)
93 tomoyo_put_group(ptr->group);
94 else
95 tomoyo_put_name(ptr->filename);
96} 70}
97 71
72/**
73 * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not.
74 *
75 * @name: Pointer to "struct tomoyo_path_info".
76 * @ptr: Pointer to "struct tomoyo_name_union".
77 *
78 * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise.
79 */
98const struct tomoyo_path_info * 80const struct tomoyo_path_info *
99tomoyo_compare_name_union(const struct tomoyo_path_info *name, 81tomoyo_compare_name_union(const struct tomoyo_path_info *name,
100 const struct tomoyo_name_union *ptr) 82 const struct tomoyo_name_union *ptr)
101{ 83{
102 if (ptr->is_group) 84 if (ptr->group)
103 return tomoyo_path_matches_group(name, ptr->group); 85 return tomoyo_path_matches_group(name, ptr->group);
104 if (tomoyo_path_matches_pattern(name, ptr->filename)) 86 if (tomoyo_path_matches_pattern(name, ptr->filename))
105 return ptr->filename; 87 return ptr->filename;
106 return NULL; 88 return NULL;
107} 89}
108 90
91/**
92 * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union".
93 *
94 * @ptr: Pointer to "struct tomoyo_number_union".
95 *
96 * Returns nothing.
97 */
109void tomoyo_put_number_union(struct tomoyo_number_union *ptr) 98void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
110{ 99{
111 if (ptr && ptr->is_group) 100 tomoyo_put_group(ptr->group);
112 tomoyo_put_group(ptr->group);
113} 101}
114 102
103/**
104 * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not.
105 *
106 * @value: Number to check.
107 * @ptr: Pointer to "struct tomoyo_number_union".
108 *
109 * Returns true if @value matches @ptr, false otherwise.
110 */
115bool tomoyo_compare_number_union(const unsigned long value, 111bool tomoyo_compare_number_union(const unsigned long value,
116 const struct tomoyo_number_union *ptr) 112 const struct tomoyo_number_union *ptr)
117{ 113{
118 if (ptr->is_group) 114 if (ptr->group)
119 return tomoyo_number_matches_group(value, value, ptr->group); 115 return tomoyo_number_matches_group(value, value, ptr->group);
120 return value >= ptr->values[0] && value <= ptr->values[1]; 116 return value >= ptr->values[0] && value <= ptr->values[1];
121} 117}
122 118
119/**
120 * tomoyo_add_slash - Add trailing '/' if needed.
121 *
122 * @buf: Pointer to "struct tomoyo_path_info".
123 *
124 * Returns nothing.
125 *
126 * @buf must be generated by tomoyo_encode() because this function does not
127 * allocate memory for adding '/'.
128 */
123static void tomoyo_add_slash(struct tomoyo_path_info *buf) 129static void tomoyo_add_slash(struct tomoyo_path_info *buf)
124{ 130{
125 if (buf->is_dir) 131 if (buf->is_dir)
@@ -132,24 +138,6 @@ static void tomoyo_add_slash(struct tomoyo_path_info *buf)
132} 138}
133 139
134/** 140/**
135 * tomoyo_strendswith - Check whether the token ends with the given token.
136 *
137 * @name: The token to check.
138 * @tail: The token to find.
139 *
140 * Returns true if @name ends with @tail, false otherwise.
141 */
142static bool tomoyo_strendswith(const char *name, const char *tail)
143{
144 int len;
145
146 if (!name || !tail)
147 return false;
148 len = strlen(name) - strlen(tail);
149 return len >= 0 && !strcmp(name + len, tail);
150}
151
152/**
153 * tomoyo_get_realpath - Get realpath. 141 * tomoyo_get_realpath - Get realpath.
154 * 142 *
155 * @buf: Pointer to "struct tomoyo_path_info". 143 * @buf: Pointer to "struct tomoyo_path_info".
@@ -164,7 +152,7 @@ static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
164 tomoyo_fill_path_info(buf); 152 tomoyo_fill_path_info(buf);
165 return true; 153 return true;
166 } 154 }
167 return false; 155 return false;
168} 156}
169 157
170/** 158/**
@@ -176,13 +164,9 @@ static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
176 */ 164 */
177static int tomoyo_audit_path_log(struct tomoyo_request_info *r) 165static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
178{ 166{
179 const char *operation = tomoyo_path_keyword[r->param.path.operation]; 167 return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword
180 const struct tomoyo_path_info *filename = r->param.path.filename; 168 [r->param.path.operation],
181 if (r->granted) 169 r->param.path.filename->name);
182 return 0;
183 tomoyo_warn_log(r, "%s %s", operation, filename->name);
184 return tomoyo_supervisor(r, "allow_%s %s\n", operation,
185 tomoyo_pattern(filename));
186} 170}
187 171
188/** 172/**
@@ -194,16 +178,10 @@ static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
194 */ 178 */
195static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) 179static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
196{ 180{
197 const char *operation = tomoyo_path2_keyword[r->param.path2.operation]; 181 return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
198 const struct tomoyo_path_info *filename1 = r->param.path2.filename1; 182 [tomoyo_pp2mac[r->param.path2.operation]],
199 const struct tomoyo_path_info *filename2 = r->param.path2.filename2; 183 r->param.path2.filename1->name,
200 if (r->granted) 184 r->param.path2.filename2->name);
201 return 0;
202 tomoyo_warn_log(r, "%s %s %s", operation, filename1->name,
203 filename2->name);
204 return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
205 tomoyo_pattern(filename1),
206 tomoyo_pattern(filename2));
207} 185}
208 186
209/** 187/**
@@ -215,24 +193,18 @@ static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
215 */ 193 */
216static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) 194static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
217{ 195{
218 const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation]; 196 return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n",
219 const struct tomoyo_path_info *filename = r->param.mkdev.filename; 197 tomoyo_mac_keywords
220 const unsigned int major = r->param.mkdev.major; 198 [tomoyo_pnnn2mac[r->param.mkdev.operation]],
221 const unsigned int minor = r->param.mkdev.minor; 199 r->param.mkdev.filename->name,
222 const unsigned int mode = r->param.mkdev.mode; 200 r->param.mkdev.mode, r->param.mkdev.major,
223 if (r->granted) 201 r->param.mkdev.minor);
224 return 0;
225 tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode,
226 major, minor);
227 return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation,
228 tomoyo_pattern(filename), mode, major, minor);
229} 202}
230 203
231/** 204/**
232 * tomoyo_audit_path_number_log - Audit path/number request log. 205 * tomoyo_audit_path_number_log - Audit path/number request log.
233 * 206 *
234 * @r: Pointer to "struct tomoyo_request_info". 207 * @r: Pointer to "struct tomoyo_request_info".
235 * @error: Error code.
236 * 208 *
237 * Returns 0 on success, negative value otherwise. 209 * Returns 0 on success, negative value otherwise.
238 */ 210 */
@@ -240,11 +212,7 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
240{ 212{
241 const u8 type = r->param.path_number.operation; 213 const u8 type = r->param.path_number.operation;
242 u8 radix; 214 u8 radix;
243 const struct tomoyo_path_info *filename = r->param.path_number.filename;
244 const char *operation = tomoyo_path_number_keyword[type];
245 char buffer[64]; 215 char buffer[64];
246 if (r->granted)
247 return 0;
248 switch (type) { 216 switch (type) {
249 case TOMOYO_TYPE_CREATE: 217 case TOMOYO_TYPE_CREATE:
250 case TOMOYO_TYPE_MKDIR: 218 case TOMOYO_TYPE_MKDIR:
@@ -262,251 +230,23 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
262 } 230 }
263 tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number, 231 tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
264 radix); 232 radix);
265 tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); 233 return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
266 return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, 234 [tomoyo_pn2mac[type]],
267 tomoyo_pattern(filename), buffer); 235 r->param.path_number.filename->name, buffer);
268}
269
270static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a,
271 const struct tomoyo_acl_head *b)
272{
273 return container_of(a, struct tomoyo_readable_file,
274 head)->filename ==
275 container_of(b, struct tomoyo_readable_file,
276 head)->filename;
277}
278
279/**
280 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_readable_file" list.
281 *
282 * @filename: Filename unconditionally permitted to open() for reading.
283 * @is_delete: True if it is a delete request.
284 *
285 * Returns 0 on success, negative value otherwise.
286 *
287 * Caller holds tomoyo_read_lock().
288 */
289static int tomoyo_update_globally_readable_entry(const char *filename,
290 const bool is_delete)
291{
292 struct tomoyo_readable_file e = { };
293 int error;
294
295 if (!tomoyo_correct_word(filename))
296 return -EINVAL;
297 e.filename = tomoyo_get_name(filename);
298 if (!e.filename)
299 return -ENOMEM;
300 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
301 &tomoyo_policy_list
302 [TOMOYO_ID_GLOBALLY_READABLE],
303 tomoyo_same_globally_readable);
304 tomoyo_put_name(e.filename);
305 return error;
306}
307
308/**
309 * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
310 *
311 * @filename: The filename to check.
312 *
313 * Returns true if any domain can open @filename for reading, false otherwise.
314 *
315 * Caller holds tomoyo_read_lock().
316 */
317static bool tomoyo_globally_readable_file(const struct tomoyo_path_info *
318 filename)
319{
320 struct tomoyo_readable_file *ptr;
321 bool found = false;
322
323 list_for_each_entry_rcu(ptr, &tomoyo_policy_list
324 [TOMOYO_ID_GLOBALLY_READABLE], head.list) {
325 if (!ptr->head.is_deleted &&
326 tomoyo_path_matches_pattern(filename, ptr->filename)) {
327 found = true;
328 break;
329 }
330 }
331 return found;
332}
333
334/**
335 * tomoyo_write_globally_readable - Write "struct tomoyo_readable_file" list.
336 *
337 * @data: String to parse.
338 * @is_delete: True if it is a delete request.
339 *
340 * Returns 0 on success, negative value otherwise.
341 *
342 * Caller holds tomoyo_read_lock().
343 */
344int tomoyo_write_globally_readable(char *data, const bool is_delete)
345{
346 return tomoyo_update_globally_readable_entry(data, is_delete);
347}
348
349static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a,
350 const struct tomoyo_acl_head *b)
351{
352 return container_of(a, struct tomoyo_no_pattern, head)->pattern ==
353 container_of(b, struct tomoyo_no_pattern, head)->pattern;
354}
355
356/**
357 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_no_pattern" list.
358 *
359 * @pattern: Pathname pattern.
360 * @is_delete: True if it is a delete request.
361 *
362 * Returns 0 on success, negative value otherwise.
363 *
364 * Caller holds tomoyo_read_lock().
365 */
366static int tomoyo_update_file_pattern_entry(const char *pattern,
367 const bool is_delete)
368{
369 struct tomoyo_no_pattern e = { };
370 int error;
371
372 if (!tomoyo_correct_word(pattern))
373 return -EINVAL;
374 e.pattern = tomoyo_get_name(pattern);
375 if (!e.pattern)
376 return -ENOMEM;
377 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
378 &tomoyo_policy_list[TOMOYO_ID_PATTERN],
379 tomoyo_same_pattern);
380 tomoyo_put_name(e.pattern);
381 return error;
382}
383
384/**
385 * tomoyo_pattern - Get patterned pathname.
386 *
387 * @filename: The filename to find patterned pathname.
388 *
389 * Returns pointer to pathname pattern if matched, @filename otherwise.
390 *
391 * Caller holds tomoyo_read_lock().
392 */
393const char *tomoyo_pattern(const struct tomoyo_path_info *filename)
394{
395 struct tomoyo_no_pattern *ptr;
396 const struct tomoyo_path_info *pattern = NULL;
397
398 list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN],
399 head.list) {
400 if (ptr->head.is_deleted)
401 continue;
402 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
403 continue;
404 pattern = ptr->pattern;
405 if (tomoyo_strendswith(pattern->name, "/\\*")) {
406 /* Do nothing. Try to find the better match. */
407 } else {
408 /* This would be the better match. Use this. */
409 break;
410 }
411 }
412 if (pattern)
413 filename = pattern;
414 return filename->name;
415}
416
417/**
418 * tomoyo_write_pattern - Write "struct tomoyo_no_pattern" list.
419 *
420 * @data: String to parse.
421 * @is_delete: True if it is a delete request.
422 *
423 * Returns 0 on success, negative value otherwise.
424 *
425 * Caller holds tomoyo_read_lock().
426 */
427int tomoyo_write_pattern(char *data, const bool is_delete)
428{
429 return tomoyo_update_file_pattern_entry(data, is_delete);
430}
431
432static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a,
433 const struct tomoyo_acl_head *b)
434{
435 return container_of(a, struct tomoyo_no_rewrite, head)->pattern
436 == container_of(b, struct tomoyo_no_rewrite, head)
437 ->pattern;
438}
439
440/**
441 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite" list.
442 *
443 * @pattern: Pathname pattern that are not rewritable by default.
444 * @is_delete: True if it is a delete request.
445 *
446 * Returns 0 on success, negative value otherwise.
447 *
448 * Caller holds tomoyo_read_lock().
449 */
450static int tomoyo_update_no_rewrite_entry(const char *pattern,
451 const bool is_delete)
452{
453 struct tomoyo_no_rewrite e = { };
454 int error;
455
456 if (!tomoyo_correct_word(pattern))
457 return -EINVAL;
458 e.pattern = tomoyo_get_name(pattern);
459 if (!e.pattern)
460 return -ENOMEM;
461 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
462 &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
463 tomoyo_same_no_rewrite);
464 tomoyo_put_name(e.pattern);
465 return error;
466} 236}
467 237
468/** 238/**
469 * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. 239 * tomoyo_check_path_acl - Check permission for path operation.
470 * 240 *
471 * @filename: Filename to check. 241 * @r: Pointer to "struct tomoyo_request_info".
242 * @ptr: Pointer to "struct tomoyo_acl_info".
472 * 243 *
473 * Returns true if @filename is specified by "deny_rewrite" directive, 244 * Returns true if granted, false otherwise.
474 * false otherwise.
475 * 245 *
476 * Caller holds tomoyo_read_lock(). 246 * To be able to use wildcard for domain transition, this function sets
247 * matching entry on success. Since the caller holds tomoyo_read_lock(),
248 * it is safe to set matching entry.
477 */ 249 */
478static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename)
479{
480 struct tomoyo_no_rewrite *ptr;
481 bool found = false;
482
483 list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
484 head.list) {
485 if (ptr->head.is_deleted)
486 continue;
487 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
488 continue;
489 found = true;
490 break;
491 }
492 return found;
493}
494
495/**
496 * tomoyo_write_no_rewrite - Write "struct tomoyo_no_rewrite" list.
497 *
498 * @data: String to parse.
499 * @is_delete: True if it is a delete request.
500 *
501 * Returns 0 on success, negative value otherwise.
502 *
503 * Caller holds tomoyo_read_lock().
504 */
505int tomoyo_write_no_rewrite(char *data, const bool is_delete)
506{
507 return tomoyo_update_no_rewrite_entry(data, is_delete);
508}
509
510static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, 250static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
511 const struct tomoyo_acl_info *ptr) 251 const struct tomoyo_acl_info *ptr)
512{ 252{
@@ -521,6 +261,14 @@ static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
521 return false; 261 return false;
522} 262}
523 263
264/**
265 * tomoyo_check_path_number_acl - Check permission for path number operation.
266 *
267 * @r: Pointer to "struct tomoyo_request_info".
268 * @ptr: Pointer to "struct tomoyo_acl_info".
269 *
270 * Returns true if granted, false otherwise.
271 */
524static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, 272static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
525 const struct tomoyo_acl_info *ptr) 273 const struct tomoyo_acl_info *ptr)
526{ 274{
@@ -533,6 +281,14 @@ static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
533 &acl->name); 281 &acl->name);
534} 282}
535 283
284/**
285 * tomoyo_check_path2_acl - Check permission for path path operation.
286 *
287 * @r: Pointer to "struct tomoyo_request_info".
288 * @ptr: Pointer to "struct tomoyo_acl_info".
289 *
290 * Returns true if granted, false otherwise.
291 */
536static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, 292static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
537 const struct tomoyo_acl_info *ptr) 293 const struct tomoyo_acl_info *ptr)
538{ 294{
@@ -544,8 +300,16 @@ static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
544 &acl->name2); 300 &acl->name2);
545} 301}
546 302
303/**
304 * tomoyo_check_mkdev_acl - Check permission for path number number number operation.
305 *
306 * @r: Pointer to "struct tomoyo_request_info".
307 * @ptr: Pointer to "struct tomoyo_acl_info".
308 *
309 * Returns true if granted, false otherwise.
310 */
547static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, 311static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
548 const struct tomoyo_acl_info *ptr) 312 const struct tomoyo_acl_info *ptr)
549{ 313{
550 const struct tomoyo_mkdev_acl *acl = 314 const struct tomoyo_mkdev_acl *acl =
551 container_of(ptr, typeof(*acl), head); 315 container_of(ptr, typeof(*acl), head);
@@ -560,15 +324,31 @@ static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
560 &acl->name); 324 &acl->name);
561} 325}
562 326
327/**
328 * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry.
329 *
330 * @a: Pointer to "struct tomoyo_acl_info".
331 * @b: Pointer to "struct tomoyo_acl_info".
332 *
333 * Returns true if @a == @b except permission bits, false otherwise.
334 */
563static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, 335static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
564 const struct tomoyo_acl_info *b) 336 const struct tomoyo_acl_info *b)
565{ 337{
566 const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); 338 const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
567 const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); 339 const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
568 return tomoyo_same_acl_head(&p1->head, &p2->head) && 340 return tomoyo_same_name_union(&p1->name, &p2->name);
569 tomoyo_same_name_union(&p1->name, &p2->name);
570} 341}
571 342
343/**
344 * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry.
345 *
346 * @a: Pointer to "struct tomoyo_acl_info".
347 * @b: Pointer to "struct tomoyo_acl_info".
348 * @is_delete: True for @a &= ~@b, false for @a |= @b.
349 *
350 * Returns true if @a is empty, false otherwise.
351 */
572static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, 352static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
573 struct tomoyo_acl_info *b, 353 struct tomoyo_acl_info *b,
574 const bool is_delete) 354 const bool is_delete)
@@ -577,19 +357,10 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
577 ->perm; 357 ->perm;
578 u16 perm = *a_perm; 358 u16 perm = *a_perm;
579 const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; 359 const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
580 if (is_delete) { 360 if (is_delete)
581 perm &= ~b_perm; 361 perm &= ~b_perm;
582 if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK) 362 else
583 perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
584 else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE)))
585 perm &= ~TOMOYO_RW_MASK;
586 } else {
587 perm |= b_perm; 363 perm |= b_perm;
588 if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK)
589 perm |= (1 << TOMOYO_TYPE_READ_WRITE);
590 else if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
591 perm |= TOMOYO_RW_MASK;
592 }
593 *a_perm = perm; 364 *a_perm = perm;
594 return !perm; 365 return !perm;
595} 366}
@@ -597,52 +368,62 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
597/** 368/**
598 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. 369 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
599 * 370 *
600 * @type: Type of operation. 371 * @perm: Permission.
601 * @filename: Filename. 372 * @param: Pointer to "struct tomoyo_acl_param".
602 * @domain: Pointer to "struct tomoyo_domain_info".
603 * @is_delete: True if it is a delete request.
604 * 373 *
605 * Returns 0 on success, negative value otherwise. 374 * Returns 0 on success, negative value otherwise.
606 * 375 *
607 * Caller holds tomoyo_read_lock(). 376 * Caller holds tomoyo_read_lock().
608 */ 377 */
609static int tomoyo_update_path_acl(const u8 type, const char *filename, 378static int tomoyo_update_path_acl(const u16 perm,
610 struct tomoyo_domain_info * const domain, 379 struct tomoyo_acl_param *param)
611 const bool is_delete)
612{ 380{
613 struct tomoyo_path_acl e = { 381 struct tomoyo_path_acl e = {
614 .head.type = TOMOYO_TYPE_PATH_ACL, 382 .head.type = TOMOYO_TYPE_PATH_ACL,
615 .perm = 1 << type 383 .perm = perm
616 }; 384 };
617 int error; 385 int error;
618 if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE)) 386 if (!tomoyo_parse_name_union(param, &e.name))
619 e.perm |= TOMOYO_RW_MASK; 387 error = -EINVAL;
620 if (!tomoyo_parse_name_union(filename, &e.name)) 388 else
621 return -EINVAL; 389 error = tomoyo_update_domain(&e.head, sizeof(e), param,
622 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 390 tomoyo_same_path_acl,
623 tomoyo_same_path_acl, 391 tomoyo_merge_path_acl);
624 tomoyo_merge_path_acl);
625 tomoyo_put_name_union(&e.name); 392 tomoyo_put_name_union(&e.name);
626 return error; 393 return error;
627} 394}
628 395
396/**
397 * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry.
398 *
399 * @a: Pointer to "struct tomoyo_acl_info".
400 * @b: Pointer to "struct tomoyo_acl_info".
401 *
402 * Returns true if @a == @b except permission bits, false otherwise.
403 */
629static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, 404static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
630 const struct tomoyo_acl_info *b) 405 const struct tomoyo_acl_info *b)
631{ 406{
632 const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), 407 const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
633 head); 408 const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
634 const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), 409 return tomoyo_same_name_union(&p1->name, &p2->name) &&
635 head); 410 tomoyo_same_number_union(&p1->mode, &p2->mode) &&
636 return tomoyo_same_acl_head(&p1->head, &p2->head) 411 tomoyo_same_number_union(&p1->major, &p2->major) &&
637 && tomoyo_same_name_union(&p1->name, &p2->name) 412 tomoyo_same_number_union(&p1->minor, &p2->minor);
638 && tomoyo_same_number_union(&p1->mode, &p2->mode)
639 && tomoyo_same_number_union(&p1->major, &p2->major)
640 && tomoyo_same_number_union(&p1->minor, &p2->minor);
641} 413}
642 414
415/**
416 * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry.
417 *
418 * @a: Pointer to "struct tomoyo_acl_info".
419 * @b: Pointer to "struct tomoyo_acl_info".
420 * @is_delete: True for @a &= ~@b, false for @a |= @b.
421 *
422 * Returns true if @a is empty, false otherwise.
423 */
643static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, 424static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
644 struct tomoyo_acl_info *b, 425 struct tomoyo_acl_info *b,
645 const bool is_delete) 426 const bool is_delete)
646{ 427{
647 u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, 428 u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
648 head)->perm; 429 head)->perm;
@@ -660,37 +441,30 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
660/** 441/**
661 * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. 442 * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
662 * 443 *
663 * @type: Type of operation. 444 * @perm: Permission.
664 * @filename: Filename. 445 * @param: Pointer to "struct tomoyo_acl_param".
665 * @mode: Create mode.
666 * @major: Device major number.
667 * @minor: Device minor number.
668 * @domain: Pointer to "struct tomoyo_domain_info".
669 * @is_delete: True if it is a delete request.
670 * 446 *
671 * Returns 0 on success, negative value otherwise. 447 * Returns 0 on success, negative value otherwise.
672 * 448 *
673 * Caller holds tomoyo_read_lock(). 449 * Caller holds tomoyo_read_lock().
674 */ 450 */
675static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, 451static int tomoyo_update_mkdev_acl(const u8 perm,
676 char *mode, char *major, char *minor, 452 struct tomoyo_acl_param *param)
677 struct tomoyo_domain_info * const
678 domain, const bool is_delete)
679{ 453{
680 struct tomoyo_mkdev_acl e = { 454 struct tomoyo_mkdev_acl e = {
681 .head.type = TOMOYO_TYPE_MKDEV_ACL, 455 .head.type = TOMOYO_TYPE_MKDEV_ACL,
682 .perm = 1 << type 456 .perm = perm
683 }; 457 };
684 int error = is_delete ? -ENOENT : -ENOMEM; 458 int error;
685 if (!tomoyo_parse_name_union(filename, &e.name) || 459 if (!tomoyo_parse_name_union(param, &e.name) ||
686 !tomoyo_parse_number_union(mode, &e.mode) || 460 !tomoyo_parse_number_union(param, &e.mode) ||
687 !tomoyo_parse_number_union(major, &e.major) || 461 !tomoyo_parse_number_union(param, &e.major) ||
688 !tomoyo_parse_number_union(minor, &e.minor)) 462 !tomoyo_parse_number_union(param, &e.minor))
689 goto out; 463 error = -EINVAL;
690 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 464 else
691 tomoyo_same_mkdev_acl, 465 error = tomoyo_update_domain(&e.head, sizeof(e), param,
692 tomoyo_merge_mkdev_acl); 466 tomoyo_same_mkdev_acl,
693 out: 467 tomoyo_merge_mkdev_acl);
694 tomoyo_put_name_union(&e.name); 468 tomoyo_put_name_union(&e.name);
695 tomoyo_put_number_union(&e.mode); 469 tomoyo_put_number_union(&e.mode);
696 tomoyo_put_number_union(&e.major); 470 tomoyo_put_number_union(&e.major);
@@ -698,16 +472,32 @@ static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
698 return error; 472 return error;
699} 473}
700 474
475/**
476 * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry.
477 *
478 * @a: Pointer to "struct tomoyo_acl_info".
479 * @b: Pointer to "struct tomoyo_acl_info".
480 *
481 * Returns true if @a == @b except permission bits, false otherwise.
482 */
701static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, 483static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
702 const struct tomoyo_acl_info *b) 484 const struct tomoyo_acl_info *b)
703{ 485{
704 const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); 486 const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
705 const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); 487 const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
706 return tomoyo_same_acl_head(&p1->head, &p2->head) 488 return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
707 && tomoyo_same_name_union(&p1->name1, &p2->name1) 489 tomoyo_same_name_union(&p1->name2, &p2->name2);
708 && tomoyo_same_name_union(&p1->name2, &p2->name2);
709} 490}
710 491
492/**
493 * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry.
494 *
495 * @a: Pointer to "struct tomoyo_acl_info".
496 * @b: Pointer to "struct tomoyo_acl_info".
497 * @is_delete: True for @a &= ~@b, false for @a |= @b.
498 *
499 * Returns true if @a is empty, false otherwise.
500 */
711static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, 501static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
712 struct tomoyo_acl_info *b, 502 struct tomoyo_acl_info *b,
713 const bool is_delete) 503 const bool is_delete)
@@ -727,33 +517,28 @@ static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
727/** 517/**
728 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. 518 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
729 * 519 *
730 * @type: Type of operation. 520 * @perm: Permission.
731 * @filename1: First filename. 521 * @param: Pointer to "struct tomoyo_acl_param".
732 * @filename2: Second filename.
733 * @domain: Pointer to "struct tomoyo_domain_info".
734 * @is_delete: True if it is a delete request.
735 * 522 *
736 * Returns 0 on success, negative value otherwise. 523 * Returns 0 on success, negative value otherwise.
737 * 524 *
738 * Caller holds tomoyo_read_lock(). 525 * Caller holds tomoyo_read_lock().
739 */ 526 */
740static int tomoyo_update_path2_acl(const u8 type, const char *filename1, 527static int tomoyo_update_path2_acl(const u8 perm,
741 const char *filename2, 528 struct tomoyo_acl_param *param)
742 struct tomoyo_domain_info * const domain,
743 const bool is_delete)
744{ 529{
745 struct tomoyo_path2_acl e = { 530 struct tomoyo_path2_acl e = {
746 .head.type = TOMOYO_TYPE_PATH2_ACL, 531 .head.type = TOMOYO_TYPE_PATH2_ACL,
747 .perm = 1 << type 532 .perm = perm
748 }; 533 };
749 int error = is_delete ? -ENOENT : -ENOMEM; 534 int error;
750 if (!tomoyo_parse_name_union(filename1, &e.name1) || 535 if (!tomoyo_parse_name_union(param, &e.name1) ||
751 !tomoyo_parse_name_union(filename2, &e.name2)) 536 !tomoyo_parse_name_union(param, &e.name2))
752 goto out; 537 error = -EINVAL;
753 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 538 else
754 tomoyo_same_path2_acl, 539 error = tomoyo_update_domain(&e.head, sizeof(e), param,
755 tomoyo_merge_path2_acl); 540 tomoyo_same_path2_acl,
756 out: 541 tomoyo_merge_path2_acl);
757 tomoyo_put_name_union(&e.name1); 542 tomoyo_put_name_union(&e.name1);
758 tomoyo_put_name_union(&e.name2); 543 tomoyo_put_name_union(&e.name2);
759 return error; 544 return error;
@@ -775,9 +560,8 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
775{ 560{
776 int error; 561 int error;
777 562
778 next:
779 r->type = tomoyo_p2mac[operation]; 563 r->type = tomoyo_p2mac[operation];
780 r->mode = tomoyo_get_mode(r->profile, r->type); 564 r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
781 if (r->mode == TOMOYO_CONFIG_DISABLED) 565 if (r->mode == TOMOYO_CONFIG_DISABLED)
782 return 0; 566 return 0;
783 r->param_type = TOMOYO_TYPE_PATH_ACL; 567 r->param_type = TOMOYO_TYPE_PATH_ACL;
@@ -785,10 +569,6 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
785 r->param.path.operation = operation; 569 r->param.path.operation = operation;
786 do { 570 do {
787 tomoyo_check_acl(r, tomoyo_check_path_acl); 571 tomoyo_check_acl(r, tomoyo_check_path_acl);
788 if (!r->granted && operation == TOMOYO_TYPE_READ &&
789 !r->domain->ignore_global_allow_read &&
790 tomoyo_globally_readable_file(filename))
791 r->granted = true;
792 error = tomoyo_audit_path_log(r); 572 error = tomoyo_audit_path_log(r);
793 /* 573 /*
794 * Do not retry for execute request, for alias may have 574 * Do not retry for execute request, for alias may have
@@ -796,19 +576,17 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
796 */ 576 */
797 } while (error == TOMOYO_RETRY_REQUEST && 577 } while (error == TOMOYO_RETRY_REQUEST &&
798 operation != TOMOYO_TYPE_EXECUTE); 578 operation != TOMOYO_TYPE_EXECUTE);
799 /*
800 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
801 * we need to check "allow_rewrite" permission if the filename is
802 * specified by "deny_rewrite" keyword.
803 */
804 if (!error && operation == TOMOYO_TYPE_TRUNCATE &&
805 tomoyo_no_rewrite_file(filename)) {
806 operation = TOMOYO_TYPE_REWRITE;
807 goto next;
808 }
809 return error; 579 return error;
810} 580}
811 581
582/**
583 * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
584 *
585 * @a: Pointer to "struct tomoyo_acl_info".
586 * @b: Pointer to "struct tomoyo_acl_info".
587 *
588 * Returns true if @a == @b except permission bits, false otherwise.
589 */
812static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, 590static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
813 const struct tomoyo_acl_info *b) 591 const struct tomoyo_acl_info *b)
814{ 592{
@@ -816,11 +594,19 @@ static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
816 head); 594 head);
817 const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), 595 const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
818 head); 596 head);
819 return tomoyo_same_acl_head(&p1->head, &p2->head) 597 return tomoyo_same_name_union(&p1->name, &p2->name) &&
820 && tomoyo_same_name_union(&p1->name, &p2->name) 598 tomoyo_same_number_union(&p1->number, &p2->number);
821 && tomoyo_same_number_union(&p1->number, &p2->number);
822} 599}
823 600
601/**
602 * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry.
603 *
604 * @a: Pointer to "struct tomoyo_acl_info".
605 * @b: Pointer to "struct tomoyo_acl_info".
606 * @is_delete: True for @a &= ~@b, false for @a |= @b.
607 *
608 * Returns true if @a is empty, false otherwise.
609 */
824static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, 610static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
825 struct tomoyo_acl_info *b, 611 struct tomoyo_acl_info *b,
826 const bool is_delete) 612 const bool is_delete)
@@ -841,33 +627,26 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
841/** 627/**
842 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. 628 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
843 * 629 *
844 * @type: Type of operation. 630 * @perm: Permission.
845 * @filename: Filename. 631 * @param: Pointer to "struct tomoyo_acl_param".
846 * @number: Number.
847 * @domain: Pointer to "struct tomoyo_domain_info".
848 * @is_delete: True if it is a delete request.
849 * 632 *
850 * Returns 0 on success, negative value otherwise. 633 * Returns 0 on success, negative value otherwise.
851 */ 634 */
852static int tomoyo_update_path_number_acl(const u8 type, const char *filename, 635static int tomoyo_update_path_number_acl(const u8 perm,
853 char *number, 636 struct tomoyo_acl_param *param)
854 struct tomoyo_domain_info * const
855 domain,
856 const bool is_delete)
857{ 637{
858 struct tomoyo_path_number_acl e = { 638 struct tomoyo_path_number_acl e = {
859 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, 639 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
860 .perm = 1 << type 640 .perm = perm
861 }; 641 };
862 int error = is_delete ? -ENOENT : -ENOMEM; 642 int error;
863 if (!tomoyo_parse_name_union(filename, &e.name)) 643 if (!tomoyo_parse_name_union(param, &e.name) ||
864 return -EINVAL; 644 !tomoyo_parse_number_union(param, &e.number))
865 if (!tomoyo_parse_number_union(number, &e.number)) 645 error = -EINVAL;
866 goto out; 646 else
867 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 647 error = tomoyo_update_domain(&e.head, sizeof(e), param,
868 tomoyo_same_path_number_acl, 648 tomoyo_same_path_number_acl,
869 tomoyo_merge_path_number_acl); 649 tomoyo_merge_path_number_acl);
870 out:
871 tomoyo_put_name_union(&e.name); 650 tomoyo_put_name_union(&e.name);
872 tomoyo_put_number_union(&e.number); 651 tomoyo_put_number_union(&e.number);
873 return error; 652 return error;
@@ -886,16 +665,20 @@ int tomoyo_path_number_perm(const u8 type, struct path *path,
886 unsigned long number) 665 unsigned long number)
887{ 666{
888 struct tomoyo_request_info r; 667 struct tomoyo_request_info r;
668 struct tomoyo_obj_info obj = {
669 .path1 = *path,
670 };
889 int error = -ENOMEM; 671 int error = -ENOMEM;
890 struct tomoyo_path_info buf; 672 struct tomoyo_path_info buf;
891 int idx; 673 int idx;
892 674
893 if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) 675 if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
894 == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry) 676 == TOMOYO_CONFIG_DISABLED || !path->dentry)
895 return 0; 677 return 0;
896 idx = tomoyo_read_lock(); 678 idx = tomoyo_read_lock();
897 if (!tomoyo_get_realpath(&buf, path)) 679 if (!tomoyo_get_realpath(&buf, path))
898 goto out; 680 goto out;
681 r.obj = &obj;
899 if (type == TOMOYO_TYPE_MKDIR) 682 if (type == TOMOYO_TYPE_MKDIR)
900 tomoyo_add_slash(&buf); 683 tomoyo_add_slash(&buf);
901 r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; 684 r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
@@ -930,45 +713,30 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
930 int error = 0; 713 int error = 0;
931 struct tomoyo_path_info buf; 714 struct tomoyo_path_info buf;
932 struct tomoyo_request_info r; 715 struct tomoyo_request_info r;
716 struct tomoyo_obj_info obj = {
717 .path1 = *path,
718 };
933 int idx; 719 int idx;
934 720
935 if (!path->mnt ||
936 (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)))
937 return 0;
938 buf.name = NULL; 721 buf.name = NULL;
939 r.mode = TOMOYO_CONFIG_DISABLED; 722 r.mode = TOMOYO_CONFIG_DISABLED;
940 idx = tomoyo_read_lock(); 723 idx = tomoyo_read_lock();
941 /* 724 if (acc_mode &&
942 * If the filename is specified by "deny_rewrite" keyword, 725 tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
943 * we need to check "allow_rewrite" permission when the filename is not
944 * opened for append mode or the filename is truncated at open time.
945 */
946 if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND)
947 && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE)
948 != TOMOYO_CONFIG_DISABLED) { 726 != TOMOYO_CONFIG_DISABLED) {
949 if (!tomoyo_get_realpath(&buf, path)) { 727 if (!tomoyo_get_realpath(&buf, path)) {
950 error = -ENOMEM; 728 error = -ENOMEM;
951 goto out; 729 goto out;
952 } 730 }
953 if (tomoyo_no_rewrite_file(&buf)) 731 r.obj = &obj;
954 error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, 732 if (acc_mode & MAY_READ)
733 error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
734 &buf);
735 if (!error && (acc_mode & MAY_WRITE))
736 error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
737 TOMOYO_TYPE_APPEND :
738 TOMOYO_TYPE_WRITE,
955 &buf); 739 &buf);
956 }
957 if (!error && acc_mode &&
958 tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
959 != TOMOYO_CONFIG_DISABLED) {
960 u8 operation;
961 if (!buf.name && !tomoyo_get_realpath(&buf, path)) {
962 error = -ENOMEM;
963 goto out;
964 }
965 if (acc_mode == (MAY_READ | MAY_WRITE))
966 operation = TOMOYO_TYPE_READ_WRITE;
967 else if (acc_mode == MAY_READ)
968 operation = TOMOYO_TYPE_READ;
969 else
970 operation = TOMOYO_TYPE_WRITE;
971 error = tomoyo_path_permission(&r, operation, &buf);
972 } 740 }
973 out: 741 out:
974 kfree(buf.name); 742 kfree(buf.name);
@@ -979,46 +747,57 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
979} 747}
980 748
981/** 749/**
982 * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount". 750 * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount".
983 * 751 *
984 * @operation: Type of operation. 752 * @operation: Type of operation.
985 * @path: Pointer to "struct path". 753 * @path: Pointer to "struct path".
754 * @target: Symlink's target if @operation is TOMOYO_TYPE_SYMLINK,
755 * NULL otherwise.
986 * 756 *
987 * Returns 0 on success, negative value otherwise. 757 * Returns 0 on success, negative value otherwise.
988 */ 758 */
989int tomoyo_path_perm(const u8 operation, struct path *path) 759int tomoyo_path_perm(const u8 operation, struct path *path, const char *target)
990{ 760{
991 int error = -ENOMEM;
992 struct tomoyo_path_info buf;
993 struct tomoyo_request_info r; 761 struct tomoyo_request_info r;
762 struct tomoyo_obj_info obj = {
763 .path1 = *path,
764 };
765 int error;
766 struct tomoyo_path_info buf;
767 bool is_enforce;
768 struct tomoyo_path_info symlink_target;
994 int idx; 769 int idx;
995 770
996 if (!path->mnt)
997 return 0;
998 if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) 771 if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
999 == TOMOYO_CONFIG_DISABLED) 772 == TOMOYO_CONFIG_DISABLED)
1000 return 0; 773 return 0;
774 is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
775 error = -ENOMEM;
1001 buf.name = NULL; 776 buf.name = NULL;
1002 idx = tomoyo_read_lock(); 777 idx = tomoyo_read_lock();
1003 if (!tomoyo_get_realpath(&buf, path)) 778 if (!tomoyo_get_realpath(&buf, path))
1004 goto out; 779 goto out;
780 r.obj = &obj;
1005 switch (operation) { 781 switch (operation) {
1006 case TOMOYO_TYPE_REWRITE:
1007 if (!tomoyo_no_rewrite_file(&buf)) {
1008 error = 0;
1009 goto out;
1010 }
1011 break;
1012 case TOMOYO_TYPE_RMDIR: 782 case TOMOYO_TYPE_RMDIR:
1013 case TOMOYO_TYPE_CHROOT: 783 case TOMOYO_TYPE_CHROOT:
1014 tomoyo_add_slash(&buf); 784 tomoyo_add_slash(&buf);
1015 break; 785 break;
786 case TOMOYO_TYPE_SYMLINK:
787 symlink_target.name = tomoyo_encode(target);
788 if (!symlink_target.name)
789 goto out;
790 tomoyo_fill_path_info(&symlink_target);
791 obj.symlink_target = &symlink_target;
792 break;
1016 } 793 }
1017 error = tomoyo_path_permission(&r, operation, &buf); 794 error = tomoyo_path_permission(&r, operation, &buf);
795 if (operation == TOMOYO_TYPE_SYMLINK)
796 kfree(symlink_target.name);
1018 out: 797 out:
1019 kfree(buf.name); 798 kfree(buf.name);
1020 tomoyo_read_unlock(idx); 799 tomoyo_read_unlock(idx);
1021 if (r.mode != TOMOYO_CONFIG_ENFORCING) 800 if (!is_enforce)
1022 error = 0; 801 error = 0;
1023 return error; 802 return error;
1024} 803}
@@ -1034,20 +813,23 @@ int tomoyo_path_perm(const u8 operation, struct path *path)
1034 * Returns 0 on success, negative value otherwise. 813 * Returns 0 on success, negative value otherwise.
1035 */ 814 */
1036int tomoyo_mkdev_perm(const u8 operation, struct path *path, 815int tomoyo_mkdev_perm(const u8 operation, struct path *path,
1037 const unsigned int mode, unsigned int dev) 816 const unsigned int mode, unsigned int dev)
1038{ 817{
1039 struct tomoyo_request_info r; 818 struct tomoyo_request_info r;
819 struct tomoyo_obj_info obj = {
820 .path1 = *path,
821 };
1040 int error = -ENOMEM; 822 int error = -ENOMEM;
1041 struct tomoyo_path_info buf; 823 struct tomoyo_path_info buf;
1042 int idx; 824 int idx;
1043 825
1044 if (!path->mnt || 826 if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
1045 tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
1046 == TOMOYO_CONFIG_DISABLED) 827 == TOMOYO_CONFIG_DISABLED)
1047 return 0; 828 return 0;
1048 idx = tomoyo_read_lock(); 829 idx = tomoyo_read_lock();
1049 error = -ENOMEM; 830 error = -ENOMEM;
1050 if (tomoyo_get_realpath(&buf, path)) { 831 if (tomoyo_get_realpath(&buf, path)) {
832 r.obj = &obj;
1051 dev = new_decode_dev(dev); 833 dev = new_decode_dev(dev);
1052 r.param_type = TOMOYO_TYPE_MKDEV_ACL; 834 r.param_type = TOMOYO_TYPE_MKDEV_ACL;
1053 r.param.mkdev.filename = &buf; 835 r.param.mkdev.filename = &buf;
@@ -1081,10 +863,13 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
1081 struct tomoyo_path_info buf1; 863 struct tomoyo_path_info buf1;
1082 struct tomoyo_path_info buf2; 864 struct tomoyo_path_info buf2;
1083 struct tomoyo_request_info r; 865 struct tomoyo_request_info r;
866 struct tomoyo_obj_info obj = {
867 .path1 = *path1,
868 .path2 = *path2,
869 };
1084 int idx; 870 int idx;
1085 871
1086 if (!path1->mnt || !path2->mnt || 872 if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
1087 tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
1088 == TOMOYO_CONFIG_DISABLED) 873 == TOMOYO_CONFIG_DISABLED)
1089 return 0; 874 return 0;
1090 buf1.name = NULL; 875 buf1.name = NULL;
@@ -1096,16 +881,17 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
1096 switch (operation) { 881 switch (operation) {
1097 struct dentry *dentry; 882 struct dentry *dentry;
1098 case TOMOYO_TYPE_RENAME: 883 case TOMOYO_TYPE_RENAME:
1099 case TOMOYO_TYPE_LINK: 884 case TOMOYO_TYPE_LINK:
1100 dentry = path1->dentry; 885 dentry = path1->dentry;
1101 if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) 886 if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
1102 break; 887 break;
1103 /* fall through */ 888 /* fall through */
1104 case TOMOYO_TYPE_PIVOT_ROOT: 889 case TOMOYO_TYPE_PIVOT_ROOT:
1105 tomoyo_add_slash(&buf1); 890 tomoyo_add_slash(&buf1);
1106 tomoyo_add_slash(&buf2); 891 tomoyo_add_slash(&buf2);
1107 break; 892 break;
1108 } 893 }
894 r.obj = &obj;
1109 r.param_type = TOMOYO_TYPE_PATH2_ACL; 895 r.param_type = TOMOYO_TYPE_PATH2_ACL;
1110 r.param.path2.operation = operation; 896 r.param.path2.operation = operation;
1111 r.param.path2.filename1 = &buf1; 897 r.param.path2.filename1 = &buf1;
@@ -1124,53 +910,91 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
1124} 910}
1125 911
1126/** 912/**
913 * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
914 *
915 * @a: Pointer to "struct tomoyo_acl_info".
916 * @b: Pointer to "struct tomoyo_acl_info".
917 *
918 * Returns true if @a == @b, false otherwise.
919 */
920static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
921 const struct tomoyo_acl_info *b)
922{
923 const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
924 const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
925 return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
926 tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
927 tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
928 tomoyo_same_number_union(&p1->flags, &p2->flags);
929}
930
931/**
932 * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list.
933 *
934 * @param: Pointer to "struct tomoyo_acl_param".
935 *
936 * Returns 0 on success, negative value otherwise.
937 *
938 * Caller holds tomoyo_read_lock().
939 */
940static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
941{
942 struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
943 int error;
944 if (!tomoyo_parse_name_union(param, &e.dev_name) ||
945 !tomoyo_parse_name_union(param, &e.dir_name) ||
946 !tomoyo_parse_name_union(param, &e.fs_type) ||
947 !tomoyo_parse_number_union(param, &e.flags))
948 error = -EINVAL;
949 else
950 error = tomoyo_update_domain(&e.head, sizeof(e), param,
951 tomoyo_same_mount_acl, NULL);
952 tomoyo_put_name_union(&e.dev_name);
953 tomoyo_put_name_union(&e.dir_name);
954 tomoyo_put_name_union(&e.fs_type);
955 tomoyo_put_number_union(&e.flags);
956 return error;
957}
958
959/**
1127 * tomoyo_write_file - Update file related list. 960 * tomoyo_write_file - Update file related list.
1128 * 961 *
1129 * @data: String to parse. 962 * @param: Pointer to "struct tomoyo_acl_param".
1130 * @domain: Pointer to "struct tomoyo_domain_info".
1131 * @is_delete: True if it is a delete request.
1132 * 963 *
1133 * Returns 0 on success, negative value otherwise. 964 * Returns 0 on success, negative value otherwise.
1134 * 965 *
1135 * Caller holds tomoyo_read_lock(). 966 * Caller holds tomoyo_read_lock().
1136 */ 967 */
1137int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, 968int tomoyo_write_file(struct tomoyo_acl_param *param)
1138 const bool is_delete)
1139{ 969{
1140 char *w[5]; 970 u16 perm = 0;
1141 u8 type; 971 u8 type;
1142 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) 972 const char *operation = tomoyo_read_token(param);
1143 return -EINVAL; 973 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
1144 if (strncmp(w[0], "allow_", 6)) 974 if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
1145 goto out; 975 perm |= 1 << type;
1146 w[0] += 6; 976 if (perm)
1147 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { 977 return tomoyo_update_path_acl(perm, param);
1148 if (strcmp(w[0], tomoyo_path_keyword[type])) 978 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
1149 continue; 979 if (tomoyo_permstr(operation,
1150 return tomoyo_update_path_acl(type, w[1], domain, is_delete); 980 tomoyo_mac_keywords[tomoyo_pp2mac[type]]))
1151 } 981 perm |= 1 << type;
1152 if (!w[2][0]) 982 if (perm)
1153 goto out; 983 return tomoyo_update_path2_acl(perm, param);
1154 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { 984 for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
1155 if (strcmp(w[0], tomoyo_path2_keyword[type])) 985 if (tomoyo_permstr(operation,
1156 continue; 986 tomoyo_mac_keywords[tomoyo_pn2mac[type]]))
1157 return tomoyo_update_path2_acl(type, w[1], w[2], domain, 987 perm |= 1 << type;
1158 is_delete); 988 if (perm)
1159 } 989 return tomoyo_update_path_number_acl(perm, param);
1160 for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) { 990 for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
1161 if (strcmp(w[0], tomoyo_path_number_keyword[type])) 991 if (tomoyo_permstr(operation,
1162 continue; 992 tomoyo_mac_keywords[tomoyo_pnnn2mac[type]]))
1163 return tomoyo_update_path_number_acl(type, w[1], w[2], domain, 993 perm |= 1 << type;
1164 is_delete); 994 if (perm)
1165 } 995 return tomoyo_update_mkdev_acl(perm, param);
1166 if (!w[3][0] || !w[4][0]) 996 if (tomoyo_permstr(operation,
1167 goto out; 997 tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT]))
1168 for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) { 998 return tomoyo_update_mount_acl(param);
1169 if (strcmp(w[0], tomoyo_mkdev_keyword[type]))
1170 continue;
1171 return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3],
1172 w[4], domain, is_delete);
1173 }
1174 out:
1175 return -EINVAL; 999 return -EINVAL;
1176} 1000}