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