blob: 414e18bd93c732ef7cbcea7470cdea71c506abe0 [file] [log] [blame]
Tetsuo Handa847b1732010-02-11 09:43:54 +09001/*
2 * security/tomoyo/gc.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 *
8 */
9
10#include "common.h"
11#include <linux/kthread.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090012#include <linux/slab.h>
Tetsuo Handa847b1732010-02-11 09:43:54 +090013
Tetsuo Handa847b1732010-02-11 09:43:54 +090014struct tomoyo_gc_entry {
15 struct list_head list;
16 int type;
Tetsuo Handae79acf02010-06-16 16:31:50 +090017 struct list_head *element;
Tetsuo Handa847b1732010-02-11 09:43:54 +090018};
19static LIST_HEAD(tomoyo_gc_queue);
20static DEFINE_MUTEX(tomoyo_gc_mutex);
21
22/* Caller holds tomoyo_policy_lock mutex. */
Tetsuo Handae79acf02010-06-16 16:31:50 +090023static bool tomoyo_add_to_gc(const int type, struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +090024{
25 struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
26 if (!entry)
27 return false;
28 entry->type = type;
29 entry->element = element;
30 list_add(&entry->list, &tomoyo_gc_queue);
Tetsuo Handae79acf02010-06-16 16:31:50 +090031 list_del_rcu(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +090032 return true;
33}
34
Tetsuo Handae79acf02010-06-16 16:31:50 +090035static void tomoyo_del_allow_read(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +090036{
Tetsuo Handae79acf02010-06-16 16:31:50 +090037 struct tomoyo_globally_readable_file_entry *ptr =
38 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa847b1732010-02-11 09:43:54 +090039 tomoyo_put_name(ptr->filename);
40}
41
Tetsuo Handae79acf02010-06-16 16:31:50 +090042static void tomoyo_del_file_pattern(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +090043{
Tetsuo Handae79acf02010-06-16 16:31:50 +090044 struct tomoyo_pattern_entry *ptr =
45 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa847b1732010-02-11 09:43:54 +090046 tomoyo_put_name(ptr->pattern);
47}
48
Tetsuo Handae79acf02010-06-16 16:31:50 +090049static void tomoyo_del_no_rewrite(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +090050{
Tetsuo Handae79acf02010-06-16 16:31:50 +090051 struct tomoyo_no_rewrite_entry *ptr =
52 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa847b1732010-02-11 09:43:54 +090053 tomoyo_put_name(ptr->pattern);
54}
55
Tetsuo Handae79acf02010-06-16 16:31:50 +090056static void tomoyo_del_domain_initializer(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +090057{
Tetsuo Handae79acf02010-06-16 16:31:50 +090058 struct tomoyo_domain_initializer_entry *ptr =
59 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa847b1732010-02-11 09:43:54 +090060 tomoyo_put_name(ptr->domainname);
61 tomoyo_put_name(ptr->program);
62}
63
Tetsuo Handae79acf02010-06-16 16:31:50 +090064static void tomoyo_del_domain_keeper(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +090065{
Tetsuo Handae79acf02010-06-16 16:31:50 +090066 struct tomoyo_domain_keeper_entry *ptr =
67 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa847b1732010-02-11 09:43:54 +090068 tomoyo_put_name(ptr->domainname);
69 tomoyo_put_name(ptr->program);
70}
71
Tetsuo Handae79acf02010-06-16 16:31:50 +090072static void tomoyo_del_aggregator(struct list_head *element)
Tetsuo Handa10843072010-06-03 20:38:03 +090073{
Tetsuo Handae79acf02010-06-16 16:31:50 +090074 struct tomoyo_aggregator_entry *ptr =
75 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa10843072010-06-03 20:38:03 +090076 tomoyo_put_name(ptr->original_name);
77 tomoyo_put_name(ptr->aggregated_name);
78}
79
Tetsuo Handae79acf02010-06-16 16:31:50 +090080static void tomoyo_del_alias(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +090081{
Tetsuo Handae79acf02010-06-16 16:31:50 +090082 struct tomoyo_alias_entry *ptr =
83 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa847b1732010-02-11 09:43:54 +090084 tomoyo_put_name(ptr->original_name);
85 tomoyo_put_name(ptr->aliased_name);
86}
87
Tetsuo Handae79acf02010-06-16 16:31:50 +090088static void tomoyo_del_manager(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +090089{
Tetsuo Handae79acf02010-06-16 16:31:50 +090090 struct tomoyo_policy_manager_entry *ptr =
91 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa847b1732010-02-11 09:43:54 +090092 tomoyo_put_name(ptr->manager);
93}
94
Tetsuo Handae79acf02010-06-16 16:31:50 +090095static void tomoyo_del_acl(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +090096{
Tetsuo Handae79acf02010-06-16 16:31:50 +090097 struct tomoyo_acl_info *acl =
98 container_of(element, typeof(*acl), list);
Tetsuo Handa847b1732010-02-11 09:43:54 +090099 switch (acl->type) {
Tetsuo Handa7ef61232010-02-16 08:03:30 +0900100 case TOMOYO_TYPE_PATH_ACL:
Tetsuo Handa847b1732010-02-11 09:43:54 +0900101 {
Tetsuo Handa7ef61232010-02-16 08:03:30 +0900102 struct tomoyo_path_acl *entry
Tetsuo Handa847b1732010-02-11 09:43:54 +0900103 = container_of(acl, typeof(*entry), head);
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900104 tomoyo_put_name_union(&entry->name);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900105 }
106 break;
Tetsuo Handa7ef61232010-02-16 08:03:30 +0900107 case TOMOYO_TYPE_PATH2_ACL:
Tetsuo Handa847b1732010-02-11 09:43:54 +0900108 {
Tetsuo Handa7ef61232010-02-16 08:03:30 +0900109 struct tomoyo_path2_acl *entry
Tetsuo Handa847b1732010-02-11 09:43:54 +0900110 = container_of(acl, typeof(*entry), head);
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900111 tomoyo_put_name_union(&entry->name1);
112 tomoyo_put_name_union(&entry->name2);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900113 }
114 break;
Tetsuo Handaa1f9bb62010-05-17 10:09:15 +0900115 case TOMOYO_TYPE_PATH_NUMBER_ACL:
116 {
117 struct tomoyo_path_number_acl *entry
118 = container_of(acl, typeof(*entry), head);
119 tomoyo_put_name_union(&entry->name);
120 tomoyo_put_number_union(&entry->number);
121 }
122 break;
Tetsuo Handa75093152010-06-16 16:23:55 +0900123 case TOMOYO_TYPE_MKDEV_ACL:
Tetsuo Handaa1f9bb62010-05-17 10:09:15 +0900124 {
Tetsuo Handa75093152010-06-16 16:23:55 +0900125 struct tomoyo_mkdev_acl *entry
Tetsuo Handaa1f9bb62010-05-17 10:09:15 +0900126 = container_of(acl, typeof(*entry), head);
127 tomoyo_put_name_union(&entry->name);
128 tomoyo_put_number_union(&entry->mode);
129 tomoyo_put_number_union(&entry->major);
130 tomoyo_put_number_union(&entry->minor);
131 }
132 break;
Tetsuo Handa2106ccd2010-05-17 10:10:31 +0900133 case TOMOYO_TYPE_MOUNT_ACL:
134 {
135 struct tomoyo_mount_acl *entry
136 = container_of(acl, typeof(*entry), head);
137 tomoyo_put_name_union(&entry->dev_name);
138 tomoyo_put_name_union(&entry->dir_name);
139 tomoyo_put_name_union(&entry->fs_type);
140 tomoyo_put_number_union(&entry->flags);
141 }
142 break;
Tetsuo Handa847b1732010-02-11 09:43:54 +0900143 }
144}
145
Tetsuo Handae79acf02010-06-16 16:31:50 +0900146static bool tomoyo_del_domain(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +0900147{
Tetsuo Handae79acf02010-06-16 16:31:50 +0900148 struct tomoyo_domain_info *domain =
149 container_of(element, typeof(*domain), list);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900150 struct tomoyo_acl_info *acl;
151 struct tomoyo_acl_info *tmp;
152 /*
153 * Since we don't protect whole execve() operation using SRCU,
154 * we need to recheck domain->users at this point.
155 *
156 * (1) Reader starts SRCU section upon execve().
157 * (2) Reader traverses tomoyo_domain_list and finds this domain.
158 * (3) Writer marks this domain as deleted.
159 * (4) Garbage collector removes this domain from tomoyo_domain_list
160 * because this domain is marked as deleted and used by nobody.
161 * (5) Reader saves reference to this domain into
162 * "struct linux_binprm"->cred->security .
163 * (6) Reader finishes SRCU section, although execve() operation has
164 * not finished yet.
165 * (7) Garbage collector waits for SRCU synchronization.
166 * (8) Garbage collector kfree() this domain because this domain is
167 * used by nobody.
168 * (9) Reader finishes execve() operation and restores this domain from
169 * "struct linux_binprm"->cred->security.
170 *
171 * By updating domain->users at (5), we can solve this race problem
172 * by rechecking domain->users at (8).
173 */
174 if (atomic_read(&domain->users))
175 return false;
176 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
Tetsuo Handae79acf02010-06-16 16:31:50 +0900177 tomoyo_del_acl(&acl->list);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900178 tomoyo_memory_free(acl);
179 }
180 tomoyo_put_name(domain->domainname);
181 return true;
182}
183
184
Tetsuo Handae79acf02010-06-16 16:31:50 +0900185static void tomoyo_del_name(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +0900186{
Tetsuo Handae79acf02010-06-16 16:31:50 +0900187 const struct tomoyo_name_entry *ptr =
188 container_of(element, typeof(*ptr), list);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900189}
190
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900191static void tomoyo_del_path_group(struct list_head *element)
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900192{
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900193 struct tomoyo_path_group *member =
Tetsuo Handae79acf02010-06-16 16:31:50 +0900194 container_of(element, typeof(*member), head.list);
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900195 tomoyo_put_name(member->member_name);
196}
197
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900198static void tomoyo_del_group(struct list_head *element)
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900199{
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900200 struct tomoyo_group *group =
Tetsuo Handae79acf02010-06-16 16:31:50 +0900201 container_of(element, typeof(*group), list);
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900202 tomoyo_put_name(group->group_name);
203}
204
Tetsuo Handae79acf02010-06-16 16:31:50 +0900205static void tomoyo_del_number_group(struct list_head *element)
Tetsuo Handa4c3e9e22010-05-17 10:06:58 +0900206{
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900207 struct tomoyo_number_group *member =
208 container_of(element, typeof(*member), head.list);
Tetsuo Handa4c3e9e22010-05-17 10:06:58 +0900209}
210
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900211static bool tomoyo_collect_member(struct list_head *member_list, int id)
212{
213 struct tomoyo_acl_head *member;
214 list_for_each_entry(member, member_list, list) {
215 if (!member->is_deleted)
216 continue;
217 if (!tomoyo_add_to_gc(id, &member->list))
218 return false;
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900219 }
220 return true;
221}
222
223static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain)
224{
225 struct tomoyo_acl_info *acl;
226 list_for_each_entry(acl, &domain->acl_info_list, list) {
227 if (!acl->is_deleted)
228 continue;
229 if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list))
230 return false;
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900231 }
232 return true;
233}
234
Tetsuo Handa847b1732010-02-11 09:43:54 +0900235static void tomoyo_collect_entry(void)
236{
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900237 int i;
Tetsuo Handa29282382010-05-06 00:18:15 +0900238 if (mutex_lock_interruptible(&tomoyo_policy_lock))
239 return;
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900240 for (i = 0; i < TOMOYO_MAX_POLICY; i++) {
Tetsuo Handaa230f9e2010-06-17 16:53:24 +0900241 if (!tomoyo_collect_member(&tomoyo_policy_list[i], i))
242 goto unlock;
Tetsuo Handa847b1732010-02-11 09:43:54 +0900243 }
244 {
245 struct tomoyo_domain_info *domain;
246 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900247 if (!tomoyo_collect_acl(domain))
248 goto unlock;
Tetsuo Handa847b1732010-02-11 09:43:54 +0900249 if (!domain->is_deleted || atomic_read(&domain->users))
250 continue;
251 /*
252 * Nobody is referring this domain. But somebody may
253 * refer this domain after successful execve().
254 * We recheck domain->users after SRCU synchronization.
255 */
Tetsuo Handae79acf02010-06-16 16:31:50 +0900256 if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list))
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900257 goto unlock;
Tetsuo Handa847b1732010-02-11 09:43:54 +0900258 }
259 }
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900260 for (i = 0; i < TOMOYO_MAX_HASH; i++) {
261 struct tomoyo_name_entry *ptr;
262 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], list) {
263 if (atomic_read(&ptr->users))
264 continue;
Tetsuo Handae79acf02010-06-16 16:31:50 +0900265 if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list))
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900266 goto unlock;
Tetsuo Handa847b1732010-02-11 09:43:54 +0900267 }
268 }
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900269 {
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900270 struct tomoyo_group *group;
Tetsuo Handaa230f9e2010-06-17 16:53:24 +0900271 list_for_each_entry_rcu(group,
272 &tomoyo_group_list[TOMOYO_PATH_GROUP],
273 list) {
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900274 tomoyo_collect_member(&group->member_list,
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900275 TOMOYO_ID_PATH_GROUP);
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900276 if (!list_empty(&group->member_list) ||
277 atomic_read(&group->users))
278 continue;
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900279 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP,
Tetsuo Handae79acf02010-06-16 16:31:50 +0900280 &group->list))
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900281 goto unlock;
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900282 }
283 }
Tetsuo Handa4c3e9e22010-05-17 10:06:58 +0900284 {
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900285 struct tomoyo_group *group;
Tetsuo Handaa230f9e2010-06-17 16:53:24 +0900286 list_for_each_entry_rcu(group,
287 &tomoyo_group_list[TOMOYO_NUMBER_GROUP],
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900288 list) {
289 tomoyo_collect_member(&group->member_list,
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900290 TOMOYO_ID_NUMBER_GROUP);
Tetsuo Handa4c3e9e22010-05-17 10:06:58 +0900291 if (!list_empty(&group->member_list) ||
292 atomic_read(&group->users))
293 continue;
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900294 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP,
Tetsuo Handae79acf02010-06-16 16:31:50 +0900295 &group->list))
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900296 goto unlock;
Tetsuo Handa4c3e9e22010-05-17 10:06:58 +0900297 }
298 }
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900299 unlock:
Tetsuo Handa29282382010-05-06 00:18:15 +0900300 mutex_unlock(&tomoyo_policy_lock);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900301}
302
303static void tomoyo_kfree_entry(void)
304{
305 struct tomoyo_gc_entry *p;
306 struct tomoyo_gc_entry *tmp;
307
308 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
Tetsuo Handae79acf02010-06-16 16:31:50 +0900309 struct list_head *element = p->element;
Tetsuo Handa847b1732010-02-11 09:43:54 +0900310 switch (p->type) {
311 case TOMOYO_ID_DOMAIN_INITIALIZER:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900312 tomoyo_del_domain_initializer(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900313 break;
314 case TOMOYO_ID_DOMAIN_KEEPER:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900315 tomoyo_del_domain_keeper(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900316 break;
Tetsuo Handa10843072010-06-03 20:38:03 +0900317 case TOMOYO_ID_AGGREGATOR:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900318 tomoyo_del_aggregator(element);
Tetsuo Handa10843072010-06-03 20:38:03 +0900319 break;
Tetsuo Handa847b1732010-02-11 09:43:54 +0900320 case TOMOYO_ID_ALIAS:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900321 tomoyo_del_alias(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900322 break;
323 case TOMOYO_ID_GLOBALLY_READABLE:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900324 tomoyo_del_allow_read(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900325 break;
326 case TOMOYO_ID_PATTERN:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900327 tomoyo_del_file_pattern(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900328 break;
329 case TOMOYO_ID_NO_REWRITE:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900330 tomoyo_del_no_rewrite(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900331 break;
332 case TOMOYO_ID_MANAGER:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900333 tomoyo_del_manager(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900334 break;
335 case TOMOYO_ID_NAME:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900336 tomoyo_del_name(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900337 break;
338 case TOMOYO_ID_ACL:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900339 tomoyo_del_acl(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900340 break;
341 case TOMOYO_ID_DOMAIN:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900342 if (!tomoyo_del_domain(element))
Tetsuo Handa847b1732010-02-11 09:43:54 +0900343 continue;
344 break;
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900345 case TOMOYO_ID_PATH_GROUP:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900346 tomoyo_del_path_group(element);
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900347 break;
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900348 case TOMOYO_ID_GROUP:
349 tomoyo_del_group(element);
Tetsuo Handa4c3e9e22010-05-17 10:06:58 +0900350 break;
351 case TOMOYO_ID_NUMBER_GROUP:
Tetsuo Handae79acf02010-06-16 16:31:50 +0900352 tomoyo_del_number_group(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900353 break;
354 }
Tetsuo Handae79acf02010-06-16 16:31:50 +0900355 tomoyo_memory_free(element);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900356 list_del(&p->list);
357 kfree(p);
358 }
359}
360
361static int tomoyo_gc_thread(void *unused)
362{
363 daemonize("GC for TOMOYO");
364 if (mutex_trylock(&tomoyo_gc_mutex)) {
365 int i;
366 for (i = 0; i < 10; i++) {
367 tomoyo_collect_entry();
368 if (list_empty(&tomoyo_gc_queue))
369 break;
370 synchronize_srcu(&tomoyo_ss);
371 tomoyo_kfree_entry();
372 }
373 mutex_unlock(&tomoyo_gc_mutex);
374 }
375 do_exit(0);
376}
377
378void tomoyo_run_gc(void)
379{
380 struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL,
381 "GC for TOMOYO");
382 if (!IS_ERR(task))
383 wake_up_process(task);
384}