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