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