root/security/tomoyo/gc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tomoyo_memory_free
  2. tomoyo_struct_used_by_io_buffer
  3. tomoyo_name_used_by_io_buffer
  4. tomoyo_del_transition_control
  5. tomoyo_del_aggregator
  6. tomoyo_del_manager
  7. tomoyo_del_acl
  8. tomoyo_del_domain
  9. tomoyo_del_condition
  10. tomoyo_del_name
  11. tomoyo_del_path_group
  12. tomoyo_del_group
  13. tomoyo_del_address_group
  14. tomoyo_del_number_group
  15. tomoyo_try_to_gc
  16. tomoyo_collect_member
  17. tomoyo_collect_acl
  18. tomoyo_collect_entry
  19. tomoyo_gc_thread
  20. tomoyo_notify_gc

   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 
  81                 head->users++;
  82                 spin_unlock(&tomoyo_io_buffer_list_lock);
  83                 mutex_lock(&head->io_sem);
  84                 for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) {
  85                         const char *w = head->r.w[i];
  86 
  87                         if (w < string || w > string + size)
  88                                 continue;
  89                         in_use = true;
  90                         break;
  91                 }
  92                 mutex_unlock(&head->io_sem);
  93                 spin_lock(&tomoyo_io_buffer_list_lock);
  94                 head->users--;
  95                 if (in_use)
  96                         break;
  97         }
  98         spin_unlock(&tomoyo_io_buffer_list_lock);
  99         return in_use;
 100 }
 101 
 102 /**
 103  * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
 104  *
 105  * @element: Pointer to "struct list_head".
 106  *
 107  * Returns nothing.
 108  */
 109 static inline void tomoyo_del_transition_control(struct list_head *element)
 110 {
 111         struct tomoyo_transition_control *ptr =
 112                 container_of(element, typeof(*ptr), head.list);
 113 
 114         tomoyo_put_name(ptr->domainname);
 115         tomoyo_put_name(ptr->program);
 116 }
 117 
 118 /**
 119  * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator".
 120  *
 121  * @element: Pointer to "struct list_head".
 122  *
 123  * Returns nothing.
 124  */
 125 static inline void tomoyo_del_aggregator(struct list_head *element)
 126 {
 127         struct tomoyo_aggregator *ptr =
 128                 container_of(element, typeof(*ptr), head.list);
 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 "struct tomoyo_manager".
 136  *
 137  * @element: Pointer to "struct list_head".
 138  *
 139  * Returns nothing.
 140  */
 141 static inline void tomoyo_del_manager(struct list_head *element)
 142 {
 143         struct tomoyo_manager *ptr =
 144                 container_of(element, typeof(*ptr), head.list);
 145 
 146         tomoyo_put_name(ptr->manager);
 147 }
 148 
 149 /**
 150  * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info".
 151  *
 152  * @element: Pointer to "struct list_head".
 153  *
 154  * Returns nothing.
 155  */
 156 static void tomoyo_del_acl(struct list_head *element)
 157 {
 158         struct tomoyo_acl_info *acl =
 159                 container_of(element, typeof(*acl), list);
 160 
 161         tomoyo_put_condition(acl->cond);
 162         switch (acl->type) {
 163         case TOMOYO_TYPE_PATH_ACL:
 164                 {
 165                         struct tomoyo_path_acl *entry
 166                                 = container_of(acl, typeof(*entry), head);
 167                         tomoyo_put_name_union(&entry->name);
 168                 }
 169                 break;
 170         case TOMOYO_TYPE_PATH2_ACL:
 171                 {
 172                         struct tomoyo_path2_acl *entry
 173                                 = container_of(acl, typeof(*entry), head);
 174                         tomoyo_put_name_union(&entry->name1);
 175                         tomoyo_put_name_union(&entry->name2);
 176                 }
 177                 break;
 178         case TOMOYO_TYPE_PATH_NUMBER_ACL:
 179                 {
 180                         struct tomoyo_path_number_acl *entry
 181                                 = container_of(acl, typeof(*entry), head);
 182                         tomoyo_put_name_union(&entry->name);
 183                         tomoyo_put_number_union(&entry->number);
 184                 }
 185                 break;
 186         case TOMOYO_TYPE_MKDEV_ACL:
 187                 {
 188                         struct tomoyo_mkdev_acl *entry
 189                                 = container_of(acl, typeof(*entry), head);
 190                         tomoyo_put_name_union(&entry->name);
 191                         tomoyo_put_number_union(&entry->mode);
 192                         tomoyo_put_number_union(&entry->major);
 193                         tomoyo_put_number_union(&entry->minor);
 194                 }
 195                 break;
 196         case TOMOYO_TYPE_MOUNT_ACL:
 197                 {
 198                         struct tomoyo_mount_acl *entry
 199                                 = container_of(acl, typeof(*entry), head);
 200                         tomoyo_put_name_union(&entry->dev_name);
 201                         tomoyo_put_name_union(&entry->dir_name);
 202                         tomoyo_put_name_union(&entry->fs_type);
 203                         tomoyo_put_number_union(&entry->flags);
 204                 }
 205                 break;
 206         case TOMOYO_TYPE_ENV_ACL:
 207                 {
 208                         struct tomoyo_env_acl *entry =
 209                                 container_of(acl, typeof(*entry), head);
 210 
 211                         tomoyo_put_name(entry->env);
 212                 }
 213                 break;
 214         case TOMOYO_TYPE_INET_ACL:
 215                 {
 216                         struct tomoyo_inet_acl *entry =
 217                                 container_of(acl, typeof(*entry), head);
 218 
 219                         tomoyo_put_group(entry->address.group);
 220                         tomoyo_put_number_union(&entry->port);
 221                 }
 222                 break;
 223         case TOMOYO_TYPE_UNIX_ACL:
 224                 {
 225                         struct tomoyo_unix_acl *entry =
 226                                 container_of(acl, typeof(*entry), head);
 227 
 228                         tomoyo_put_name_union(&entry->name);
 229                 }
 230                 break;
 231         case TOMOYO_TYPE_MANUAL_TASK_ACL:
 232                 {
 233                         struct tomoyo_task_acl *entry =
 234                                 container_of(acl, typeof(*entry), head);
 235 
 236                         tomoyo_put_name(entry->domainname);
 237                 }
 238                 break;
 239         }
 240 }
 241 
 242 /**
 243  * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info".
 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 list_head *element)
 252 {
 253         struct tomoyo_domain_info *domain =
 254                 container_of(element, typeof(*domain), list);
 255         struct tomoyo_acl_info *acl;
 256         struct tomoyo_acl_info *tmp;
 257 
 258         /*
 259          * Since this domain is referenced from neither
 260          * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete
 261          * elements without checking for is_deleted flag.
 262          */
 263         list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
 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 "struct tomoyo_condition".
 272  *
 273  * @element: Pointer to "struct list_head".
 274  *
 275  * Returns nothing.
 276  */
 277 void tomoyo_del_condition(struct list_head *element)
 278 {
 279         struct tomoyo_condition *cond = container_of(element, typeof(*cond),
 280                                                      head.list);
 281         const u16 condc = cond->condc;
 282         const u16 numbers_count = cond->numbers_count;
 283         const u16 names_count = cond->names_count;
 284         const u16 argc = cond->argc;
 285         const u16 envc = cond->envc;
 286         unsigned int i;
 287         const struct tomoyo_condition_element *condp
 288                 = (const struct tomoyo_condition_element *) (cond + 1);
 289         struct tomoyo_number_union *numbers_p
 290                 = (struct tomoyo_number_union *) (condp + condc);
 291         struct tomoyo_name_union *names_p
 292                 = (struct tomoyo_name_union *) (numbers_p + numbers_count);
 293         const struct tomoyo_argv *argv
 294                 = (const struct tomoyo_argv *) (names_p + names_count);
 295         const struct tomoyo_envp *envp
 296                 = (const struct tomoyo_envp *) (argv + argc);
 297 
 298         for (i = 0; i < numbers_count; i++)
 299                 tomoyo_put_number_union(numbers_p++);
 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 tomoyo_name".
 312  *
 313  * @element: Pointer to "struct list_head".
 314  *
 315  * Returns nothing.
 316  */
 317 static inline void tomoyo_del_name(struct list_head *element)
 318 {
 319         /* Nothing to do. */
 320 }
 321 
 322 /**
 323  * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group".
 324  *
 325  * @element: Pointer to "struct list_head".
 326  *
 327  * Returns nothing.
 328  */
 329 static inline void tomoyo_del_path_group(struct list_head *element)
 330 {
 331         struct tomoyo_path_group *member =
 332                 container_of(element, typeof(*member), head.list);
 333 
 334         tomoyo_put_name(member->member_name);
 335 }
 336 
 337 /**
 338  * tomoyo_del_group - Delete "struct tomoyo_group".
 339  *
 340  * @element: Pointer to "struct list_head".
 341  *
 342  * Returns nothing.
 343  */
 344 static inline void tomoyo_del_group(struct list_head *element)
 345 {
 346         struct tomoyo_group *group =
 347                 container_of(element, typeof(*group), head.list);
 348 
 349         tomoyo_put_name(group->group_name);
 350 }
 351 
 352 /**
 353  * tomoyo_del_address_group - Delete members in "struct tomoyo_address_group".
 354  *
 355  * @element: Pointer to "struct list_head".
 356  *
 357  * Returns nothing.
 358  */
 359 static inline void tomoyo_del_address_group(struct list_head *element)
 360 {
 361         /* Nothing to do. */
 362 }
 363 
 364 /**
 365  * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
 366  *
 367  * @element: Pointer to "struct list_head".
 368  *
 369  * Returns nothing.
 370  */
 371 static inline void tomoyo_del_number_group(struct list_head *element)
 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_policy_id".
 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_policy_id type,
 387                              struct list_head *element)
 388 {
 389         /*
 390          * __list_del_entry() guarantees that the list element became no longer
 391          * reachable from the list which the element was originally on (e.g.
 392          * tomoyo_domain_list). Also, synchronize_srcu() guarantees that the
 393          * list element became no longer referenced by syscall users.
 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 may still be using the list
 400          * element. We need to defer until both users forget this element.
 401          *
 402          * Don't kfree() until "struct tomoyo_io_buffer"->r.{domain,group,acl}
 403          * and "struct tomoyo_io_buffer"->w.domain forget this element.
 404          */
 405         if (tomoyo_struct_used_by_io_buffer(element))
 406                 goto reinject;
 407         switch (type) {
 408         case TOMOYO_ID_TRANSITION_CONTROL:
 409                 tomoyo_del_transition_control(element);
 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(element);
 425                 break;
 426         case TOMOYO_ID_NUMBER_GROUP:
 427                 tomoyo_del_number_group(element);
 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 "struct tomoyo_io_buffer"->r.w[]
 435                  * forget this element.
 436                  */
 437                 if (tomoyo_name_used_by_io_buffer
 438                     (container_of(element, typeof(struct tomoyo_name),
 439                                   head.list)->entry.name))
 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 "struct cred"->security forget this
 449                  * element.
 450                  */
 451                 if (atomic_read(&container_of
 452                                 (element, typeof(struct tomoyo_domain_info),
 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 here bacause
 467          * (1) Appending list elements and removing list elements are protected
 468          *     by tomoyo_policy_lock mutex.
 469          * (2) Only this function removes list elements and this function is
 470          *     exclusively executed by tomoyo_gc_mutex mutex.
 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 with "struct tomoyo_acl_head".
 479  *
 480  * @id:          One of values in "enum tomoyo_policy_id".
 481  * @member_list: Pointer to "struct list_head".
 482  *
 483  * Returns nothing.
 484  */
 485 static void tomoyo_collect_member(const enum tomoyo_policy_id id,
 486                                   struct list_head *member_list)
 487 {
 488         struct tomoyo_acl_head *member;
 489         struct tomoyo_acl_head *tmp;
 490 
 491         list_for_each_entry_safe(member, tmp, member_list, list) {
 492                 if (!member->is_deleted)
 493                         continue;
 494                 member->is_deleted = TOMOYO_GC_IN_PROGRESS;
 495                 tomoyo_try_to_gc(id, &member->list);
 496         }
 497 }
 498 
 499 /**
 500  * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info".
 501  *
 502  * @list: Pointer to "struct list_head".
 503  *
 504  * Returns nothing.
 505  */
 506 static void tomoyo_collect_acl(struct list_head *list)
 507 {
 508         struct tomoyo_acl_info *acl;
 509         struct tomoyo_acl_info *tmp;
 510 
 511         list_for_each_entry_safe(acl, tmp, list, list) {
 512                 if (!acl->is_deleted)
 513                         continue;
 514                 acl->is_deleted = TOMOYO_GC_IN_PROGRESS;
 515                 tomoyo_try_to_gc(TOMOYO_ID_ACL, &acl->list);
 516         }
 517 }
 518 
 519 /**
 520  * tomoyo_collect_entry - Try to kfree() deleted elements.
 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 *domain;
 533                 struct tomoyo_domain_info *tmp;
 534 
 535                 list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list,
 536                                          list) {
 537                         tomoyo_collect_acl(&domain->acl_info_list);
 538                         if (!domain->is_deleted || atomic_read(&domain->users))
 539                                 continue;
 540                         tomoyo_try_to_gc(TOMOYO_ID_DOMAIN, &domain->list);
 541                 }
 542         }
 543         list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
 544                 for (id = 0; id < TOMOYO_MAX_POLICY; id++)
 545                         tomoyo_collect_member(id, &ns->policy_list[id]);
 546                 for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
 547                         tomoyo_collect_acl(&ns->acl_group[i]);
 548         }
 549         {
 550                 struct tomoyo_shared_acl_head *ptr;
 551                 struct tomoyo_shared_acl_head *tmp;
 552 
 553                 list_for_each_entry_safe(ptr, tmp, &tomoyo_condition_list,
 554                                          list) {
 555                         if (atomic_read(&ptr->users) > 0)
 556                                 continue;
 557                         atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
 558                         tomoyo_try_to_gc(TOMOYO_ID_CONDITION, &ptr->list);
 559                 }
 560         }
 561         list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
 562                 for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
 563                         struct list_head *list = &ns->group_list[i];
 564                         struct tomoyo_group *group;
 565                         struct tomoyo_group *tmp;
 566 
 567                         switch (i) {
 568                         case 0:
 569                                 id = TOMOYO_ID_PATH_GROUP;
 570                                 break;
 571                         case 1:
 572                                 id = TOMOYO_ID_NUMBER_GROUP;
 573                                 break;
 574                         default:
 575                                 id = TOMOYO_ID_ADDRESS_GROUP;
 576                                 break;
 577                         }
 578                         list_for_each_entry_safe(group, tmp, list, head.list) {
 579                                 tomoyo_collect_member(id, &group->member_list);
 580                                 if (!list_empty(&group->member_list) ||
 581                                     atomic_read(&group->head.users) > 0)
 582                                         continue;
 583                                 atomic_set(&group->head.users,
 584                                            TOMOYO_GC_IN_PROGRESS);
 585                                 tomoyo_try_to_gc(TOMOYO_ID_GROUP,
 586                                                  &group->head.list);
 587                         }
 588                 }
 589         }
 590         for (i = 0; i < TOMOYO_MAX_HASH; i++) {
 591                 struct list_head *list = &tomoyo_name_list[i];
 592                 struct tomoyo_shared_acl_head *ptr;
 593                 struct tomoyo_shared_acl_head *tmp;
 594 
 595                 list_for_each_entry_safe(ptr, tmp, list, list) {
 596                         if (atomic_read(&ptr->users) > 0)
 597                                 continue;
 598                         atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
 599                         tomoyo_try_to_gc(TOMOYO_ID_NAME, &ptr->list);
 600                 }
 601         }
 602         mutex_unlock(&tomoyo_policy_lock);
 603 }
 604 
 605 /**
 606  * tomoyo_gc_thread - Garbage collector thread function.
 607  *
 608  * @unused: Unused.
 609  *
 610  * Returns 0.
 611  */
 612 static int tomoyo_gc_thread(void *unused)
 613 {
 614         /* Garbage collector thread is exclusive. */
 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_list_lock);
 625                 list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list,
 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_list_lock);
 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/kernel/security/tomoyo/ users.
 644  *
 645  * @head:        Pointer to "struct tomoyo_io_buffer".
 646  * @is_register: True if register, false if unregister.
 647  *
 648  * Returns nothing.
 649  */
 650 void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register)
 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_io_buffer_list);
 658         } else {
 659                 is_write = head->write_buf != NULL;
 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_lock);
 668         if (is_write)
 669                 kthread_run(tomoyo_gc_thread, NULL, "GC for TOMOYO");
 670 }

/* [<][>][^][v][top][bottom][index][help] */