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