xref: /linux/security/tomoyo/group.c (revision 484ca79c653121d3c79fffb86e1deea724f2e20b)
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