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