xref: /openbmc/linux/security/tomoyo/group.c (revision 9c1f8594)
1 /*
2  * security/tomoyo/group.c
3  *
4  * Copyright (C) 2005-2011  NTT DATA CORPORATION
5  */
6 
7 #include <linux/slab.h>
8 #include "common.h"
9 
10 /**
11  * tomoyo_same_path_group - Check for duplicated "struct tomoyo_path_group" entry.
12  *
13  * @a: Pointer to "struct tomoyo_acl_head".
14  * @b: Pointer to "struct tomoyo_acl_head".
15  *
16  * Returns true if @a == @b, false otherwise.
17  */
18 static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
19 				   const struct tomoyo_acl_head *b)
20 {
21 	return container_of(a, struct tomoyo_path_group, head)->member_name ==
22 		container_of(b, struct tomoyo_path_group, head)->member_name;
23 }
24 
25 /**
26  * tomoyo_same_number_group - Check for duplicated "struct tomoyo_number_group" entry.
27  *
28  * @a: Pointer to "struct tomoyo_acl_head".
29  * @b: Pointer to "struct tomoyo_acl_head".
30  *
31  * Returns true if @a == @b, false otherwise.
32  */
33 static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
34 				     const struct tomoyo_acl_head *b)
35 {
36 	return !memcmp(&container_of(a, struct tomoyo_number_group, head)
37 		       ->number,
38 		       &container_of(b, struct tomoyo_number_group, head)
39 		       ->number,
40 		       sizeof(container_of(a, struct tomoyo_number_group, head)
41 			      ->number));
42 }
43 
44 /**
45  * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list.
46  *
47  * @param: Pointer to "struct tomoyo_acl_param".
48  * @type:  Type of this group.
49  *
50  * Returns 0 on success, negative value otherwise.
51  */
52 int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type)
53 {
54 	struct tomoyo_group *group = tomoyo_get_group(param, type);
55 	int error = -EINVAL;
56 	if (!group)
57 		return -ENOMEM;
58 	param->list = &group->member_list;
59 	if (type == TOMOYO_PATH_GROUP) {
60 		struct tomoyo_path_group e = { };
61 		e.member_name = tomoyo_get_name(tomoyo_read_token(param));
62 		if (!e.member_name) {
63 			error = -ENOMEM;
64 			goto out;
65 		}
66 		error = tomoyo_update_policy(&e.head, sizeof(e), param,
67 					  tomoyo_same_path_group);
68 		tomoyo_put_name(e.member_name);
69 	} else if (type == TOMOYO_NUMBER_GROUP) {
70 		struct tomoyo_number_group e = { };
71 		if (param->data[0] == '@' ||
72 		    !tomoyo_parse_number_union(param, &e.number))
73 			goto out;
74 		error = tomoyo_update_policy(&e.head, sizeof(e), param,
75 					  tomoyo_same_number_group);
76 		/*
77 		 * tomoyo_put_number_union() is not needed because
78 		 * param->data[0] != '@'.
79 		 */
80 	}
81 out:
82 	tomoyo_put_group(group);
83 	return error;
84 }
85 
86 /**
87  * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group.
88  *
89  * @pathname: The name of pathname.
90  * @group:    Pointer to "struct tomoyo_path_group".
91  *
92  * Returns matched member's pathname if @pathname matches pathnames in @group,
93  * NULL otherwise.
94  *
95  * Caller holds tomoyo_read_lock().
96  */
97 const struct tomoyo_path_info *
98 tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
99 			  const struct tomoyo_group *group)
100 {
101 	struct tomoyo_path_group *member;
102 	list_for_each_entry_rcu(member, &group->member_list, head.list) {
103 		if (member->head.is_deleted)
104 			continue;
105 		if (!tomoyo_path_matches_pattern(pathname, member->member_name))
106 			continue;
107 		return member->member_name;
108 	}
109 	return NULL;
110 }
111 
112 /**
113  * tomoyo_number_matches_group - Check whether the given number matches members of the given number group.
114  *
115  * @min:   Min number.
116  * @max:   Max number.
117  * @group: Pointer to "struct tomoyo_number_group".
118  *
119  * Returns true if @min and @max partially overlaps @group, false otherwise.
120  *
121  * Caller holds tomoyo_read_lock().
122  */
123 bool tomoyo_number_matches_group(const unsigned long min,
124 				 const unsigned long max,
125 				 const struct tomoyo_group *group)
126 {
127 	struct tomoyo_number_group *member;
128 	bool matched = false;
129 	list_for_each_entry_rcu(member, &group->member_list, head.list) {
130 		if (member->head.is_deleted)
131 			continue;
132 		if (min > member->number.values[1] ||
133 		    max < member->number.values[0])
134 			continue;
135 		matched = true;
136 		break;
137 	}
138 	return matched;
139 }
140