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