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