aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo')
-rw-r--r--security/tomoyo/Makefile2
-rw-r--r--security/tomoyo/common.c161
-rw-r--r--security/tomoyo/common.h61
-rw-r--r--security/tomoyo/file.c14
-rw-r--r--security/tomoyo/gc.c41
-rw-r--r--security/tomoyo/number_group.c176
6 files changed, 454 insertions, 1 deletions
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
index 4fb39030f6bd..4d1b5af4f1f7 100644
--- a/security/tomoyo/Makefile
+++ b/security/tomoyo/Makefile
@@ -1 +1 @@
obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o number_group.o
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index b5dbdc9ff73c..d82c2978b1be 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -119,6 +119,159 @@ static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head,
119} 119}
120 120
121/** 121/**
122 * tomoyo_parse_ulong - Parse an "unsigned long" value.
123 *
124 * @result: Pointer to "unsigned long".
125 * @str: Pointer to string to parse.
126 *
127 * Returns value type on success, 0 otherwise.
128 *
129 * The @src is updated to point the first character after the value
130 * on success.
131 */
132u8 tomoyo_parse_ulong(unsigned long *result, char **str)
133{
134 const char *cp = *str;
135 char *ep;
136 int base = 10;
137 if (*cp == '0') {
138 char c = *(cp + 1);
139 if (c == 'x' || c == 'X') {
140 base = 16;
141 cp += 2;
142 } else if (c >= '0' && c <= '7') {
143 base = 8;
144 cp++;
145 }
146 }
147 *result = simple_strtoul(cp, &ep, base);
148 if (cp == ep)
149 return 0;
150 *str = ep;
151 switch (base) {
152 case 16:
153 return TOMOYO_VALUE_TYPE_HEXADECIMAL;
154 case 8:
155 return TOMOYO_VALUE_TYPE_OCTAL;
156 default:
157 return TOMOYO_VALUE_TYPE_DECIMAL;
158 }
159}
160
161/**
162 * tomoyo_print_ulong - Print an "unsigned long" value.
163 *
164 * @buffer: Pointer to buffer.
165 * @buffer_len: Size of @buffer.
166 * @value: An "unsigned long" value.
167 * @type: Type of @value.
168 *
169 * Returns nothing.
170 */
171void tomoyo_print_ulong(char *buffer, const int buffer_len,
172 const unsigned long value, const u8 type)
173{
174 if (type == TOMOYO_VALUE_TYPE_DECIMAL)
175 snprintf(buffer, buffer_len, "%lu", value);
176 else if (type == TOMOYO_VALUE_TYPE_OCTAL)
177 snprintf(buffer, buffer_len, "0%lo", value);
178 else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL)
179 snprintf(buffer, buffer_len, "0x%lX", value);
180 else
181 snprintf(buffer, buffer_len, "type(%u)", type);
182}
183
184/**
185 * tomoyo_print_number_union - Print a tomoyo_number_union.
186 *
187 * @head: Pointer to "struct tomoyo_io_buffer".
188 * @ptr: Pointer to "struct tomoyo_number_union".
189 *
190 * Returns true on success, false otherwise.
191 */
192bool tomoyo_print_number_union(struct tomoyo_io_buffer *head,
193 const struct tomoyo_number_union *ptr)
194{
195 unsigned long min;
196 unsigned long max;
197 u8 min_type;
198 u8 max_type;
199 if (!tomoyo_io_printf(head, " "))
200 return false;
201 if (ptr->is_group)
202 return tomoyo_io_printf(head, "@%s",
203 ptr->group->group_name->name);
204 min_type = ptr->min_type;
205 max_type = ptr->max_type;
206 min = ptr->values[0];
207 max = ptr->values[1];
208 switch (min_type) {
209 case TOMOYO_VALUE_TYPE_HEXADECIMAL:
210 if (!tomoyo_io_printf(head, "0x%lX", min))
211 return false;
212 break;
213 case TOMOYO_VALUE_TYPE_OCTAL:
214 if (!tomoyo_io_printf(head, "0%lo", min))
215 return false;
216 break;
217 default:
218 if (!tomoyo_io_printf(head, "%lu", min))
219 return false;
220 break;
221 }
222 if (min == max && min_type == max_type)
223 return true;
224 switch (max_type) {
225 case TOMOYO_VALUE_TYPE_HEXADECIMAL:
226 return tomoyo_io_printf(head, "-0x%lX", max);
227 case TOMOYO_VALUE_TYPE_OCTAL:
228 return tomoyo_io_printf(head, "-0%lo", max);
229 default:
230 return tomoyo_io_printf(head, "-%lu", max);
231 }
232}
233
234/**
235 * tomoyo_parse_number_union - Parse a tomoyo_number_union.
236 *
237 * @data: Number or number range or number group.
238 * @ptr: Pointer to "struct tomoyo_number_union".
239 *
240 * Returns true on success, false otherwise.
241 */
242bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
243{
244 u8 type;
245 unsigned long v;
246 memset(num, 0, sizeof(*num));
247 if (data[0] == '@') {
248 if (!tomoyo_is_correct_path(data, 0, 0, 0))
249 return false;
250 num->group = tomoyo_get_number_group(data + 1);
251 num->is_group = true;
252 return num->group != NULL;
253 }
254 type = tomoyo_parse_ulong(&v, &data);
255 if (!type)
256 return false;
257 num->values[0] = v;
258 num->min_type = type;
259 if (!*data) {
260 num->values[1] = v;
261 num->max_type = type;
262 return true;
263 }
264 if (*data++ != '-')
265 return false;
266 type = tomoyo_parse_ulong(&v, &data);
267 if (!type || *data)
268 return false;
269 num->values[1] = v;
270 num->max_type = type;
271 return true;
272}
273
274/**
122 * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value. 275 * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value.
123 * 276 *
124 * @str: Pointer to the string. 277 * @str: Pointer to the string.
@@ -1750,6 +1903,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
1750 return tomoyo_write_no_rewrite_policy(data, is_delete); 1903 return tomoyo_write_no_rewrite_policy(data, is_delete);
1751 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) 1904 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP))
1752 return tomoyo_write_path_group_policy(data, is_delete); 1905 return tomoyo_write_path_group_policy(data, is_delete);
1906 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NUMBER_GROUP))
1907 return tomoyo_write_number_group_policy(data, is_delete);
1753 return -EINVAL; 1908 return -EINVAL;
1754} 1909}
1755 1910
@@ -1812,6 +1967,12 @@ static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
1812 head->read_var2 = NULL; 1967 head->read_var2 = NULL;
1813 head->read_step = 10; 1968 head->read_step = 10;
1814 case 10: 1969 case 10:
1970 if (!tomoyo_read_number_group_policy(head))
1971 break;
1972 head->read_var1 = NULL;
1973 head->read_var2 = NULL;
1974 head->read_step = 11;
1975 case 11:
1815 head->read_eof = true; 1976 head->read_eof = true;
1816 break; 1977 break;
1817 default: 1978 default:
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 9f1ae5e3ba51..33d3072f9bb4 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -55,6 +55,7 @@ struct linux_binprm;
55#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " 55#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain "
56#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " 56#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain "
57#define TOMOYO_KEYWORD_PATH_GROUP "path_group " 57#define TOMOYO_KEYWORD_PATH_GROUP "path_group "
58#define TOMOYO_KEYWORD_NUMBER_GROUP "number_group "
58#define TOMOYO_KEYWORD_SELECT "select " 59#define TOMOYO_KEYWORD_SELECT "select "
59#define TOMOYO_KEYWORD_USE_PROFILE "use_profile " 60#define TOMOYO_KEYWORD_USE_PROFILE "use_profile "
60#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" 61#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read"
@@ -62,6 +63,12 @@ struct linux_binprm;
62#define TOMOYO_ROOT_NAME "<kernel>" 63#define TOMOYO_ROOT_NAME "<kernel>"
63#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) 64#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1)
64 65
66/* Value type definition. */
67#define TOMOYO_VALUE_TYPE_INVALID 0
68#define TOMOYO_VALUE_TYPE_DECIMAL 1
69#define TOMOYO_VALUE_TYPE_OCTAL 2
70#define TOMOYO_VALUE_TYPE_HEXADECIMAL 3
71
65/* Index numbers for Access Controls. */ 72/* Index numbers for Access Controls. */
66enum tomoyo_mac_index { 73enum tomoyo_mac_index {
67 TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */ 74 TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */
@@ -211,6 +218,14 @@ struct tomoyo_name_union {
211 u8 is_group; 218 u8 is_group;
212}; 219};
213 220
221struct tomoyo_number_union {
222 unsigned long values[2];
223 struct tomoyo_number_group *group;
224 u8 min_type;
225 u8 max_type;
226 u8 is_group;
227};
228
214/* Structure for "path_group" directive. */ 229/* Structure for "path_group" directive. */
215struct tomoyo_path_group { 230struct tomoyo_path_group {
216 struct list_head list; 231 struct list_head list;
@@ -219,6 +234,14 @@ struct tomoyo_path_group {
219 atomic_t users; 234 atomic_t users;
220}; 235};
221 236
237/* Structure for "number_group" directive. */
238struct tomoyo_number_group {
239 struct list_head list;
240 const struct tomoyo_path_info *group_name;
241 struct list_head member_list;
242 atomic_t users;
243};
244
222/* Structure for "path_group" directive. */ 245/* Structure for "path_group" directive. */
223struct tomoyo_path_group_member { 246struct tomoyo_path_group_member {
224 struct list_head list; 247 struct list_head list;
@@ -226,6 +249,13 @@ struct tomoyo_path_group_member {
226 const struct tomoyo_path_info *member_name; 249 const struct tomoyo_path_info *member_name;
227}; 250};
228 251
252/* Structure for "number_group" directive. */
253struct tomoyo_number_group_member {
254 struct list_head list;
255 bool is_deleted;
256 struct tomoyo_number_union number;
257};
258
229/* 259/*
230 * tomoyo_acl_info is a structure which is used for holding 260 * tomoyo_acl_info is a structure which is used for holding
231 * 261 *
@@ -554,9 +584,18 @@ bool tomoyo_parse_name_union(const char *filename,
554bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, 584bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
555 const struct tomoyo_path_group *group, 585 const struct tomoyo_path_group *group,
556 const bool may_use_pattern); 586 const bool may_use_pattern);
587/* Check whether the given value matches the given number_group. */
588bool tomoyo_number_matches_group(const unsigned long min,
589 const unsigned long max,
590 const struct tomoyo_number_group *group);
557/* Check whether the given filename matches the given pattern. */ 591/* Check whether the given filename matches the given pattern. */
558bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 592bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
559 const struct tomoyo_path_info *pattern); 593 const struct tomoyo_path_info *pattern);
594
595bool tomoyo_print_number_union(struct tomoyo_io_buffer *head,
596 const struct tomoyo_number_union *ptr);
597bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num);
598
560/* Read "alias" entry in exception policy. */ 599/* Read "alias" entry in exception policy. */
561bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head); 600bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head);
562/* 601/*
@@ -570,6 +609,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head);
570bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); 609bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head);
571/* Read "path_group" entry in exception policy. */ 610/* Read "path_group" entry in exception policy. */
572bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head); 611bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head);
612/* Read "number_group" entry in exception policy. */
613bool tomoyo_read_number_group_policy(struct tomoyo_io_buffer *head);
573/* Read "allow_read" entry in exception policy. */ 614/* Read "allow_read" entry in exception policy. */
574bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); 615bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head);
575/* Read "deny_rewrite" entry in exception policy. */ 616/* Read "deny_rewrite" entry in exception policy. */
@@ -614,6 +655,8 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete);
614int tomoyo_write_pattern_policy(char *data, const bool is_delete); 655int tomoyo_write_pattern_policy(char *data, const bool is_delete);
615/* Create "path_group" entry in exception policy. */ 656/* Create "path_group" entry in exception policy. */
616int tomoyo_write_path_group_policy(char *data, const bool is_delete); 657int tomoyo_write_path_group_policy(char *data, const bool is_delete);
658/* Create "number_group" entry in exception policy. */
659int tomoyo_write_number_group_policy(char *data, const bool is_delete);
617/* Find a domain by the given name. */ 660/* Find a domain by the given name. */
618struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); 661struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
619/* Find or create a domain by the given name. */ 662/* Find or create a domain by the given name. */
@@ -623,6 +666,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
623 666
624/* Allocate memory for "struct tomoyo_path_group". */ 667/* Allocate memory for "struct tomoyo_path_group". */
625struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); 668struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name);
669struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name);
626 670
627/* Check mode for specified functionality. */ 671/* Check mode for specified functionality. */
628unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, 672unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
@@ -632,6 +676,8 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
632/* Run policy loader when /sbin/init starts. */ 676/* Run policy loader when /sbin/init starts. */
633void tomoyo_load_policy(const char *filename); 677void tomoyo_load_policy(const char *filename);
634 678
679void tomoyo_put_number_union(struct tomoyo_number_union *ptr);
680
635/* Convert binary string to ascii string. */ 681/* Convert binary string to ascii string. */
636int tomoyo_encode(char *buffer, int buflen, const char *str); 682int tomoyo_encode(char *buffer, int buflen, const char *str);
637 683
@@ -697,6 +743,7 @@ extern struct srcu_struct tomoyo_ss;
697extern struct list_head tomoyo_domain_list; 743extern struct list_head tomoyo_domain_list;
698 744
699extern struct list_head tomoyo_path_group_list; 745extern struct list_head tomoyo_path_group_list;
746extern struct list_head tomoyo_number_group_list;
700extern struct list_head tomoyo_domain_initializer_list; 747extern struct list_head tomoyo_domain_initializer_list;
701extern struct list_head tomoyo_domain_keeper_list; 748extern struct list_head tomoyo_domain_keeper_list;
702extern struct list_head tomoyo_alias_list; 749extern struct list_head tomoyo_alias_list;
@@ -773,6 +820,12 @@ static inline void tomoyo_put_path_group(struct tomoyo_path_group *group)
773 atomic_dec(&group->users); 820 atomic_dec(&group->users);
774} 821}
775 822
823static inline void tomoyo_put_number_group(struct tomoyo_number_group *group)
824{
825 if (group)
826 atomic_dec(&group->users);
827}
828
776static inline struct tomoyo_domain_info *tomoyo_domain(void) 829static inline struct tomoyo_domain_info *tomoyo_domain(void)
777{ 830{
778 return current_cred()->security; 831 return current_cred()->security;
@@ -797,6 +850,14 @@ static inline bool tomoyo_is_same_name_union
797 p1->is_group == p2->is_group; 850 p1->is_group == p2->is_group;
798} 851}
799 852
853static inline bool tomoyo_is_same_number_union
854(const struct tomoyo_number_union *p1, const struct tomoyo_number_union *p2)
855{
856 return p1->values[0] == p2->values[0] && p1->values[1] == p2->values[1]
857 && p1->group == p2->group && p1->min_type == p2->min_type &&
858 p1->max_type == p2->max_type && p1->is_group == p2->is_group;
859}
860
800static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1, 861static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1,
801 const struct tomoyo_path_acl *p2) 862 const struct tomoyo_path_acl *p2)
802{ 863{
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 1c6f8238ec47..2dffe0730918 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -76,6 +76,20 @@ static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info
76 return false; 76 return false;
77} 77}
78 78
79void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
80{
81 if (ptr && ptr->is_group)
82 tomoyo_put_number_group(ptr->group);
83}
84
85bool tomoyo_compare_number_union(const unsigned long value,
86 const struct tomoyo_number_union *ptr)
87{
88 if (ptr->is_group)
89 return tomoyo_number_matches_group(value, value, ptr->group);
90 return value >= ptr->values[0] && value <= ptr->values[1];
91}
92
79/** 93/**
80 * tomoyo_path2keyword - Get the name of single path operation. 94 * tomoyo_path2keyword - Get the name of single path operation.
81 * 95 *
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
index b9cc71b04314..6a48197f6ce5 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -14,6 +14,8 @@
14enum tomoyo_gc_id { 14enum tomoyo_gc_id {
15 TOMOYO_ID_PATH_GROUP, 15 TOMOYO_ID_PATH_GROUP,
16 TOMOYO_ID_PATH_GROUP_MEMBER, 16 TOMOYO_ID_PATH_GROUP_MEMBER,
17 TOMOYO_ID_NUMBER_GROUP,
18 TOMOYO_ID_NUMBER_GROUP_MEMBER,
17 TOMOYO_ID_DOMAIN_INITIALIZER, 19 TOMOYO_ID_DOMAIN_INITIALIZER,
18 TOMOYO_ID_DOMAIN_KEEPER, 20 TOMOYO_ID_DOMAIN_KEEPER,
19 TOMOYO_ID_ALIAS, 21 TOMOYO_ID_ALIAS,
@@ -162,6 +164,16 @@ static void tomoyo_del_path_group(struct tomoyo_path_group *group)
162 tomoyo_put_name(group->group_name); 164 tomoyo_put_name(group->group_name);
163} 165}
164 166
167static void tomoyo_del_number_group_member(struct tomoyo_number_group_member
168 *member)
169{
170}
171
172static void tomoyo_del_number_group(struct tomoyo_number_group *group)
173{
174 tomoyo_put_name(group->group_name);
175}
176
165static void tomoyo_collect_entry(void) 177static void tomoyo_collect_entry(void)
166{ 178{
167 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 179 if (mutex_lock_interruptible(&tomoyo_policy_lock))
@@ -329,6 +341,29 @@ static void tomoyo_collect_entry(void)
329 break; 341 break;
330 } 342 }
331 } 343 }
344 {
345 struct tomoyo_number_group *group;
346 list_for_each_entry_rcu(group, &tomoyo_number_group_list, list) {
347 struct tomoyo_number_group_member *member;
348 list_for_each_entry_rcu(member, &group->member_list,
349 list) {
350 if (!member->is_deleted)
351 continue;
352 if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP_MEMBER,
353 member))
354 list_del_rcu(&member->list);
355 else
356 break;
357 }
358 if (!list_empty(&group->member_list) ||
359 atomic_read(&group->users))
360 continue;
361 if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP, group))
362 list_del_rcu(&group->list);
363 else
364 break;
365 }
366 }
332 mutex_unlock(&tomoyo_policy_lock); 367 mutex_unlock(&tomoyo_policy_lock);
333} 368}
334 369
@@ -376,6 +411,12 @@ static void tomoyo_kfree_entry(void)
376 case TOMOYO_ID_PATH_GROUP: 411 case TOMOYO_ID_PATH_GROUP:
377 tomoyo_del_path_group(p->element); 412 tomoyo_del_path_group(p->element);
378 break; 413 break;
414 case TOMOYO_ID_NUMBER_GROUP_MEMBER:
415 tomoyo_del_number_group_member(p->element);
416 break;
417 case TOMOYO_ID_NUMBER_GROUP:
418 tomoyo_del_number_group(p->element);
419 break;
379 default: 420 default:
380 printk(KERN_WARNING "Unknown type\n"); 421 printk(KERN_WARNING "Unknown type\n");
381 break; 422 break;
diff --git a/security/tomoyo/number_group.c b/security/tomoyo/number_group.c
new file mode 100644
index 000000000000..c49792e09e81
--- /dev/null
+++ b/security/tomoyo/number_group.c
@@ -0,0 +1,176 @@
1/*
2 * security/tomoyo/number_group.c
3 *
4 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 */
6
7#include <linux/slab.h>
8#include "common.h"
9
10/* The list for "struct tomoyo_number_group". */
11LIST_HEAD(tomoyo_number_group_list);
12
13/**
14 * tomoyo_get_number_group - Allocate memory for "struct tomoyo_number_group".
15 *
16 * @group_name: The name of number group.
17 *
18 * Returns pointer to "struct tomoyo_number_group" on success,
19 * NULL otherwise.
20 */
21struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name)
22{
23 struct tomoyo_number_group *entry = NULL;
24 struct tomoyo_number_group *group = NULL;
25 const struct tomoyo_path_info *saved_group_name;
26 int error = -ENOMEM;
27 if (!tomoyo_is_correct_path(group_name, 0, 0, 0) ||
28 !group_name[0])
29 return NULL;
30 saved_group_name = tomoyo_get_name(group_name);
31 if (!saved_group_name)
32 return NULL;
33 entry = kzalloc(sizeof(*entry), GFP_NOFS);
34 if (mutex_lock_interruptible(&tomoyo_policy_lock))
35 goto out;
36 list_for_each_entry_rcu(group, &tomoyo_number_group_list, list) {
37 if (saved_group_name != group->group_name)
38 continue;
39 atomic_inc(&group->users);
40 error = 0;
41 break;
42 }
43 if (error && tomoyo_memory_ok(entry)) {
44 INIT_LIST_HEAD(&entry->member_list);
45 entry->group_name = saved_group_name;
46 saved_group_name = NULL;
47 atomic_set(&entry->users, 1);
48 list_add_tail_rcu(&entry->list, &tomoyo_number_group_list);
49 group = entry;
50 entry = NULL;
51 error = 0;
52 }
53 mutex_unlock(&tomoyo_policy_lock);
54 out:
55 tomoyo_put_name(saved_group_name);
56 kfree(entry);
57 return !error ? group : NULL;
58}
59
60/**
61 * tomoyo_write_number_group_policy - Write "struct tomoyo_number_group" list.
62 *
63 * @data: String to parse.
64 * @is_delete: True if it is a delete request.
65 *
66 * Returns 0 on success, nagative value otherwise.
67 */
68int tomoyo_write_number_group_policy(char *data, const bool is_delete)
69{
70 struct tomoyo_number_group *group;
71 struct tomoyo_number_group_member e = { };
72 struct tomoyo_number_group_member *member;
73 int error = is_delete ? -ENOENT : -ENOMEM;
74 char *w[2];
75 if (!tomoyo_tokenize(data, w, sizeof(w)))
76 return -EINVAL;
77 if (!tomoyo_parse_number_union(w[1], &e.number))
78 return -EINVAL;
79 if (e.number.is_group || e.number.values[0] > e.number.values[1]) {
80 tomoyo_put_number_union(&e.number);
81 return -EINVAL;
82 }
83 group = tomoyo_get_number_group(w[0]);
84 if (!group)
85 return -ENOMEM;
86 if (mutex_lock_interruptible(&tomoyo_policy_lock))
87 goto out;
88 list_for_each_entry_rcu(member, &group->member_list, list) {
89 if (memcmp(&member->number, &e.number, sizeof(e.number)))
90 continue;
91 member->is_deleted = is_delete;
92 error = 0;
93 break;
94 }
95 if (!is_delete && error) {
96 struct tomoyo_number_group_member *entry =
97 tomoyo_commit_ok(&e, sizeof(e));
98 if (entry) {
99 list_add_tail_rcu(&entry->list, &group->member_list);
100 error = 0;
101 }
102 }
103 mutex_unlock(&tomoyo_policy_lock);
104 out:
105 tomoyo_put_number_group(group);
106 return error;
107}
108
109/**
110 * tomoyo_read_number_group_policy - Read "struct tomoyo_number_group" list.
111 *
112 * @head: Pointer to "struct tomoyo_io_buffer".
113 *
114 * Returns true on success, false otherwise.
115 *
116 * Caller holds tomoyo_read_lock().
117 */
118bool tomoyo_read_number_group_policy(struct tomoyo_io_buffer *head)
119{
120 struct list_head *gpos;
121 struct list_head *mpos;
122 list_for_each_cookie(gpos, head->read_var1, &tomoyo_number_group_list) {
123 struct tomoyo_number_group *group;
124 const char *name;
125 group = list_entry(gpos, struct tomoyo_number_group, list);
126 name = group->group_name->name;
127 list_for_each_cookie(mpos, head->read_var2,
128 &group->member_list) {
129 int pos;
130 const struct tomoyo_number_group_member *member
131 = list_entry(mpos,
132 struct tomoyo_number_group_member,
133 list);
134 if (member->is_deleted)
135 continue;
136 pos = head->read_avail;
137 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_NUMBER_GROUP
138 "%s", name) ||
139 !tomoyo_print_number_union(head, &member->number) ||
140 !tomoyo_io_printf(head, "\n")) {
141 head->read_avail = pos;
142 return false;
143 }
144 }
145 }
146 return true;
147}
148
149/**
150 * tomoyo_number_matches_group - Check whether the given number matches members of the given number group.
151 *
152 * @min: Min number.
153 * @max: Max number.
154 * @group: Pointer to "struct tomoyo_number_group".
155 *
156 * Returns true if @min and @max partially overlaps @group, false otherwise.
157 *
158 * Caller holds tomoyo_read_lock().
159 */
160bool tomoyo_number_matches_group(const unsigned long min,
161 const unsigned long max,
162 const struct tomoyo_number_group *group)
163{
164 struct tomoyo_number_group_member *member;
165 bool matched = false;
166 list_for_each_entry_rcu(member, &group->member_list, list) {
167 if (member->is_deleted)
168 continue;
169 if (min > member->number.values[1] ||
170 max < member->number.values[0])
171 continue;
172 matched = true;
173 break;
174 }
175 return matched;
176}