1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * security/tomoyo/gc.c 4 * 5 * Copyright (C) 2005-2011 NTT DATA CORPORATION 6 */ 7 8 #include "common.h" 9 #include <linux/kthread.h> 10 #include <linux/slab.h> 11 12 /** 13 * tomoyo_memory_free - Free memory for elements. 14 * 15 * @ptr: Pointer to allocated memory. 16 * 17 * Returns nothing. 18 * 19 * Caller holds tomoyo_policy_lock mutex. 20 */ 21 static inline void tomoyo_memory_free(void *ptr) 22 { 23 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= ksize(ptr); 24 kfree(ptr); 25 } 26 27 /* The list for "struct tomoyo_io_buffer". */ 28 static LIST_HEAD(tomoyo_io_buffer_list); 29 /* Lock for protecting tomoyo_io_buffer_list. */ 30 static DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock); 31 32 /** 33 * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not. 34 * 35 * @element: Pointer to "struct list_head". 36 * 37 * Returns true if @element is used by /sys/kernel/security/tomoyo/ users, 38 * false otherwise. 39 */ 40 static bool tomoyo_struct_used_by_io_buffer(const struct list_head *element) 41 { 42 struct tomoyo_io_buffer *head; 43 bool in_use = false; 44 45 spin_lock(&tomoyo_io_buffer_list_lock); 46 list_for_each_entry(head, &tomoyo_io_buffer_list, list) { 47 head->users++; 48 spin_unlock(&tomoyo_io_buffer_list_lock); 49 mutex_lock(&head->io_sem); 50 if (head->r.domain == element || head->r.group == element || 51 head->r.acl == element || &head->w.domain->list == element) 52 in_use = true; 53 mutex_unlock(&head->io_sem); 54 spin_lock(&tomoyo_io_buffer_list_lock); 55 head->users--; 56 if (in_use) 57 break; 58 } 59 spin_unlock(&tomoyo_io_buffer_list_lock); 60 return in_use; 61 } 62 63 /** 64 * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not. 65 * 66 * @string: String to check. 67 * 68 * Returns true if @string is used by /sys/kernel/security/tomoyo/ users, 69 * false otherwise. 70 */ 71 static bool tomoyo_name_used_by_io_buffer(const char *string) 72 { 73 struct tomoyo_io_buffer *head; 74 const size_t size = strlen(string) + 1; 75 bool in_use = false; 76 77 spin_lock(&tomoyo_io_buffer_list_lock); 78 list_for_each_entry(head, &tomoyo_io_buffer_list, list) { 79 int i; 80 head->users++; 81 spin_unlock(&tomoyo_io_buffer_list_lock); 82 mutex_lock(&head->io_sem); 83 for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) { 84 const char *w = head->r.w[i]; 85 if (w < string || w > string + size) 86 continue; 87 in_use = true; 88 break; 89 } 90 mutex_unlock(&head->io_sem); 91 spin_lock(&tomoyo_io_buffer_list_lock); 92 head->users--; 93 if (in_use) 94 break; 95 } 96 spin_unlock(&tomoyo_io_buffer_list_lock); 97 return in_use; 98 } 99 100 /** 101 * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control". 102 * 103 * @element: Pointer to "struct list_head". 104 * 105 * Returns nothing. 106 */ 107 static inline void tomoyo_del_transition_control(struct list_head *element) 108 { 109 struct tomoyo_transition_control *ptr = 110 container_of(element, typeof(*ptr), head.list); 111 tomoyo_put_name(ptr->domainname); 112 tomoyo_put_name(ptr->program); 113 } 114 115 /** 116 * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator". 117 * 118 * @element: Pointer to "struct list_head". 119 * 120 * Returns nothing. 121 */ 122 static inline void tomoyo_del_aggregator(struct list_head *element) 123 { 124 struct tomoyo_aggregator *ptr = 125 container_of(element, typeof(*ptr), head.list); 126 tomoyo_put_name(ptr->original_name); 127 tomoyo_put_name(ptr->aggregated_name); 128 } 129 130 /** 131 * tomoyo_del_manager - Delete members in "struct tomoyo_manager". 132 * 133 * @element: Pointer to "struct list_head". 134 * 135 * Returns nothing. 136 */ 137 static inline void tomoyo_del_manager(struct list_head *element) 138 { 139 struct tomoyo_manager *ptr = 140 container_of(element, typeof(*ptr), head.list); 141 tomoyo_put_name(ptr->manager); 142 } 143 144 /** 145 * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info". 146 * 147 * @element: Pointer to "struct list_head". 148 * 149 * Returns nothing. 150 */ 151 static void tomoyo_del_acl(struct list_head *element) 152 { 153 struct tomoyo_acl_info *acl = 154 container_of(element, typeof(*acl), list); 155 tomoyo_put_condition(acl->cond); 156 switch (acl->type) { 157 case TOMOYO_TYPE_PATH_ACL: 158 { 159 struct tomoyo_path_acl *entry 160 = container_of(acl, typeof(*entry), head); 161 tomoyo_put_name_union(&entry->name); 162 } 163 break; 164 case TOMOYO_TYPE_PATH2_ACL: 165 { 166 struct tomoyo_path2_acl *entry 167 = container_of(acl, typeof(*entry), head); 168 tomoyo_put_name_union(&entry->name1); 169 tomoyo_put_name_union(&entry->name2); 170 } 171 break; 172 case TOMOYO_TYPE_PATH_NUMBER_ACL: 173 { 174 struct tomoyo_path_number_acl *entry 175 = container_of(acl, typeof(*entry), head); 176 tomoyo_put_name_union(&entry->name); 177 tomoyo_put_number_union(&entry->number); 178 } 179 break; 180 case TOMOYO_TYPE_MKDEV_ACL: 181 { 182 struct tomoyo_mkdev_acl *entry 183 = container_of(acl, typeof(*entry), head); 184 tomoyo_put_name_union(&entry->name); 185 tomoyo_put_number_union(&entry->mode); 186 tomoyo_put_number_union(&entry->major); 187 tomoyo_put_number_union(&entry->minor); 188 } 189 break; 190 case TOMOYO_TYPE_MOUNT_ACL: 191 { 192 struct tomoyo_mount_acl *entry 193 = container_of(acl, typeof(*entry), head); 194 tomoyo_put_name_union(&entry->dev_name); 195 tomoyo_put_name_union(&entry->dir_name); 196 tomoyo_put_name_union(&entry->fs_type); 197 tomoyo_put_number_union(&entry->flags); 198 } 199 break; 200 case TOMOYO_TYPE_ENV_ACL: 201 { 202 struct tomoyo_env_acl *entry = 203 container_of(acl, typeof(*entry), head); 204 205 tomoyo_put_name(entry->env); 206 } 207 break; 208 case TOMOYO_TYPE_INET_ACL: 209 { 210 struct tomoyo_inet_acl *entry = 211 container_of(acl, typeof(*entry), head); 212 213 tomoyo_put_group(entry->address.group); 214 tomoyo_put_number_union(&entry->port); 215 } 216 break; 217 case TOMOYO_TYPE_UNIX_ACL: 218 { 219 struct tomoyo_unix_acl *entry = 220 container_of(acl, typeof(*entry), head); 221 222 tomoyo_put_name_union(&entry->name); 223 } 224 break; 225 case TOMOYO_TYPE_MANUAL_TASK_ACL: 226 { 227 struct tomoyo_task_acl *entry = 228 container_of(acl, typeof(*entry), head); 229 tomoyo_put_name(entry->domainname); 230 } 231 break; 232 } 233 } 234 235 /** 236 * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info". 237 * 238 * @element: Pointer to "struct list_head". 239 * 240 * Returns nothing. 241 * 242 * Caller holds tomoyo_policy_lock mutex. 243 */ 244 static inline void tomoyo_del_domain(struct list_head *element) 245 { 246 struct tomoyo_domain_info *domain = 247 container_of(element, typeof(*domain), list); 248 struct tomoyo_acl_info *acl; 249 struct tomoyo_acl_info *tmp; 250 /* 251 * Since this domain is referenced from neither 252 * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete 253 * elements without checking for is_deleted flag. 254 */ 255 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { 256 tomoyo_del_acl(&acl->list); 257 tomoyo_memory_free(acl); 258 } 259 tomoyo_put_name(domain->domainname); 260 } 261 262 /** 263 * tomoyo_del_condition - Delete members in "struct tomoyo_condition". 264 * 265 * @element: Pointer to "struct list_head". 266 * 267 * Returns nothing. 268 */ 269 void tomoyo_del_condition(struct list_head *element) 270 { 271 struct tomoyo_condition *cond = container_of(element, typeof(*cond), 272 head.list); 273 const u16 condc = cond->condc; 274 const u16 numbers_count = cond->numbers_count; 275 const u16 names_count = cond->names_count; 276 const u16 argc = cond->argc; 277 const u16 envc = cond->envc; 278 unsigned int i; 279 const struct tomoyo_condition_element *condp 280 = (const struct tomoyo_condition_element *) (cond + 1); 281 struct tomoyo_number_union *numbers_p 282 = (struct tomoyo_number_union *) (condp + condc); 283 struct tomoyo_name_union *names_p 284 = (struct tomoyo_name_union *) (numbers_p + numbers_count); 285 const struct tomoyo_argv *argv 286 = (const struct tomoyo_argv *) (names_p + names_count); 287 const struct tomoyo_envp *envp 288 = (const struct tomoyo_envp *) (argv + argc); 289 for (i = 0; i < numbers_count; i++) 290 tomoyo_put_number_union(numbers_p++); 291 for (i = 0; i < names_count; i++) 292 tomoyo_put_name_union(names_p++); 293 for (i = 0; i < argc; argv++, i++) 294 tomoyo_put_name(argv->value); 295 for (i = 0; i < envc; envp++, i++) { 296 tomoyo_put_name(envp->name); 297 tomoyo_put_name(envp->value); 298 } 299 } 300 301 /** 302 * tomoyo_del_name - Delete members in "struct tomoyo_name". 303 * 304 * @element: Pointer to "struct list_head". 305 * 306 * Returns nothing. 307 */ 308 static inline void tomoyo_del_name(struct list_head *element) 309 { 310 /* Nothing to do. */ 311 } 312 313 /** 314 * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group". 315 * 316 * @element: Pointer to "struct list_head". 317 * 318 * Returns nothing. 319 */ 320 static inline void tomoyo_del_path_group(struct list_head *element) 321 { 322 struct tomoyo_path_group *member = 323 container_of(element, typeof(*member), head.list); 324 tomoyo_put_name(member->member_name); 325 } 326 327 /** 328 * tomoyo_del_group - Delete "struct tomoyo_group". 329 * 330 * @element: Pointer to "struct list_head". 331 * 332 * Returns nothing. 333 */ 334 static inline void tomoyo_del_group(struct list_head *element) 335 { 336 struct tomoyo_group *group = 337 container_of(element, typeof(*group), head.list); 338 tomoyo_put_name(group->group_name); 339 } 340 341 /** 342 * tomoyo_del_address_group - Delete members in "struct tomoyo_address_group". 343 * 344 * @element: Pointer to "struct list_head". 345 * 346 * Returns nothing. 347 */ 348 static inline void tomoyo_del_address_group(struct list_head *element) 349 { 350 /* Nothing to do. */ 351 } 352 353 /** 354 * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group". 355 * 356 * @element: Pointer to "struct list_head". 357 * 358 * Returns nothing. 359 */ 360 static inline void tomoyo_del_number_group(struct list_head *element) 361 { 362 /* Nothing to do. */ 363 } 364 365 /** 366 * tomoyo_try_to_gc - Try to kfree() an entry. 367 * 368 * @type: One of values in "enum tomoyo_policy_id". 369 * @element: Pointer to "struct list_head". 370 * 371 * Returns nothing. 372 * 373 * Caller holds tomoyo_policy_lock mutex. 374 */ 375 static void tomoyo_try_to_gc(const enum tomoyo_policy_id type, 376 struct list_head *element) 377 { 378 /* 379 * __list_del_entry() guarantees that the list element became no longer 380 * reachable from the list which the element was originally on (e.g. 381 * tomoyo_domain_list). Also, synchronize_srcu() guarantees that the 382 * list element became no longer referenced by syscall users. 383 */ 384 __list_del_entry(element); 385 mutex_unlock(&tomoyo_policy_lock); 386 synchronize_srcu(&tomoyo_ss); 387 /* 388 * However, there are two users which may still be using the list 389 * element. We need to defer until both users forget this element. 390 * 391 * Don't kfree() until "struct tomoyo_io_buffer"->r.{domain,group,acl} 392 * and "struct tomoyo_io_buffer"->w.domain forget this element. 393 */ 394 if (tomoyo_struct_used_by_io_buffer(element)) 395 goto reinject; 396 switch (type) { 397 case TOMOYO_ID_TRANSITION_CONTROL: 398 tomoyo_del_transition_control(element); 399 break; 400 case TOMOYO_ID_MANAGER: 401 tomoyo_del_manager(element); 402 break; 403 case TOMOYO_ID_AGGREGATOR: 404 tomoyo_del_aggregator(element); 405 break; 406 case TOMOYO_ID_GROUP: 407 tomoyo_del_group(element); 408 break; 409 case TOMOYO_ID_PATH_GROUP: 410 tomoyo_del_path_group(element); 411 break; 412 case TOMOYO_ID_ADDRESS_GROUP: 413 tomoyo_del_address_group(element); 414 break; 415 case TOMOYO_ID_NUMBER_GROUP: 416 tomoyo_del_number_group(element); 417 break; 418 case TOMOYO_ID_CONDITION: 419 tomoyo_del_condition(element); 420 break; 421 case TOMOYO_ID_NAME: 422 /* 423 * Don't kfree() until all "struct tomoyo_io_buffer"->r.w[] 424 * forget this element. 425 */ 426 if (tomoyo_name_used_by_io_buffer 427 (container_of(element, typeof(struct tomoyo_name), 428 head.list)->entry.name)) 429 goto reinject; 430 tomoyo_del_name(element); 431 break; 432 case TOMOYO_ID_ACL: 433 tomoyo_del_acl(element); 434 break; 435 case TOMOYO_ID_DOMAIN: 436 /* 437 * Don't kfree() until all "struct cred"->security forget this 438 * element. 439 */ 440 if (atomic_read(&container_of 441 (element, typeof(struct tomoyo_domain_info), 442 list)->users)) 443 goto reinject; 444 break; 445 case TOMOYO_MAX_POLICY: 446 break; 447 } 448 mutex_lock(&tomoyo_policy_lock); 449 if (type == TOMOYO_ID_DOMAIN) 450 tomoyo_del_domain(element); 451 tomoyo_memory_free(element); 452 return; 453 reinject: 454 /* 455 * We can safely reinject this element here bacause 456 * (1) Appending list elements and removing list elements are protected 457 * by tomoyo_policy_lock mutex. 458 * (2) Only this function removes list elements and this function is 459 * exclusively executed by tomoyo_gc_mutex mutex. 460 * are true. 461 */ 462 mutex_lock(&tomoyo_policy_lock); 463 list_add_rcu(element, element->prev); 464 } 465 466 /** 467 * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head". 468 * 469 * @id: One of values in "enum tomoyo_policy_id". 470 * @member_list: Pointer to "struct list_head". 471 * 472 * Returns nothing. 473 */ 474 static void tomoyo_collect_member(const enum tomoyo_policy_id id, 475 struct list_head *member_list) 476 { 477 struct tomoyo_acl_head *member; 478 struct tomoyo_acl_head *tmp; 479 list_for_each_entry_safe(member, tmp, member_list, list) { 480 if (!member->is_deleted) 481 continue; 482 member->is_deleted = TOMOYO_GC_IN_PROGRESS; 483 tomoyo_try_to_gc(id, &member->list); 484 } 485 } 486 487 /** 488 * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info". 489 * 490 * @list: Pointer to "struct list_head". 491 * 492 * Returns nothing. 493 */ 494 static void tomoyo_collect_acl(struct list_head *list) 495 { 496 struct tomoyo_acl_info *acl; 497 struct tomoyo_acl_info *tmp; 498 list_for_each_entry_safe(acl, tmp, list, list) { 499 if (!acl->is_deleted) 500 continue; 501 acl->is_deleted = TOMOYO_GC_IN_PROGRESS; 502 tomoyo_try_to_gc(TOMOYO_ID_ACL, &acl->list); 503 } 504 } 505 506 /** 507 * tomoyo_collect_entry - Try to kfree() deleted elements. 508 * 509 * Returns nothing. 510 */ 511 static void tomoyo_collect_entry(void) 512 { 513 int i; 514 enum tomoyo_policy_id id; 515 struct tomoyo_policy_namespace *ns; 516 mutex_lock(&tomoyo_policy_lock); 517 { 518 struct tomoyo_domain_info *domain; 519 struct tomoyo_domain_info *tmp; 520 list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list, 521 list) { 522 tomoyo_collect_acl(&domain->acl_info_list); 523 if (!domain->is_deleted || atomic_read(&domain->users)) 524 continue; 525 tomoyo_try_to_gc(TOMOYO_ID_DOMAIN, &domain->list); 526 } 527 } 528 list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { 529 for (id = 0; id < TOMOYO_MAX_POLICY; id++) 530 tomoyo_collect_member(id, &ns->policy_list[id]); 531 for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++) 532 tomoyo_collect_acl(&ns->acl_group[i]); 533 } 534 { 535 struct tomoyo_shared_acl_head *ptr; 536 struct tomoyo_shared_acl_head *tmp; 537 list_for_each_entry_safe(ptr, tmp, &tomoyo_condition_list, 538 list) { 539 if (atomic_read(&ptr->users) > 0) 540 continue; 541 atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS); 542 tomoyo_try_to_gc(TOMOYO_ID_CONDITION, &ptr->list); 543 } 544 } 545 list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { 546 for (i = 0; i < TOMOYO_MAX_GROUP; i++) { 547 struct list_head *list = &ns->group_list[i]; 548 struct tomoyo_group *group; 549 struct tomoyo_group *tmp; 550 switch (i) { 551 case 0: 552 id = TOMOYO_ID_PATH_GROUP; 553 break; 554 case 1: 555 id = TOMOYO_ID_NUMBER_GROUP; 556 break; 557 default: 558 id = TOMOYO_ID_ADDRESS_GROUP; 559 break; 560 } 561 list_for_each_entry_safe(group, tmp, list, head.list) { 562 tomoyo_collect_member(id, &group->member_list); 563 if (!list_empty(&group->member_list) || 564 atomic_read(&group->head.users) > 0) 565 continue; 566 atomic_set(&group->head.users, 567 TOMOYO_GC_IN_PROGRESS); 568 tomoyo_try_to_gc(TOMOYO_ID_GROUP, 569 &group->head.list); 570 } 571 } 572 } 573 for (i = 0; i < TOMOYO_MAX_HASH; i++) { 574 struct list_head *list = &tomoyo_name_list[i]; 575 struct tomoyo_shared_acl_head *ptr; 576 struct tomoyo_shared_acl_head *tmp; 577 list_for_each_entry_safe(ptr, tmp, list, list) { 578 if (atomic_read(&ptr->users) > 0) 579 continue; 580 atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS); 581 tomoyo_try_to_gc(TOMOYO_ID_NAME, &ptr->list); 582 } 583 } 584 mutex_unlock(&tomoyo_policy_lock); 585 } 586 587 /** 588 * tomoyo_gc_thread - Garbage collector thread function. 589 * 590 * @unused: Unused. 591 * 592 * Returns 0. 593 */ 594 static int tomoyo_gc_thread(void *unused) 595 { 596 /* Garbage collector thread is exclusive. */ 597 static DEFINE_MUTEX(tomoyo_gc_mutex); 598 if (!mutex_trylock(&tomoyo_gc_mutex)) 599 goto out; 600 tomoyo_collect_entry(); 601 { 602 struct tomoyo_io_buffer *head; 603 struct tomoyo_io_buffer *tmp; 604 605 spin_lock(&tomoyo_io_buffer_list_lock); 606 list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list, 607 list) { 608 if (head->users) 609 continue; 610 list_del(&head->list); 611 kfree(head->read_buf); 612 kfree(head->write_buf); 613 kfree(head); 614 } 615 spin_unlock(&tomoyo_io_buffer_list_lock); 616 } 617 mutex_unlock(&tomoyo_gc_mutex); 618 out: 619 /* This acts as do_exit(0). */ 620 return 0; 621 } 622 623 /** 624 * tomoyo_notify_gc - Register/unregister /sys/kernel/security/tomoyo/ users. 625 * 626 * @head: Pointer to "struct tomoyo_io_buffer". 627 * @is_register: True if register, false if unregister. 628 * 629 * Returns nothing. 630 */ 631 void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register) 632 { 633 bool is_write = false; 634 635 spin_lock(&tomoyo_io_buffer_list_lock); 636 if (is_register) { 637 head->users = 1; 638 list_add(&head->list, &tomoyo_io_buffer_list); 639 } else { 640 is_write = head->write_buf != NULL; 641 if (!--head->users) { 642 list_del(&head->list); 643 kfree(head->read_buf); 644 kfree(head->write_buf); 645 kfree(head); 646 } 647 } 648 spin_unlock(&tomoyo_io_buffer_list_lock); 649 if (is_write) 650 kthread_run(tomoyo_gc_thread, NULL, "GC for TOMOYO"); 651 } 652