file.c revision 39826a1e17c1957bd7b5cd7815b83940e5e3a230
1/*
2 * security/tomoyo/file.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2009  NTT DATA CORPORATION
7 *
8 * Version: 2.2.0   2009/04/01
9 *
10 */
11
12#include "common.h"
13#include "tomoyo.h"
14#include "realpath.h"
15#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
16
17/* Structure for "allow_read" keyword. */
18struct tomoyo_globally_readable_file_entry {
19	struct list_head list;
20	const struct tomoyo_path_info *filename;
21	bool is_deleted;
22};
23
24/* Structure for "file_pattern" keyword. */
25struct tomoyo_pattern_entry {
26	struct list_head list;
27	const struct tomoyo_path_info *pattern;
28	bool is_deleted;
29};
30
31/* Structure for "deny_rewrite" keyword. */
32struct tomoyo_no_rewrite_entry {
33	struct list_head list;
34	const struct tomoyo_path_info *pattern;
35	bool is_deleted;
36};
37
38/* Keyword array for single path operations. */
39static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
40	[TOMOYO_TYPE_READ_WRITE_ACL] = "read/write",
41	[TOMOYO_TYPE_EXECUTE_ACL]    = "execute",
42	[TOMOYO_TYPE_READ_ACL]       = "read",
43	[TOMOYO_TYPE_WRITE_ACL]      = "write",
44	[TOMOYO_TYPE_CREATE_ACL]     = "create",
45	[TOMOYO_TYPE_UNLINK_ACL]     = "unlink",
46	[TOMOYO_TYPE_MKDIR_ACL]      = "mkdir",
47	[TOMOYO_TYPE_RMDIR_ACL]      = "rmdir",
48	[TOMOYO_TYPE_MKFIFO_ACL]     = "mkfifo",
49	[TOMOYO_TYPE_MKSOCK_ACL]     = "mksock",
50	[TOMOYO_TYPE_MKBLOCK_ACL]    = "mkblock",
51	[TOMOYO_TYPE_MKCHAR_ACL]     = "mkchar",
52	[TOMOYO_TYPE_TRUNCATE_ACL]   = "truncate",
53	[TOMOYO_TYPE_SYMLINK_ACL]    = "symlink",
54	[TOMOYO_TYPE_REWRITE_ACL]    = "rewrite",
55};
56
57/* Keyword array for double path operations. */
58static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
59	[TOMOYO_TYPE_LINK_ACL]    = "link",
60	[TOMOYO_TYPE_RENAME_ACL]  = "rename",
61};
62
63/**
64 * tomoyo_sp2keyword - Get the name of single path operation.
65 *
66 * @operation: Type of operation.
67 *
68 * Returns the name of single path operation.
69 */
70const char *tomoyo_sp2keyword(const u8 operation)
71{
72	return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION)
73		? tomoyo_sp_keyword[operation] : NULL;
74}
75
76/**
77 * tomoyo_dp2keyword - Get the name of double path operation.
78 *
79 * @operation: Type of operation.
80 *
81 * Returns the name of double path operation.
82 */
83const char *tomoyo_dp2keyword(const u8 operation)
84{
85	return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION)
86		? tomoyo_dp_keyword[operation] : NULL;
87}
88
89/**
90 * tomoyo_strendswith - Check whether the token ends with the given token.
91 *
92 * @name: The token to check.
93 * @tail: The token to find.
94 *
95 * Returns true if @name ends with @tail, false otherwise.
96 */
97static bool tomoyo_strendswith(const char *name, const char *tail)
98{
99	int len;
100
101	if (!name || !tail)
102		return false;
103	len = strlen(name) - strlen(tail);
104	return len >= 0 && !strcmp(name + len, tail);
105}
106
107/**
108 * tomoyo_get_path - Get realpath.
109 *
110 * @path: Pointer to "struct path".
111 *
112 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
113 */
114static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
115{
116	int error;
117	struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf));
118
119	if (!buf)
120		return NULL;
121	/* Reserve one byte for appending "/". */
122	error = tomoyo_realpath_from_path2(path, buf->body,
123					   sizeof(buf->body) - 2);
124	if (!error) {
125		buf->head.name = buf->body;
126		tomoyo_fill_path_info(&buf->head);
127		return &buf->head;
128	}
129	tomoyo_free(buf);
130	return NULL;
131}
132
133/* Lock for domain->acl_info_list. */
134DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
135
136static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
137					 const char *filename2,
138					 struct tomoyo_domain_info *
139					 const domain, const bool is_delete);
140static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
141					 struct tomoyo_domain_info *
142					 const domain, const bool is_delete);
143
144/* The list for "struct tomoyo_globally_readable_file_entry". */
145static LIST_HEAD(tomoyo_globally_readable_list);
146static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
147
148/**
149 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
150 *
151 * @filename:  Filename unconditionally permitted to open() for reading.
152 * @is_delete: True if it is a delete request.
153 *
154 * Returns 0 on success, negative value otherwise.
155 */
156static int tomoyo_update_globally_readable_entry(const char *filename,
157						 const bool is_delete)
158{
159	struct tomoyo_globally_readable_file_entry *new_entry;
160	struct tomoyo_globally_readable_file_entry *ptr;
161	const struct tomoyo_path_info *saved_filename;
162	int error = -ENOMEM;
163
164	if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
165		return -EINVAL;
166	saved_filename = tomoyo_save_name(filename);
167	if (!saved_filename)
168		return -ENOMEM;
169	/***** EXCLUSIVE SECTION START *****/
170	down_write(&tomoyo_globally_readable_list_lock);
171	list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
172		if (ptr->filename != saved_filename)
173			continue;
174		ptr->is_deleted = is_delete;
175		error = 0;
176		goto out;
177	}
178	if (is_delete) {
179		error = -ENOENT;
180		goto out;
181	}
182	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
183	if (!new_entry)
184		goto out;
185	new_entry->filename = saved_filename;
186	list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
187	error = 0;
188 out:
189	up_write(&tomoyo_globally_readable_list_lock);
190	/***** EXCLUSIVE SECTION END *****/
191	return error;
192}
193
194/**
195 * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
196 *
197 * @filename: The filename to check.
198 *
199 * Returns true if any domain can open @filename for reading, false otherwise.
200 */
201static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
202					     filename)
203{
204	struct tomoyo_globally_readable_file_entry *ptr;
205	bool found = false;
206	down_read(&tomoyo_globally_readable_list_lock);
207	list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
208		if (!ptr->is_deleted &&
209		    tomoyo_path_matches_pattern(filename, ptr->filename)) {
210			found = true;
211			break;
212		}
213	}
214	up_read(&tomoyo_globally_readable_list_lock);
215	return found;
216}
217
218/**
219 * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list.
220 *
221 * @data:      String to parse.
222 * @is_delete: True if it is a delete request.
223 *
224 * Returns 0 on success, negative value otherwise.
225 */
226int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
227{
228	return tomoyo_update_globally_readable_entry(data, is_delete);
229}
230
231/**
232 * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list.
233 *
234 * @head: Pointer to "struct tomoyo_io_buffer".
235 *
236 * Returns true on success, false otherwise.
237 */
238bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
239{
240	struct list_head *pos;
241	bool done = true;
242
243	down_read(&tomoyo_globally_readable_list_lock);
244	list_for_each_cookie(pos, head->read_var2,
245			     &tomoyo_globally_readable_list) {
246		struct tomoyo_globally_readable_file_entry *ptr;
247		ptr = list_entry(pos,
248				 struct tomoyo_globally_readable_file_entry,
249				 list);
250		if (ptr->is_deleted)
251			continue;
252		if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
253				      ptr->filename->name)) {
254			done = false;
255			break;
256		}
257	}
258	up_read(&tomoyo_globally_readable_list_lock);
259	return done;
260}
261
262/* The list for "struct tomoyo_pattern_entry". */
263static LIST_HEAD(tomoyo_pattern_list);
264static DECLARE_RWSEM(tomoyo_pattern_list_lock);
265
266/**
267 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
268 *
269 * @pattern:   Pathname pattern.
270 * @is_delete: True if it is a delete request.
271 *
272 * Returns 0 on success, negative value otherwise.
273 */
274static int tomoyo_update_file_pattern_entry(const char *pattern,
275					    const bool is_delete)
276{
277	struct tomoyo_pattern_entry *new_entry;
278	struct tomoyo_pattern_entry *ptr;
279	const struct tomoyo_path_info *saved_pattern;
280	int error = -ENOMEM;
281
282	if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
283		return -EINVAL;
284	saved_pattern = tomoyo_save_name(pattern);
285	if (!saved_pattern)
286		return -ENOMEM;
287	/***** EXCLUSIVE SECTION START *****/
288	down_write(&tomoyo_pattern_list_lock);
289	list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
290		if (saved_pattern != ptr->pattern)
291			continue;
292		ptr->is_deleted = is_delete;
293		error = 0;
294		goto out;
295	}
296	if (is_delete) {
297		error = -ENOENT;
298		goto out;
299	}
300	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
301	if (!new_entry)
302		goto out;
303	new_entry->pattern = saved_pattern;
304	list_add_tail(&new_entry->list, &tomoyo_pattern_list);
305	error = 0;
306 out:
307	up_write(&tomoyo_pattern_list_lock);
308	/***** EXCLUSIVE SECTION END *****/
309	return error;
310}
311
312/**
313 * tomoyo_get_file_pattern - Get patterned pathname.
314 *
315 * @filename: The filename to find patterned pathname.
316 *
317 * Returns pointer to pathname pattern if matched, @filename otherwise.
318 */
319static const struct tomoyo_path_info *
320tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
321{
322	struct tomoyo_pattern_entry *ptr;
323	const struct tomoyo_path_info *pattern = NULL;
324
325	down_read(&tomoyo_pattern_list_lock);
326	list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
327		if (ptr->is_deleted)
328			continue;
329		if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
330			continue;
331		pattern = ptr->pattern;
332		if (tomoyo_strendswith(pattern->name, "/\\*")) {
333			/* Do nothing. Try to find the better match. */
334		} else {
335			/* This would be the better match. Use this. */
336			break;
337		}
338	}
339	up_read(&tomoyo_pattern_list_lock);
340	if (pattern)
341		filename = pattern;
342	return filename;
343}
344
345/**
346 * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list.
347 *
348 * @data:      String to parse.
349 * @is_delete: True if it is a delete request.
350 *
351 * Returns 0 on success, negative value otherwise.
352 */
353int tomoyo_write_pattern_policy(char *data, const bool is_delete)
354{
355	return tomoyo_update_file_pattern_entry(data, is_delete);
356}
357
358/**
359 * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list.
360 *
361 * @head: Pointer to "struct tomoyo_io_buffer".
362 *
363 * Returns true on success, false otherwise.
364 */
365bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
366{
367	struct list_head *pos;
368	bool done = true;
369
370	down_read(&tomoyo_pattern_list_lock);
371	list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
372		struct tomoyo_pattern_entry *ptr;
373		ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
374		if (ptr->is_deleted)
375			continue;
376		if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN "%s\n",
377				      ptr->pattern->name)) {
378			done = false;
379			break;
380		}
381	}
382	up_read(&tomoyo_pattern_list_lock);
383	return done;
384}
385
386/* The list for "struct tomoyo_no_rewrite_entry". */
387static LIST_HEAD(tomoyo_no_rewrite_list);
388static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
389
390/**
391 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
392 *
393 * @pattern:   Pathname pattern that are not rewritable by default.
394 * @is_delete: True if it is a delete request.
395 *
396 * Returns 0 on success, negative value otherwise.
397 */
398static int tomoyo_update_no_rewrite_entry(const char *pattern,
399					  const bool is_delete)
400{
401	struct tomoyo_no_rewrite_entry *new_entry, *ptr;
402	const struct tomoyo_path_info *saved_pattern;
403	int error = -ENOMEM;
404
405	if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
406		return -EINVAL;
407	saved_pattern = tomoyo_save_name(pattern);
408	if (!saved_pattern)
409		return -ENOMEM;
410	/***** EXCLUSIVE SECTION START *****/
411	down_write(&tomoyo_no_rewrite_list_lock);
412	list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
413		if (ptr->pattern != saved_pattern)
414			continue;
415		ptr->is_deleted = is_delete;
416		error = 0;
417		goto out;
418	}
419	if (is_delete) {
420		error = -ENOENT;
421		goto out;
422	}
423	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
424	if (!new_entry)
425		goto out;
426	new_entry->pattern = saved_pattern;
427	list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
428	error = 0;
429 out:
430	up_write(&tomoyo_no_rewrite_list_lock);
431	/***** EXCLUSIVE SECTION END *****/
432	return error;
433}
434
435/**
436 * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
437 *
438 * @filename: Filename to check.
439 *
440 * Returns true if @filename is specified by "deny_rewrite" directive,
441 * false otherwise.
442 */
443static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
444{
445	struct tomoyo_no_rewrite_entry *ptr;
446	bool found = false;
447
448	down_read(&tomoyo_no_rewrite_list_lock);
449	list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
450		if (ptr->is_deleted)
451			continue;
452		if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
453			continue;
454		found = true;
455		break;
456	}
457	up_read(&tomoyo_no_rewrite_list_lock);
458	return found;
459}
460
461/**
462 * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list.
463 *
464 * @data:      String to parse.
465 * @is_delete: True if it is a delete request.
466 *
467 * Returns 0 on success, negative value otherwise.
468 */
469int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
470{
471	return tomoyo_update_no_rewrite_entry(data, is_delete);
472}
473
474/**
475 * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list.
476 *
477 * @head: Pointer to "struct tomoyo_io_buffer".
478 *
479 * Returns true on success, false otherwise.
480 */
481bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
482{
483	struct list_head *pos;
484	bool done = true;
485
486	down_read(&tomoyo_no_rewrite_list_lock);
487	list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
488		struct tomoyo_no_rewrite_entry *ptr;
489		ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
490		if (ptr->is_deleted)
491			continue;
492		if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE "%s\n",
493				      ptr->pattern->name)) {
494			done = false;
495			break;
496		}
497	}
498	up_read(&tomoyo_no_rewrite_list_lock);
499	return done;
500}
501
502/**
503 * tomoyo_update_file_acl - Update file's read/write/execute ACL.
504 *
505 * @filename:  Filename.
506 * @perm:      Permission (between 1 to 7).
507 * @domain:    Pointer to "struct tomoyo_domain_info".
508 * @is_delete: True if it is a delete request.
509 *
510 * Returns 0 on success, negative value otherwise.
511 *
512 * This is legacy support interface for older policy syntax.
513 * Current policy syntax uses "allow_read/write" instead of "6",
514 * "allow_read" instead of "4", "allow_write" instead of "2",
515 * "allow_execute" instead of "1".
516 */
517static int tomoyo_update_file_acl(const char *filename, u8 perm,
518				  struct tomoyo_domain_info * const domain,
519				  const bool is_delete)
520{
521	if (perm > 7 || !perm) {
522		printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n",
523		       __func__, perm, filename);
524		return -EINVAL;
525	}
526	if (filename[0] != '@' && tomoyo_strendswith(filename, "/"))
527		/*
528		 * Only 'allow_mkdir' and 'allow_rmdir' are valid for
529		 * directory permissions.
530		 */
531		return 0;
532	if (perm & 4)
533		tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename,
534					      domain, is_delete);
535	if (perm & 2)
536		tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename,
537					      domain, is_delete);
538	if (perm & 1)
539		tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL,
540					      filename, domain, is_delete);
541	return 0;
542}
543
544/**
545 * tomoyo_check_single_path_acl2 - Check permission for single path operation.
546 *
547 * @domain:          Pointer to "struct tomoyo_domain_info".
548 * @filename:        Filename to check.
549 * @perm:            Permission.
550 * @may_use_pattern: True if patterned ACL is permitted.
551 *
552 * Returns 0 on success, -EPERM otherwise.
553 */
554static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
555					 domain,
556					 const struct tomoyo_path_info *
557					 filename,
558					 const u16 perm,
559					 const bool may_use_pattern)
560{
561	struct tomoyo_acl_info *ptr;
562	int error = -EPERM;
563
564	down_read(&tomoyo_domain_acl_info_list_lock);
565	list_for_each_entry(ptr, &domain->acl_info_list, list) {
566		struct tomoyo_single_path_acl_record *acl;
567		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
568			continue;
569		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
570				   head);
571		if (!(acl->perm & perm))
572			continue;
573		if (may_use_pattern || !acl->filename->is_patterned) {
574			if (!tomoyo_path_matches_pattern(filename,
575							 acl->filename))
576				continue;
577		} else {
578			continue;
579		}
580		error = 0;
581		break;
582	}
583	up_read(&tomoyo_domain_acl_info_list_lock);
584	return error;
585}
586
587/**
588 * tomoyo_check_file_acl - Check permission for opening files.
589 *
590 * @domain:    Pointer to "struct tomoyo_domain_info".
591 * @filename:  Filename to check.
592 * @operation: Mode ("read" or "write" or "read/write" or "execute").
593 *
594 * Returns 0 on success, -EPERM otherwise.
595 */
596static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
597				 const struct tomoyo_path_info *filename,
598				 const u8 operation)
599{
600	u16 perm = 0;
601
602	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
603		return 0;
604	if (operation == 6)
605		perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL;
606	else if (operation == 4)
607		perm = 1 << TOMOYO_TYPE_READ_ACL;
608	else if (operation == 2)
609		perm = 1 << TOMOYO_TYPE_WRITE_ACL;
610	else if (operation == 1)
611		perm = 1 << TOMOYO_TYPE_EXECUTE_ACL;
612	else
613		BUG();
614	return tomoyo_check_single_path_acl2(domain, filename, perm,
615					     operation != 1);
616}
617
618/**
619 * tomoyo_check_file_perm2 - Check permission for opening files.
620 *
621 * @domain:    Pointer to "struct tomoyo_domain_info".
622 * @filename:  Filename to check.
623 * @perm:      Mode ("read" or "write" or "read/write" or "execute").
624 * @operation: Operation name passed used for verbose mode.
625 * @mode:      Access control mode.
626 *
627 * Returns 0 on success, negative value otherwise.
628 */
629static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
630				   const struct tomoyo_path_info *filename,
631				   const u8 perm, const char *operation,
632				   const u8 mode)
633{
634	const bool is_enforce = (mode == 3);
635	const char *msg = "<unknown>";
636	int error = 0;
637
638	if (!filename)
639		return 0;
640	error = tomoyo_check_file_acl(domain, filename, perm);
641	if (error && perm == 4 &&
642	    (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
643	    && tomoyo_is_globally_readable_file(filename))
644		error = 0;
645	if (perm == 6)
646		msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL);
647	else if (perm == 4)
648		msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL);
649	else if (perm == 2)
650		msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL);
651	else if (perm == 1)
652		msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL);
653	else
654		BUG();
655	if (!error)
656		return 0;
657	if (tomoyo_verbose_mode(domain))
658		printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied "
659		       "for %s\n", tomoyo_get_msg(is_enforce), msg, operation,
660		       filename->name, tomoyo_get_last_name(domain));
661	if (is_enforce)
662		return error;
663	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
664		/* Don't use patterns for execute permission. */
665		const struct tomoyo_path_info *patterned_file = (perm != 1) ?
666			tomoyo_get_file_pattern(filename) : filename;
667		tomoyo_update_file_acl(patterned_file->name, perm,
668				       domain, false);
669	}
670	return 0;
671}
672
673/**
674 * tomoyo_write_file_policy - Update file related list.
675 *
676 * @data:      String to parse.
677 * @domain:    Pointer to "struct tomoyo_domain_info".
678 * @is_delete: True if it is a delete request.
679 *
680 * Returns 0 on success, negative value otherwise.
681 */
682int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
683			     const bool is_delete)
684{
685	char *filename = strchr(data, ' ');
686	char *filename2;
687	unsigned int perm;
688	u8 type;
689
690	if (!filename)
691		return -EINVAL;
692	*filename++ = '\0';
693	if (sscanf(data, "%u", &perm) == 1)
694		return tomoyo_update_file_acl(filename, (u8) perm, domain,
695					      is_delete);
696	if (strncmp(data, "allow_", 6))
697		goto out;
698	data += 6;
699	for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) {
700		if (strcmp(data, tomoyo_sp_keyword[type]))
701			continue;
702		return tomoyo_update_single_path_acl(type, filename,
703						     domain, is_delete);
704	}
705	filename2 = strchr(filename, ' ');
706	if (!filename2)
707		goto out;
708	*filename2++ = '\0';
709	for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) {
710		if (strcmp(data, tomoyo_dp_keyword[type]))
711			continue;
712		return tomoyo_update_double_path_acl(type, filename, filename2,
713						     domain, is_delete);
714	}
715 out:
716	return -EINVAL;
717}
718
719/**
720 * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list.
721 *
722 * @type:      Type of operation.
723 * @filename:  Filename.
724 * @domain:    Pointer to "struct tomoyo_domain_info".
725 * @is_delete: True if it is a delete request.
726 *
727 * Returns 0 on success, negative value otherwise.
728 */
729static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
730					 struct tomoyo_domain_info *
731					 const domain, const bool is_delete)
732{
733	static const u16 rw_mask =
734		(1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
735	const struct tomoyo_path_info *saved_filename;
736	struct tomoyo_acl_info *ptr;
737	struct tomoyo_single_path_acl_record *acl;
738	int error = -ENOMEM;
739	const u16 perm = 1 << type;
740
741	if (!domain)
742		return -EINVAL;
743	if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
744		return -EINVAL;
745	saved_filename = tomoyo_save_name(filename);
746	if (!saved_filename)
747		return -ENOMEM;
748	/***** EXCLUSIVE SECTION START *****/
749	down_write(&tomoyo_domain_acl_info_list_lock);
750	if (is_delete)
751		goto delete;
752	list_for_each_entry(ptr, &domain->acl_info_list, list) {
753		if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
754			continue;
755		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
756				   head);
757		if (acl->filename != saved_filename)
758			continue;
759		/* Special case. Clear all bits if marked as deleted. */
760		if (ptr->type & TOMOYO_ACL_DELETED)
761			acl->perm = 0;
762		acl->perm |= perm;
763		if ((acl->perm & rw_mask) == rw_mask)
764			acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
765		else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
766			acl->perm |= rw_mask;
767		ptr->type &= ~TOMOYO_ACL_DELETED;
768		error = 0;
769		goto out;
770	}
771	/* Not found. Append it to the tail. */
772	acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
773	if (!acl)
774		goto out;
775	acl->perm = perm;
776	if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
777		acl->perm |= rw_mask;
778	acl->filename = saved_filename;
779	list_add_tail(&acl->head.list, &domain->acl_info_list);
780	error = 0;
781	goto out;
782 delete:
783	error = -ENOENT;
784	list_for_each_entry(ptr, &domain->acl_info_list, list) {
785		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
786			continue;
787		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
788				   head);
789		if (acl->filename != saved_filename)
790			continue;
791		acl->perm &= ~perm;
792		if ((acl->perm & rw_mask) != rw_mask)
793			acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
794		else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
795			acl->perm &= ~rw_mask;
796		if (!acl->perm)
797			ptr->type |= TOMOYO_ACL_DELETED;
798		error = 0;
799		break;
800	}
801 out:
802	up_write(&tomoyo_domain_acl_info_list_lock);
803	/***** EXCLUSIVE SECTION END *****/
804	return error;
805}
806
807/**
808 * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list.
809 *
810 * @type:      Type of operation.
811 * @filename1: First filename.
812 * @filename2: Second filename.
813 * @domain:    Pointer to "struct tomoyo_domain_info".
814 * @is_delete: True if it is a delete request.
815 *
816 * Returns 0 on success, negative value otherwise.
817 */
818static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
819					 const char *filename2,
820					 struct tomoyo_domain_info *
821					 const domain, const bool is_delete)
822{
823	const struct tomoyo_path_info *saved_filename1;
824	const struct tomoyo_path_info *saved_filename2;
825	struct tomoyo_acl_info *ptr;
826	struct tomoyo_double_path_acl_record *acl;
827	int error = -ENOMEM;
828	const u8 perm = 1 << type;
829
830	if (!domain)
831		return -EINVAL;
832	if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
833	    !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
834		return -EINVAL;
835	saved_filename1 = tomoyo_save_name(filename1);
836	saved_filename2 = tomoyo_save_name(filename2);
837	if (!saved_filename1 || !saved_filename2)
838		return -ENOMEM;
839	/***** EXCLUSIVE SECTION START *****/
840	down_write(&tomoyo_domain_acl_info_list_lock);
841	if (is_delete)
842		goto delete;
843	list_for_each_entry(ptr, &domain->acl_info_list, list) {
844		if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
845			continue;
846		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
847				   head);
848		if (acl->filename1 != saved_filename1 ||
849		    acl->filename2 != saved_filename2)
850			continue;
851		/* Special case. Clear all bits if marked as deleted. */
852		if (ptr->type & TOMOYO_ACL_DELETED)
853			acl->perm = 0;
854		acl->perm |= perm;
855		ptr->type &= ~TOMOYO_ACL_DELETED;
856		error = 0;
857		goto out;
858	}
859	/* Not found. Append it to the tail. */
860	acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
861	if (!acl)
862		goto out;
863	acl->perm = perm;
864	acl->filename1 = saved_filename1;
865	acl->filename2 = saved_filename2;
866	list_add_tail(&acl->head.list, &domain->acl_info_list);
867	error = 0;
868	goto out;
869 delete:
870	error = -ENOENT;
871	list_for_each_entry(ptr, &domain->acl_info_list, list) {
872		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
873			continue;
874		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
875				   head);
876		if (acl->filename1 != saved_filename1 ||
877		    acl->filename2 != saved_filename2)
878			continue;
879		acl->perm &= ~perm;
880		if (!acl->perm)
881			ptr->type |= TOMOYO_ACL_DELETED;
882		error = 0;
883		break;
884	}
885 out:
886	up_write(&tomoyo_domain_acl_info_list_lock);
887	/***** EXCLUSIVE SECTION END *****/
888	return error;
889}
890
891/**
892 * tomoyo_check_single_path_acl - Check permission for single path operation.
893 *
894 * @domain:   Pointer to "struct tomoyo_domain_info".
895 * @type:     Type of operation.
896 * @filename: Filename to check.
897 *
898 * Returns 0 on success, negative value otherwise.
899 */
900static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
901					const u8 type,
902					const struct tomoyo_path_info *filename)
903{
904	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
905		return 0;
906	return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1);
907}
908
909/**
910 * tomoyo_check_double_path_acl - Check permission for double path operation.
911 *
912 * @domain:    Pointer to "struct tomoyo_domain_info".
913 * @type:      Type of operation.
914 * @filename1: First filename to check.
915 * @filename2: Second filename to check.
916 *
917 * Returns 0 on success, -EPERM otherwise.
918 */
919static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
920					const u8 type,
921					const struct tomoyo_path_info *
922					filename1,
923					const struct tomoyo_path_info *
924					filename2)
925{
926	struct tomoyo_acl_info *ptr;
927	const u8 perm = 1 << type;
928	int error = -EPERM;
929
930	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
931		return 0;
932	down_read(&tomoyo_domain_acl_info_list_lock);
933	list_for_each_entry(ptr, &domain->acl_info_list, list) {
934		struct tomoyo_double_path_acl_record *acl;
935		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
936			continue;
937		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
938				   head);
939		if (!(acl->perm & perm))
940			continue;
941		if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
942			continue;
943		if (!tomoyo_path_matches_pattern(filename2, acl->filename2))
944			continue;
945		error = 0;
946		break;
947	}
948	up_read(&tomoyo_domain_acl_info_list_lock);
949	return error;
950}
951
952/**
953 * tomoyo_check_single_path_permission2 - Check permission for single path operation.
954 *
955 * @domain:    Pointer to "struct tomoyo_domain_info".
956 * @operation: Type of operation.
957 * @filename:  Filename to check.
958 * @mode:      Access control mode.
959 *
960 * Returns 0 on success, negative value otherwise.
961 */
962static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
963						const domain, u8 operation,
964						const struct tomoyo_path_info *
965						filename, const u8 mode)
966{
967	const char *msg;
968	int error;
969	const bool is_enforce = (mode == 3);
970
971	if (!mode)
972		return 0;
973 next:
974	error = tomoyo_check_single_path_acl(domain, operation, filename);
975	msg = tomoyo_sp2keyword(operation);
976	if (!error)
977		goto ok;
978	if (tomoyo_verbose_mode(domain))
979		printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n",
980		       tomoyo_get_msg(is_enforce), msg, filename->name,
981		       tomoyo_get_last_name(domain));
982	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
983		const char *name = tomoyo_get_file_pattern(filename)->name;
984		tomoyo_update_single_path_acl(operation, name, domain, false);
985	}
986	if (!is_enforce)
987		error = 0;
988 ok:
989	/*
990	 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
991	 * we need to check "allow_rewrite" permission if the filename is
992	 * specified by "deny_rewrite" keyword.
993	 */
994	if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL &&
995	    tomoyo_is_no_rewrite_file(filename)) {
996		operation = TOMOYO_TYPE_REWRITE_ACL;
997		goto next;
998	}
999	return error;
1000}
1001
1002/**
1003 * tomoyo_check_file_perm - Check permission for sysctl()'s "read" and "write".
1004 *
1005 * @domain:    Pointer to "struct tomoyo_domain_info".
1006 * @filename:  Filename to check.
1007 * @perm:      Mode ("read" or "write" or "read/write").
1008 * Returns 0 on success, negative value otherwise.
1009 */
1010int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
1011			   const char *filename, const u8 perm)
1012{
1013	struct tomoyo_path_info name;
1014	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1015
1016	if (!mode)
1017		return 0;
1018	name.name = filename;
1019	tomoyo_fill_path_info(&name);
1020	return tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode);
1021}
1022
1023/**
1024 * tomoyo_check_exec_perm - Check permission for "execute".
1025 *
1026 * @domain:   Pointer to "struct tomoyo_domain_info".
1027 * @filename: Check permission for "execute".
1028 * @tmp:      Buffer for temporary use.
1029 *
1030 * Returns 0 on success, negativevalue otherwise.
1031 */
1032int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
1033			   const struct tomoyo_path_info *filename,
1034			   struct tomoyo_page_buffer *tmp)
1035{
1036	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1037
1038	if (!mode)
1039		return 0;
1040	return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode);
1041}
1042
1043/**
1044 * tomoyo_check_open_permission - Check permission for "read" and "write".
1045 *
1046 * @domain: Pointer to "struct tomoyo_domain_info".
1047 * @path:   Pointer to "struct path".
1048 * @flag:   Flags for open().
1049 *
1050 * Returns 0 on success, negative value otherwise.
1051 */
1052int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1053				 struct path *path, const int flag)
1054{
1055	const u8 acc_mode = ACC_MODE(flag);
1056	int error = -ENOMEM;
1057	struct tomoyo_path_info *buf;
1058	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1059	const bool is_enforce = (mode == 3);
1060
1061	if (!mode || !path->mnt)
1062		return 0;
1063	if (acc_mode == 0)
1064		return 0;
1065	if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
1066		/*
1067		 * I don't check directories here because mkdir() and rmdir()
1068		 * don't call me.
1069		 */
1070		return 0;
1071	buf = tomoyo_get_path(path);
1072	if (!buf)
1073		goto out;
1074	error = 0;
1075	/*
1076	 * If the filename is specified by "deny_rewrite" keyword,
1077	 * we need to check "allow_rewrite" permission when the filename is not
1078	 * opened for append mode or the filename is truncated at open time.
1079	 */
1080	if ((acc_mode & MAY_WRITE) &&
1081	    ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
1082	    (tomoyo_is_no_rewrite_file(buf))) {
1083		error = tomoyo_check_single_path_permission2(domain,
1084						     TOMOYO_TYPE_REWRITE_ACL,
1085							     buf, mode);
1086	}
1087	if (!error)
1088		error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
1089						mode);
1090	if (!error && (flag & O_TRUNC))
1091		error = tomoyo_check_single_path_permission2(domain,
1092						     TOMOYO_TYPE_TRUNCATE_ACL,
1093							     buf, mode);
1094 out:
1095	tomoyo_free(buf);
1096	if (!is_enforce)
1097		error = 0;
1098	return error;
1099}
1100
1101/**
1102 * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink".
1103 *
1104 * @domain:    Pointer to "struct tomoyo_domain_info".
1105 * @operation: Type of operation.
1106 * @path:      Pointer to "struct path".
1107 *
1108 * Returns 0 on success, negative value otherwise.
1109 */
1110int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
1111			    const u8 operation, struct path *path)
1112{
1113	int error = -ENOMEM;
1114	struct tomoyo_path_info *buf;
1115	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1116	const bool is_enforce = (mode == 3);
1117
1118	if (!mode || !path->mnt)
1119		return 0;
1120	buf = tomoyo_get_path(path);
1121	if (!buf)
1122		goto out;
1123	switch (operation) {
1124	case TOMOYO_TYPE_MKDIR_ACL:
1125	case TOMOYO_TYPE_RMDIR_ACL:
1126		if (!buf->is_dir) {
1127			/*
1128			 * tomoyo_get_path() reserves space for appending "/."
1129			 */
1130			strcat((char *) buf->name, "/");
1131			tomoyo_fill_path_info(buf);
1132		}
1133	}
1134	error = tomoyo_check_single_path_permission2(domain, operation, buf,
1135						     mode);
1136 out:
1137	tomoyo_free(buf);
1138	if (!is_enforce)
1139		error = 0;
1140	return error;
1141}
1142
1143/**
1144 * tomoyo_check_rewrite_permission - Check permission for "rewrite".
1145 *
1146 * @domain: Pointer to "struct tomoyo_domain_info".
1147 * @filp: Pointer to "struct file".
1148 *
1149 * Returns 0 on success, negative value otherwise.
1150 */
1151int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
1152				    struct file *filp)
1153{
1154	int error = -ENOMEM;
1155	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1156	const bool is_enforce = (mode == 3);
1157	struct tomoyo_path_info *buf;
1158
1159	if (!mode || !filp->f_path.mnt)
1160		return 0;
1161	buf = tomoyo_get_path(&filp->f_path);
1162	if (!buf)
1163		goto out;
1164	if (!tomoyo_is_no_rewrite_file(buf)) {
1165		error = 0;
1166		goto out;
1167	}
1168	error = tomoyo_check_single_path_permission2(domain,
1169						     TOMOYO_TYPE_REWRITE_ACL,
1170						     buf, mode);
1171 out:
1172	tomoyo_free(buf);
1173	if (!is_enforce)
1174		error = 0;
1175	return error;
1176}
1177
1178/**
1179 * tomoyo_check_2path_perm - Check permission for "rename" and "link".
1180 *
1181 * @domain:    Pointer to "struct tomoyo_domain_info".
1182 * @operation: Type of operation.
1183 * @path1:      Pointer to "struct path".
1184 * @path2:      Pointer to "struct path".
1185 *
1186 * Returns 0 on success, negative value otherwise.
1187 */
1188int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
1189			    const u8 operation, struct path *path1,
1190			    struct path *path2)
1191{
1192	int error = -ENOMEM;
1193	struct tomoyo_path_info *buf1, *buf2;
1194	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1195	const bool is_enforce = (mode == 3);
1196	const char *msg;
1197
1198	if (!mode || !path1->mnt || !path2->mnt)
1199		return 0;
1200	buf1 = tomoyo_get_path(path1);
1201	buf2 = tomoyo_get_path(path2);
1202	if (!buf1 || !buf2)
1203		goto out;
1204	{
1205		struct dentry *dentry = path1->dentry;
1206		if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
1207			/*
1208			 * tomoyo_get_path() reserves space for appending "/."
1209			 */
1210			if (!buf1->is_dir) {
1211				strcat((char *) buf1->name, "/");
1212				tomoyo_fill_path_info(buf1);
1213			}
1214			if (!buf2->is_dir) {
1215				strcat((char *) buf2->name, "/");
1216				tomoyo_fill_path_info(buf2);
1217			}
1218		}
1219	}
1220	error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2);
1221	msg = tomoyo_dp2keyword(operation);
1222	if (!error)
1223		goto out;
1224	if (tomoyo_verbose_mode(domain))
1225		printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' "
1226		       "denied for %s\n", tomoyo_get_msg(is_enforce),
1227		       msg, buf1->name, buf2->name,
1228		       tomoyo_get_last_name(domain));
1229	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
1230		const char *name1 = tomoyo_get_file_pattern(buf1)->name;
1231		const char *name2 = tomoyo_get_file_pattern(buf2)->name;
1232		tomoyo_update_double_path_acl(operation, name1, name2, domain,
1233					      false);
1234	}
1235 out:
1236	tomoyo_free(buf1);
1237	tomoyo_free(buf2);
1238	if (!is_enforce)
1239		error = 0;
1240	return error;
1241}
1242