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