xref: /linux/security/tomoyo/group.c (revision 0f2a55d5bb2372058275b0b343d90dd5d640d045)
17c2ea22eSTetsuo Handa /*
27c2ea22eSTetsuo Handa  * security/tomoyo/group.c
37c2ea22eSTetsuo Handa  *
4*0f2a55d5STetsuo Handa  * Copyright (C) 2005-2011  NTT DATA CORPORATION
57c2ea22eSTetsuo Handa  */
67c2ea22eSTetsuo Handa 
77c2ea22eSTetsuo Handa #include <linux/slab.h>
87c2ea22eSTetsuo Handa #include "common.h"
97c2ea22eSTetsuo Handa 
10*0f2a55d5STetsuo Handa /**
11*0f2a55d5STetsuo Handa  * tomoyo_same_path_group - Check for duplicated "struct tomoyo_path_group" entry.
12*0f2a55d5STetsuo Handa  *
13*0f2a55d5STetsuo Handa  * @a: Pointer to "struct tomoyo_acl_head".
14*0f2a55d5STetsuo Handa  * @b: Pointer to "struct tomoyo_acl_head".
15*0f2a55d5STetsuo Handa  *
16*0f2a55d5STetsuo Handa  * Returns true if @a == @b, false otherwise.
17*0f2a55d5STetsuo Handa  */
187c2ea22eSTetsuo Handa static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
197c2ea22eSTetsuo Handa 				   const struct tomoyo_acl_head *b)
207c2ea22eSTetsuo Handa {
217c2ea22eSTetsuo Handa 	return container_of(a, struct tomoyo_path_group, head)->member_name ==
227c2ea22eSTetsuo Handa 		container_of(b, struct tomoyo_path_group, head)->member_name;
237c2ea22eSTetsuo Handa }
247c2ea22eSTetsuo Handa 
25*0f2a55d5STetsuo Handa /**
26*0f2a55d5STetsuo Handa  * tomoyo_same_number_group - Check for duplicated "struct tomoyo_number_group" entry.
27*0f2a55d5STetsuo Handa  *
28*0f2a55d5STetsuo Handa  * @a: Pointer to "struct tomoyo_acl_head".
29*0f2a55d5STetsuo Handa  * @b: Pointer to "struct tomoyo_acl_head".
30*0f2a55d5STetsuo Handa  *
31*0f2a55d5STetsuo Handa  * Returns true if @a == @b, false otherwise.
32*0f2a55d5STetsuo Handa  */
337c2ea22eSTetsuo Handa static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
347c2ea22eSTetsuo Handa 				     const struct tomoyo_acl_head *b)
357c2ea22eSTetsuo Handa {
367c2ea22eSTetsuo Handa 	return !memcmp(&container_of(a, struct tomoyo_number_group, head)
377c2ea22eSTetsuo Handa 		       ->number,
387c2ea22eSTetsuo Handa 		       &container_of(b, struct tomoyo_number_group, head)
397c2ea22eSTetsuo Handa 		       ->number,
407c2ea22eSTetsuo Handa 		       sizeof(container_of(a, struct tomoyo_number_group, head)
417c2ea22eSTetsuo Handa 			      ->number));
427c2ea22eSTetsuo Handa }
437c2ea22eSTetsuo Handa 
447c2ea22eSTetsuo Handa /**
457c2ea22eSTetsuo Handa  * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list.
467c2ea22eSTetsuo Handa  *
47a238cf5bSTetsuo Handa  * @param: Pointer to "struct tomoyo_acl_param".
487c2ea22eSTetsuo Handa  * @type:  Type of this group.
497c2ea22eSTetsuo Handa  *
507c2ea22eSTetsuo Handa  * Returns 0 on success, negative value otherwise.
517c2ea22eSTetsuo Handa  */
52a238cf5bSTetsuo Handa int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type)
537c2ea22eSTetsuo Handa {
54a238cf5bSTetsuo Handa 	struct tomoyo_group *group = tomoyo_get_group(param, type);
557c2ea22eSTetsuo Handa 	int error = -EINVAL;
567c2ea22eSTetsuo Handa 	if (!group)
577c2ea22eSTetsuo Handa 		return -ENOMEM;
58a238cf5bSTetsuo Handa 	param->list = &group->member_list;
597c2ea22eSTetsuo Handa 	if (type == TOMOYO_PATH_GROUP) {
607c2ea22eSTetsuo Handa 		struct tomoyo_path_group e = { };
61a238cf5bSTetsuo Handa 		e.member_name = tomoyo_get_name(tomoyo_read_token(param));
627c2ea22eSTetsuo Handa 		if (!e.member_name) {
637c2ea22eSTetsuo Handa 			error = -ENOMEM;
647c2ea22eSTetsuo Handa 			goto out;
657c2ea22eSTetsuo Handa 		}
66a238cf5bSTetsuo Handa 		error = tomoyo_update_policy(&e.head, sizeof(e), param,
67a238cf5bSTetsuo Handa 					  tomoyo_same_path_group);
687c2ea22eSTetsuo Handa 		tomoyo_put_name(e.member_name);
697c2ea22eSTetsuo Handa 	} else if (type == TOMOYO_NUMBER_GROUP) {
707c2ea22eSTetsuo Handa 		struct tomoyo_number_group e = { };
71a238cf5bSTetsuo Handa 		if (param->data[0] == '@' ||
72a238cf5bSTetsuo Handa 		    !tomoyo_parse_number_union(param, &e.number))
737c2ea22eSTetsuo Handa 			goto out;
74a238cf5bSTetsuo Handa 		error = tomoyo_update_policy(&e.head, sizeof(e), param,
75a238cf5bSTetsuo Handa 					  tomoyo_same_number_group);
767c2ea22eSTetsuo Handa 		/*
777c2ea22eSTetsuo Handa 		 * tomoyo_put_number_union() is not needed because
78a238cf5bSTetsuo Handa 		 * param->data[0] != '@'.
797c2ea22eSTetsuo Handa 		 */
807c2ea22eSTetsuo Handa 	}
817c2ea22eSTetsuo Handa out:
827c2ea22eSTetsuo Handa 	tomoyo_put_group(group);
837c2ea22eSTetsuo Handa 	return error;
847c2ea22eSTetsuo Handa }
857c2ea22eSTetsuo Handa 
867c2ea22eSTetsuo Handa /**
877c2ea22eSTetsuo Handa  * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group.
887c2ea22eSTetsuo Handa  *
897c2ea22eSTetsuo Handa  * @pathname: The name of pathname.
907c2ea22eSTetsuo Handa  * @group:    Pointer to "struct tomoyo_path_group".
917c2ea22eSTetsuo Handa  *
92484ca79cSTetsuo Handa  * Returns matched member's pathname if @pathname matches pathnames in @group,
93484ca79cSTetsuo Handa  * NULL otherwise.
947c2ea22eSTetsuo Handa  *
957c2ea22eSTetsuo Handa  * Caller holds tomoyo_read_lock().
967c2ea22eSTetsuo Handa  */
97484ca79cSTetsuo Handa const struct tomoyo_path_info *
98484ca79cSTetsuo Handa tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
997c2ea22eSTetsuo Handa 			  const struct tomoyo_group *group)
1007c2ea22eSTetsuo Handa {
1017c2ea22eSTetsuo Handa 	struct tomoyo_path_group *member;
1027c2ea22eSTetsuo Handa 	list_for_each_entry_rcu(member, &group->member_list, head.list) {
1037c2ea22eSTetsuo Handa 		if (member->head.is_deleted)
1047c2ea22eSTetsuo Handa 			continue;
1057c2ea22eSTetsuo Handa 		if (!tomoyo_path_matches_pattern(pathname, member->member_name))
1067c2ea22eSTetsuo Handa 			continue;
107484ca79cSTetsuo Handa 		return member->member_name;
1087c2ea22eSTetsuo Handa 	}
109484ca79cSTetsuo Handa 	return NULL;
1107c2ea22eSTetsuo Handa }
1117c2ea22eSTetsuo Handa 
1127c2ea22eSTetsuo Handa /**
1137c2ea22eSTetsuo Handa  * tomoyo_number_matches_group - Check whether the given number matches members of the given number group.
1147c2ea22eSTetsuo Handa  *
1157c2ea22eSTetsuo Handa  * @min:   Min number.
1167c2ea22eSTetsuo Handa  * @max:   Max number.
1177c2ea22eSTetsuo Handa  * @group: Pointer to "struct tomoyo_number_group".
1187c2ea22eSTetsuo Handa  *
1197c2ea22eSTetsuo Handa  * Returns true if @min and @max partially overlaps @group, false otherwise.
1207c2ea22eSTetsuo Handa  *
1217c2ea22eSTetsuo Handa  * Caller holds tomoyo_read_lock().
1227c2ea22eSTetsuo Handa  */
1237c2ea22eSTetsuo Handa bool tomoyo_number_matches_group(const unsigned long min,
1247c2ea22eSTetsuo Handa 				 const unsigned long max,
1257c2ea22eSTetsuo Handa 				 const struct tomoyo_group *group)
1267c2ea22eSTetsuo Handa {
1277c2ea22eSTetsuo Handa 	struct tomoyo_number_group *member;
1287c2ea22eSTetsuo Handa 	bool matched = false;
1297c2ea22eSTetsuo Handa 	list_for_each_entry_rcu(member, &group->member_list, head.list) {
1307c2ea22eSTetsuo Handa 		if (member->head.is_deleted)
1317c2ea22eSTetsuo Handa 			continue;
1327c2ea22eSTetsuo Handa 		if (min > member->number.values[1] ||
1337c2ea22eSTetsuo Handa 		    max < member->number.values[0])
1347c2ea22eSTetsuo Handa 			continue;
1357c2ea22eSTetsuo Handa 		matched = true;
1367c2ea22eSTetsuo Handa 		break;
1377c2ea22eSTetsuo Handa 	}
1387c2ea22eSTetsuo Handa 	return matched;
1397c2ea22eSTetsuo Handa }
140