gc.c revision a230f9e7121cbcbfe23bd5a630abf6b53cece555
1/* 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> 12#include <linux/slab.h> 13 14struct tomoyo_gc_entry { 15 struct list_head list; 16 int type; 17 struct list_head *element; 18}; 19static LIST_HEAD(tomoyo_gc_queue); 20static DEFINE_MUTEX(tomoyo_gc_mutex); 21 22/* Caller holds tomoyo_policy_lock mutex. */ 23static bool tomoyo_add_to_gc(const int type, struct list_head *element) 24{ 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); 31 list_del_rcu(element); 32 return true; 33} 34 35static void tomoyo_del_allow_read(struct list_head *element) 36{ 37 struct tomoyo_globally_readable_file_entry *ptr = 38 container_of(element, typeof(*ptr), head.list); 39 tomoyo_put_name(ptr->filename); 40} 41 42static void tomoyo_del_file_pattern(struct list_head *element) 43{ 44 struct tomoyo_pattern_entry *ptr = 45 container_of(element, typeof(*ptr), head.list); 46 tomoyo_put_name(ptr->pattern); 47} 48 49static void tomoyo_del_no_rewrite(struct list_head *element) 50{ 51 struct tomoyo_no_rewrite_entry *ptr = 52 container_of(element, typeof(*ptr), head.list); 53 tomoyo_put_name(ptr->pattern); 54} 55 56static void tomoyo_del_domain_initializer(struct list_head *element) 57{ 58 struct tomoyo_domain_initializer_entry *ptr = 59 container_of(element, typeof(*ptr), head.list); 60 tomoyo_put_name(ptr->domainname); 61 tomoyo_put_name(ptr->program); 62} 63 64static void tomoyo_del_domain_keeper(struct list_head *element) 65{ 66 struct tomoyo_domain_keeper_entry *ptr = 67 container_of(element, typeof(*ptr), head.list); 68 tomoyo_put_name(ptr->domainname); 69 tomoyo_put_name(ptr->program); 70} 71 72static void tomoyo_del_aggregator(struct list_head *element) 73{ 74 struct tomoyo_aggregator_entry *ptr = 75 container_of(element, typeof(*ptr), head.list); 76 tomoyo_put_name(ptr->original_name); 77 tomoyo_put_name(ptr->aggregated_name); 78} 79 80static void tomoyo_del_alias(struct list_head *element) 81{ 82 struct tomoyo_alias_entry *ptr = 83 container_of(element, typeof(*ptr), head.list); 84 tomoyo_put_name(ptr->original_name); 85 tomoyo_put_name(ptr->aliased_name); 86} 87 88static void tomoyo_del_manager(struct list_head *element) 89{ 90 struct tomoyo_policy_manager_entry *ptr = 91 container_of(element, typeof(*ptr), head.list); 92 tomoyo_put_name(ptr->manager); 93} 94 95static void tomoyo_del_acl(struct list_head *element) 96{ 97 struct tomoyo_acl_info *acl = 98 container_of(element, typeof(*acl), list); 99 switch (acl->type) { 100 case TOMOYO_TYPE_PATH_ACL: 101 { 102 struct tomoyo_path_acl *entry 103 = container_of(acl, typeof(*entry), head); 104 tomoyo_put_name_union(&entry->name); 105 } 106 break; 107 case TOMOYO_TYPE_PATH2_ACL: 108 { 109 struct tomoyo_path2_acl *entry 110 = container_of(acl, typeof(*entry), head); 111 tomoyo_put_name_union(&entry->name1); 112 tomoyo_put_name_union(&entry->name2); 113 } 114 break; 115 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; 123 case TOMOYO_TYPE_MKDEV_ACL: 124 { 125 struct tomoyo_mkdev_acl *entry 126 = 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; 133 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; 143 } 144} 145 146static bool tomoyo_del_domain(struct list_head *element) 147{ 148 struct tomoyo_domain_info *domain = 149 container_of(element, typeof(*domain), list); 150 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) { 177 tomoyo_del_acl(&acl->list); 178 tomoyo_memory_free(acl); 179 } 180 tomoyo_put_name(domain->domainname); 181 return true; 182} 183 184 185static void tomoyo_del_name(struct list_head *element) 186{ 187 const struct tomoyo_name_entry *ptr = 188 container_of(element, typeof(*ptr), list); 189} 190 191static void tomoyo_del_path_group(struct list_head *element) 192{ 193 struct tomoyo_path_group *member = 194 container_of(element, typeof(*member), head.list); 195 tomoyo_put_name(member->member_name); 196} 197 198static void tomoyo_del_group(struct list_head *element) 199{ 200 struct tomoyo_group *group = 201 container_of(element, typeof(*group), list); 202 tomoyo_put_name(group->group_name); 203} 204 205static void tomoyo_del_number_group(struct list_head *element) 206{ 207 struct tomoyo_number_group *member = 208 container_of(element, typeof(*member), head.list); 209} 210 211static 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; 219 } 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; 231 } 232 return true; 233} 234 235static void tomoyo_collect_entry(void) 236{ 237 int i; 238 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 239 return; 240 for (i = 0; i < TOMOYO_MAX_POLICY; i++) { 241 if (!tomoyo_collect_member(&tomoyo_policy_list[i], i)) 242 goto unlock; 243 } 244 { 245 struct tomoyo_domain_info *domain; 246 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 247 if (!tomoyo_collect_acl(domain)) 248 goto unlock; 249 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 */ 256 if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list)) 257 goto unlock; 258 } 259 } 260 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; 265 if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list)) 266 goto unlock; 267 } 268 } 269 { 270 struct tomoyo_group *group; 271 list_for_each_entry_rcu(group, 272 &tomoyo_group_list[TOMOYO_PATH_GROUP], 273 list) { 274 tomoyo_collect_member(&group->member_list, 275 TOMOYO_ID_PATH_GROUP); 276 if (!list_empty(&group->member_list) || 277 atomic_read(&group->users)) 278 continue; 279 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, 280 &group->list)) 281 goto unlock; 282 } 283 } 284 { 285 struct tomoyo_group *group; 286 list_for_each_entry_rcu(group, 287 &tomoyo_group_list[TOMOYO_NUMBER_GROUP], 288 list) { 289 tomoyo_collect_member(&group->member_list, 290 TOMOYO_ID_NUMBER_GROUP); 291 if (!list_empty(&group->member_list) || 292 atomic_read(&group->users)) 293 continue; 294 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, 295 &group->list)) 296 goto unlock; 297 } 298 } 299 unlock: 300 mutex_unlock(&tomoyo_policy_lock); 301} 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) { 309 struct list_head *element = p->element; 310 switch (p->type) { 311 case TOMOYO_ID_DOMAIN_INITIALIZER: 312 tomoyo_del_domain_initializer(element); 313 break; 314 case TOMOYO_ID_DOMAIN_KEEPER: 315 tomoyo_del_domain_keeper(element); 316 break; 317 case TOMOYO_ID_AGGREGATOR: 318 tomoyo_del_aggregator(element); 319 break; 320 case TOMOYO_ID_ALIAS: 321 tomoyo_del_alias(element); 322 break; 323 case TOMOYO_ID_GLOBALLY_READABLE: 324 tomoyo_del_allow_read(element); 325 break; 326 case TOMOYO_ID_PATTERN: 327 tomoyo_del_file_pattern(element); 328 break; 329 case TOMOYO_ID_NO_REWRITE: 330 tomoyo_del_no_rewrite(element); 331 break; 332 case TOMOYO_ID_MANAGER: 333 tomoyo_del_manager(element); 334 break; 335 case TOMOYO_ID_NAME: 336 tomoyo_del_name(element); 337 break; 338 case TOMOYO_ID_ACL: 339 tomoyo_del_acl(element); 340 break; 341 case TOMOYO_ID_DOMAIN: 342 if (!tomoyo_del_domain(element)) 343 continue; 344 break; 345 case TOMOYO_ID_PATH_GROUP: 346 tomoyo_del_path_group(element); 347 break; 348 case TOMOYO_ID_GROUP: 349 tomoyo_del_group(element); 350 break; 351 case TOMOYO_ID_NUMBER_GROUP: 352 tomoyo_del_number_group(element); 353 break; 354 } 355 tomoyo_memory_free(element); 356 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} 385