17c2ea22eSTetsuo Handa /* 27c2ea22eSTetsuo Handa * security/tomoyo/group.c 37c2ea22eSTetsuo Handa * 47c2ea22eSTetsuo Handa * Copyright (C) 2005-2010 NTT DATA CORPORATION 57c2ea22eSTetsuo Handa */ 67c2ea22eSTetsuo Handa 77c2ea22eSTetsuo Handa #include <linux/slab.h> 87c2ea22eSTetsuo Handa #include "common.h" 97c2ea22eSTetsuo Handa 107c2ea22eSTetsuo Handa static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a, 117c2ea22eSTetsuo Handa const struct tomoyo_acl_head *b) 127c2ea22eSTetsuo Handa { 137c2ea22eSTetsuo Handa return container_of(a, struct tomoyo_path_group, head)->member_name == 147c2ea22eSTetsuo Handa container_of(b, struct tomoyo_path_group, head)->member_name; 157c2ea22eSTetsuo Handa } 167c2ea22eSTetsuo Handa 177c2ea22eSTetsuo Handa static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a, 187c2ea22eSTetsuo Handa const struct tomoyo_acl_head *b) 197c2ea22eSTetsuo Handa { 207c2ea22eSTetsuo Handa return !memcmp(&container_of(a, struct tomoyo_number_group, head) 217c2ea22eSTetsuo Handa ->number, 227c2ea22eSTetsuo Handa &container_of(b, struct tomoyo_number_group, head) 237c2ea22eSTetsuo Handa ->number, 247c2ea22eSTetsuo Handa sizeof(container_of(a, struct tomoyo_number_group, head) 257c2ea22eSTetsuo Handa ->number)); 267c2ea22eSTetsuo Handa } 277c2ea22eSTetsuo Handa 287c2ea22eSTetsuo Handa /** 297c2ea22eSTetsuo Handa * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list. 307c2ea22eSTetsuo Handa * 317c2ea22eSTetsuo Handa * @data: String to parse. 327c2ea22eSTetsuo Handa * @is_delete: True if it is a delete request. 337c2ea22eSTetsuo Handa * @type: Type of this group. 347c2ea22eSTetsuo Handa * 357c2ea22eSTetsuo Handa * Returns 0 on success, negative value otherwise. 367c2ea22eSTetsuo Handa */ 377c2ea22eSTetsuo Handa int tomoyo_write_group(char *data, const bool is_delete, const u8 type) 387c2ea22eSTetsuo Handa { 397c2ea22eSTetsuo Handa struct tomoyo_group *group; 407c2ea22eSTetsuo Handa struct list_head *member; 417c2ea22eSTetsuo Handa char *w[2]; 427c2ea22eSTetsuo Handa int error = -EINVAL; 437c2ea22eSTetsuo Handa if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) 447c2ea22eSTetsuo Handa return -EINVAL; 457c2ea22eSTetsuo Handa group = tomoyo_get_group(w[0], type); 467c2ea22eSTetsuo Handa if (!group) 477c2ea22eSTetsuo Handa return -ENOMEM; 487c2ea22eSTetsuo Handa member = &group->member_list; 497c2ea22eSTetsuo Handa if (type == TOMOYO_PATH_GROUP) { 507c2ea22eSTetsuo Handa struct tomoyo_path_group e = { }; 517c2ea22eSTetsuo Handa e.member_name = tomoyo_get_name(w[1]); 527c2ea22eSTetsuo Handa if (!e.member_name) { 537c2ea22eSTetsuo Handa error = -ENOMEM; 547c2ea22eSTetsuo Handa goto out; 557c2ea22eSTetsuo Handa } 567c2ea22eSTetsuo Handa error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 577c2ea22eSTetsuo Handa member, tomoyo_same_path_group); 587c2ea22eSTetsuo Handa tomoyo_put_name(e.member_name); 597c2ea22eSTetsuo Handa } else if (type == TOMOYO_NUMBER_GROUP) { 607c2ea22eSTetsuo Handa struct tomoyo_number_group e = { }; 617c2ea22eSTetsuo Handa if (w[1][0] == '@' 627c2ea22eSTetsuo Handa || !tomoyo_parse_number_union(w[1], &e.number) 637c2ea22eSTetsuo Handa || e.number.values[0] > e.number.values[1]) 647c2ea22eSTetsuo Handa goto out; 657c2ea22eSTetsuo Handa error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 667c2ea22eSTetsuo Handa member, tomoyo_same_number_group); 677c2ea22eSTetsuo Handa /* 687c2ea22eSTetsuo Handa * tomoyo_put_number_union() is not needed because 697c2ea22eSTetsuo Handa * w[1][0] != '@'. 707c2ea22eSTetsuo Handa */ 717c2ea22eSTetsuo Handa } 727c2ea22eSTetsuo Handa out: 737c2ea22eSTetsuo Handa tomoyo_put_group(group); 747c2ea22eSTetsuo Handa return error; 757c2ea22eSTetsuo Handa } 767c2ea22eSTetsuo Handa 777c2ea22eSTetsuo Handa /** 787c2ea22eSTetsuo Handa * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. 797c2ea22eSTetsuo Handa * 807c2ea22eSTetsuo Handa * @pathname: The name of pathname. 817c2ea22eSTetsuo Handa * @group: Pointer to "struct tomoyo_path_group". 827c2ea22eSTetsuo Handa * 83*484ca79cSTetsuo Handa * Returns matched member's pathname if @pathname matches pathnames in @group, 84*484ca79cSTetsuo Handa * NULL otherwise. 857c2ea22eSTetsuo Handa * 867c2ea22eSTetsuo Handa * Caller holds tomoyo_read_lock(). 877c2ea22eSTetsuo Handa */ 88*484ca79cSTetsuo Handa const struct tomoyo_path_info * 89*484ca79cSTetsuo Handa tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, 907c2ea22eSTetsuo Handa const struct tomoyo_group *group) 917c2ea22eSTetsuo Handa { 927c2ea22eSTetsuo Handa struct tomoyo_path_group *member; 937c2ea22eSTetsuo Handa list_for_each_entry_rcu(member, &group->member_list, head.list) { 947c2ea22eSTetsuo Handa if (member->head.is_deleted) 957c2ea22eSTetsuo Handa continue; 967c2ea22eSTetsuo Handa if (!tomoyo_path_matches_pattern(pathname, member->member_name)) 977c2ea22eSTetsuo Handa continue; 98*484ca79cSTetsuo Handa return member->member_name; 997c2ea22eSTetsuo Handa } 100*484ca79cSTetsuo Handa return NULL; 1017c2ea22eSTetsuo Handa } 1027c2ea22eSTetsuo Handa 1037c2ea22eSTetsuo Handa /** 1047c2ea22eSTetsuo Handa * tomoyo_number_matches_group - Check whether the given number matches members of the given number group. 1057c2ea22eSTetsuo Handa * 1067c2ea22eSTetsuo Handa * @min: Min number. 1077c2ea22eSTetsuo Handa * @max: Max number. 1087c2ea22eSTetsuo Handa * @group: Pointer to "struct tomoyo_number_group". 1097c2ea22eSTetsuo Handa * 1107c2ea22eSTetsuo Handa * Returns true if @min and @max partially overlaps @group, false otherwise. 1117c2ea22eSTetsuo Handa * 1127c2ea22eSTetsuo Handa * Caller holds tomoyo_read_lock(). 1137c2ea22eSTetsuo Handa */ 1147c2ea22eSTetsuo Handa bool tomoyo_number_matches_group(const unsigned long min, 1157c2ea22eSTetsuo Handa const unsigned long max, 1167c2ea22eSTetsuo Handa const struct tomoyo_group *group) 1177c2ea22eSTetsuo Handa { 1187c2ea22eSTetsuo Handa struct tomoyo_number_group *member; 1197c2ea22eSTetsuo Handa bool matched = false; 1207c2ea22eSTetsuo Handa list_for_each_entry_rcu(member, &group->member_list, head.list) { 1217c2ea22eSTetsuo Handa if (member->head.is_deleted) 1227c2ea22eSTetsuo Handa continue; 1237c2ea22eSTetsuo Handa if (min > member->number.values[1] || 1247c2ea22eSTetsuo Handa max < member->number.values[0]) 1257c2ea22eSTetsuo Handa continue; 1267c2ea22eSTetsuo Handa matched = true; 1277c2ea22eSTetsuo Handa break; 1287c2ea22eSTetsuo Handa } 1297c2ea22eSTetsuo Handa return matched; 1307c2ea22eSTetsuo Handa } 131