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 14 enum tomoyo_gc_id { 15 TOMOYO_ID_PATH_GROUP, 16 TOMOYO_ID_PATH_GROUP_MEMBER, 17 TOMOYO_ID_DOMAIN_INITIALIZER, 18 TOMOYO_ID_DOMAIN_KEEPER, 19 TOMOYO_ID_ALIAS, 20 TOMOYO_ID_GLOBALLY_READABLE, 21 TOMOYO_ID_PATTERN, 22 TOMOYO_ID_NO_REWRITE, 23 TOMOYO_ID_MANAGER, 24 TOMOYO_ID_NAME, 25 TOMOYO_ID_ACL, 26 TOMOYO_ID_DOMAIN 27 }; 28 29 struct tomoyo_gc_entry { 30 struct list_head list; 31 int type; 32 void *element; 33 }; 34 static LIST_HEAD(tomoyo_gc_queue); 35 static DEFINE_MUTEX(tomoyo_gc_mutex); 36 37 /* Caller holds tomoyo_policy_lock mutex. */ 38 static bool tomoyo_add_to_gc(const int type, void *element) 39 { 40 struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 41 if (!entry) 42 return false; 43 entry->type = type; 44 entry->element = element; 45 list_add(&entry->list, &tomoyo_gc_queue); 46 return true; 47 } 48 49 static void tomoyo_del_allow_read 50 (struct tomoyo_globally_readable_file_entry *ptr) 51 { 52 tomoyo_put_name(ptr->filename); 53 } 54 55 static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr) 56 { 57 tomoyo_put_name(ptr->pattern); 58 } 59 60 static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr) 61 { 62 tomoyo_put_name(ptr->pattern); 63 } 64 65 static void tomoyo_del_domain_initializer 66 (struct tomoyo_domain_initializer_entry *ptr) 67 { 68 tomoyo_put_name(ptr->domainname); 69 tomoyo_put_name(ptr->program); 70 } 71 72 static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr) 73 { 74 tomoyo_put_name(ptr->domainname); 75 tomoyo_put_name(ptr->program); 76 } 77 78 static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr) 79 { 80 tomoyo_put_name(ptr->original_name); 81 tomoyo_put_name(ptr->aliased_name); 82 } 83 84 static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr) 85 { 86 tomoyo_put_name(ptr->manager); 87 } 88 89 static void tomoyo_del_acl(struct tomoyo_acl_info *acl) 90 { 91 switch (acl->type) { 92 case TOMOYO_TYPE_PATH_ACL: 93 { 94 struct tomoyo_path_acl *entry 95 = container_of(acl, typeof(*entry), head); 96 tomoyo_put_name_union(&entry->name); 97 } 98 break; 99 case TOMOYO_TYPE_PATH2_ACL: 100 { 101 struct tomoyo_path2_acl *entry 102 = container_of(acl, typeof(*entry), head); 103 tomoyo_put_name_union(&entry->name1); 104 tomoyo_put_name_union(&entry->name2); 105 } 106 break; 107 default: 108 printk(KERN_WARNING "Unknown type\n"); 109 break; 110 } 111 } 112 113 static bool tomoyo_del_domain(struct tomoyo_domain_info *domain) 114 { 115 struct tomoyo_acl_info *acl; 116 struct tomoyo_acl_info *tmp; 117 /* 118 * Since we don't protect whole execve() operation using SRCU, 119 * we need to recheck domain->users at this point. 120 * 121 * (1) Reader starts SRCU section upon execve(). 122 * (2) Reader traverses tomoyo_domain_list and finds this domain. 123 * (3) Writer marks this domain as deleted. 124 * (4) Garbage collector removes this domain from tomoyo_domain_list 125 * because this domain is marked as deleted and used by nobody. 126 * (5) Reader saves reference to this domain into 127 * "struct linux_binprm"->cred->security . 128 * (6) Reader finishes SRCU section, although execve() operation has 129 * not finished yet. 130 * (7) Garbage collector waits for SRCU synchronization. 131 * (8) Garbage collector kfree() this domain because this domain is 132 * used by nobody. 133 * (9) Reader finishes execve() operation and restores this domain from 134 * "struct linux_binprm"->cred->security. 135 * 136 * By updating domain->users at (5), we can solve this race problem 137 * by rechecking domain->users at (8). 138 */ 139 if (atomic_read(&domain->users)) 140 return false; 141 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { 142 tomoyo_del_acl(acl); 143 tomoyo_memory_free(acl); 144 } 145 tomoyo_put_name(domain->domainname); 146 return true; 147 } 148 149 150 static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) 151 { 152 } 153 154 static void tomoyo_del_path_group_member(struct tomoyo_path_group_member 155 *member) 156 { 157 tomoyo_put_name(member->member_name); 158 } 159 160 static void tomoyo_del_path_group(struct tomoyo_path_group *group) 161 { 162 tomoyo_put_name(group->group_name); 163 } 164 165 static void tomoyo_collect_entry(void) 166 { 167 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 168 return; 169 { 170 struct tomoyo_globally_readable_file_entry *ptr; 171 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, 172 list) { 173 if (!ptr->is_deleted) 174 continue; 175 if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr)) 176 list_del_rcu(&ptr->list); 177 else 178 break; 179 } 180 } 181 { 182 struct tomoyo_pattern_entry *ptr; 183 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { 184 if (!ptr->is_deleted) 185 continue; 186 if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr)) 187 list_del_rcu(&ptr->list); 188 else 189 break; 190 } 191 } 192 { 193 struct tomoyo_no_rewrite_entry *ptr; 194 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 195 if (!ptr->is_deleted) 196 continue; 197 if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr)) 198 list_del_rcu(&ptr->list); 199 else 200 break; 201 } 202 } 203 { 204 struct tomoyo_domain_initializer_entry *ptr; 205 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, 206 list) { 207 if (!ptr->is_deleted) 208 continue; 209 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr)) 210 list_del_rcu(&ptr->list); 211 else 212 break; 213 } 214 } 215 { 216 struct tomoyo_domain_keeper_entry *ptr; 217 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { 218 if (!ptr->is_deleted) 219 continue; 220 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr)) 221 list_del_rcu(&ptr->list); 222 else 223 break; 224 } 225 } 226 { 227 struct tomoyo_alias_entry *ptr; 228 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 229 if (!ptr->is_deleted) 230 continue; 231 if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr)) 232 list_del_rcu(&ptr->list); 233 else 234 break; 235 } 236 } 237 { 238 struct tomoyo_policy_manager_entry *ptr; 239 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, 240 list) { 241 if (!ptr->is_deleted) 242 continue; 243 if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr)) 244 list_del_rcu(&ptr->list); 245 else 246 break; 247 } 248 } 249 { 250 struct tomoyo_domain_info *domain; 251 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 252 struct tomoyo_acl_info *acl; 253 list_for_each_entry_rcu(acl, &domain->acl_info_list, 254 list) { 255 switch (acl->type) { 256 case TOMOYO_TYPE_PATH_ACL: 257 if (container_of(acl, 258 struct tomoyo_path_acl, 259 head)->perm || 260 container_of(acl, 261 struct tomoyo_path_acl, 262 head)->perm_high) 263 continue; 264 break; 265 case TOMOYO_TYPE_PATH2_ACL: 266 if (container_of(acl, 267 struct tomoyo_path2_acl, 268 head)->perm) 269 continue; 270 break; 271 default: 272 continue; 273 } 274 if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl)) 275 list_del_rcu(&acl->list); 276 else 277 break; 278 } 279 if (!domain->is_deleted || atomic_read(&domain->users)) 280 continue; 281 /* 282 * Nobody is referring this domain. But somebody may 283 * refer this domain after successful execve(). 284 * We recheck domain->users after SRCU synchronization. 285 */ 286 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain)) 287 list_del_rcu(&domain->list); 288 else 289 break; 290 } 291 } 292 { 293 int i; 294 for (i = 0; i < TOMOYO_MAX_HASH; i++) { 295 struct tomoyo_name_entry *ptr; 296 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], 297 list) { 298 if (atomic_read(&ptr->users)) 299 continue; 300 if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr)) 301 list_del_rcu(&ptr->list); 302 else { 303 i = TOMOYO_MAX_HASH; 304 break; 305 } 306 } 307 } 308 } 309 { 310 struct tomoyo_path_group *group; 311 list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { 312 struct tomoyo_path_group_member *member; 313 list_for_each_entry_rcu(member, &group->member_list, 314 list) { 315 if (!member->is_deleted) 316 continue; 317 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER, 318 member)) 319 list_del_rcu(&member->list); 320 else 321 break; 322 } 323 if (!list_empty(&group->member_list) || 324 atomic_read(&group->users)) 325 continue; 326 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group)) 327 list_del_rcu(&group->list); 328 else 329 break; 330 } 331 } 332 mutex_unlock(&tomoyo_policy_lock); 333 } 334 335 static void tomoyo_kfree_entry(void) 336 { 337 struct tomoyo_gc_entry *p; 338 struct tomoyo_gc_entry *tmp; 339 340 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { 341 switch (p->type) { 342 case TOMOYO_ID_DOMAIN_INITIALIZER: 343 tomoyo_del_domain_initializer(p->element); 344 break; 345 case TOMOYO_ID_DOMAIN_KEEPER: 346 tomoyo_del_domain_keeper(p->element); 347 break; 348 case TOMOYO_ID_ALIAS: 349 tomoyo_del_alias(p->element); 350 break; 351 case TOMOYO_ID_GLOBALLY_READABLE: 352 tomoyo_del_allow_read(p->element); 353 break; 354 case TOMOYO_ID_PATTERN: 355 tomoyo_del_file_pattern(p->element); 356 break; 357 case TOMOYO_ID_NO_REWRITE: 358 tomoyo_del_no_rewrite(p->element); 359 break; 360 case TOMOYO_ID_MANAGER: 361 tomoyo_del_manager(p->element); 362 break; 363 case TOMOYO_ID_NAME: 364 tomoyo_del_name(p->element); 365 break; 366 case TOMOYO_ID_ACL: 367 tomoyo_del_acl(p->element); 368 break; 369 case TOMOYO_ID_DOMAIN: 370 if (!tomoyo_del_domain(p->element)) 371 continue; 372 break; 373 case TOMOYO_ID_PATH_GROUP_MEMBER: 374 tomoyo_del_path_group_member(p->element); 375 break; 376 case TOMOYO_ID_PATH_GROUP: 377 tomoyo_del_path_group(p->element); 378 break; 379 default: 380 printk(KERN_WARNING "Unknown type\n"); 381 break; 382 } 383 tomoyo_memory_free(p->element); 384 list_del(&p->list); 385 kfree(p); 386 } 387 } 388 389 static int tomoyo_gc_thread(void *unused) 390 { 391 daemonize("GC for TOMOYO"); 392 if (mutex_trylock(&tomoyo_gc_mutex)) { 393 int i; 394 for (i = 0; i < 10; i++) { 395 tomoyo_collect_entry(); 396 if (list_empty(&tomoyo_gc_queue)) 397 break; 398 synchronize_srcu(&tomoyo_ss); 399 tomoyo_kfree_entry(); 400 } 401 mutex_unlock(&tomoyo_gc_mutex); 402 } 403 do_exit(0); 404 } 405 406 void tomoyo_run_gc(void) 407 { 408 struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL, 409 "GC for TOMOYO"); 410 if (!IS_ERR(task)) 411 wake_up_process(task); 412 } 413