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