linux/security/tomoyo/gc.c
<<
>>
Prefs
   1/*
   2 * security/tomoyo/gc.c
   3 *
   4 * Copyright (C) 2005-2011  NTT DATA CORPORATION
   5 */
   6
   7#include "common.h"
   8#include <linux/kthread.h>
   9#include <linux/slab.h>
  10
  11/* The list for "struct tomoyo_io_buffer". */
  12static LIST_HEAD(tomoyo_io_buffer_list);
  13/* Lock for protecting tomoyo_io_buffer_list. */
  14static DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock);
  15
  16/* Size of an element. */
  17static const u8 tomoyo_element_size[TOMOYO_MAX_POLICY] = {
  18        [TOMOYO_ID_GROUP] = sizeof(struct tomoyo_group),
  19        [TOMOYO_ID_PATH_GROUP] = sizeof(struct tomoyo_path_group),
  20        [TOMOYO_ID_NUMBER_GROUP] = sizeof(struct tomoyo_number_group),
  21        [TOMOYO_ID_AGGREGATOR] = sizeof(struct tomoyo_aggregator),
  22        [TOMOYO_ID_TRANSITION_CONTROL] =
  23        sizeof(struct tomoyo_transition_control),
  24        [TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager),
  25        /* [TOMOYO_ID_CONDITION] = "struct tomoyo_condition"->size, */
  26        /* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */
  27        /* [TOMOYO_ID_ACL] =
  28           tomoyo_acl_size["struct tomoyo_acl_info"->type], */
  29        [TOMOYO_ID_DOMAIN] = sizeof(struct tomoyo_domain_info),
  30};
  31
  32/* Size of a domain ACL element. */
  33static const u8 tomoyo_acl_size[] = {
  34        [TOMOYO_TYPE_PATH_ACL] = sizeof(struct tomoyo_path_acl),
  35        [TOMOYO_TYPE_PATH2_ACL] = sizeof(struct tomoyo_path2_acl),
  36        [TOMOYO_TYPE_PATH_NUMBER_ACL] = sizeof(struct tomoyo_path_number_acl),
  37        [TOMOYO_TYPE_MKDEV_ACL] = sizeof(struct tomoyo_mkdev_acl),
  38        [TOMOYO_TYPE_MOUNT_ACL] = sizeof(struct tomoyo_mount_acl),
  39};
  40
  41/**
  42 * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not.
  43 *
  44 * @element: Pointer to "struct list_head".
  45 *
  46 * Returns true if @element is used by /sys/kernel/security/tomoyo/ users,
  47 * false otherwise.
  48 */
  49static bool tomoyo_struct_used_by_io_buffer(const struct list_head *element)
  50{
  51        struct tomoyo_io_buffer *head;
  52        bool in_use = false;
  53
  54        spin_lock(&tomoyo_io_buffer_list_lock);
  55        list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
  56                head->users++;
  57                spin_unlock(&tomoyo_io_buffer_list_lock);
  58                if (mutex_lock_interruptible(&head->io_sem)) {
  59                        in_use = true;
  60                        goto out;
  61                }
  62                if (head->r.domain == element || head->r.group == element ||
  63                    head->r.acl == element || &head->w.domain->list == element)
  64                        in_use = true;
  65                mutex_unlock(&head->io_sem);
  66out:
  67                spin_lock(&tomoyo_io_buffer_list_lock);
  68                head->users--;
  69                if (in_use)
  70                        break;
  71        }
  72        spin_unlock(&tomoyo_io_buffer_list_lock);
  73        return in_use;
  74}
  75
  76/**
  77 * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not.
  78 *
  79 * @string: String to check.
  80 * @size:   Memory allocated for @string .
  81 *
  82 * Returns true if @string is used by /sys/kernel/security/tomoyo/ users,
  83 * false otherwise.
  84 */
  85static bool tomoyo_name_used_by_io_buffer(const char *string,
  86                                          const size_t size)
  87{
  88        struct tomoyo_io_buffer *head;
  89        bool in_use = false;
  90
  91        spin_lock(&tomoyo_io_buffer_list_lock);
  92        list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
  93                int i;
  94                head->users++;
  95                spin_unlock(&tomoyo_io_buffer_list_lock);
  96                if (mutex_lock_interruptible(&head->io_sem)) {
  97                        in_use = true;
  98                        goto out;
  99                }
 100                for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) {
 101                        const char *w = head->r.w[i];
 102                        if (w < string || w > string + size)
 103                                continue;
 104                        in_use = true;
 105                        break;
 106                }
 107                mutex_unlock(&head->io_sem);
 108out:
 109                spin_lock(&tomoyo_io_buffer_list_lock);
 110                head->users--;
 111                if (in_use)
 112                        break;
 113        }
 114        spin_unlock(&tomoyo_io_buffer_list_lock);
 115        return in_use;
 116}
 117
 118/* Structure for garbage collection. */
 119struct tomoyo_gc {
 120        struct list_head list;
 121        enum tomoyo_policy_id type;
 122        size_t size;
 123        struct list_head *element;
 124};
 125/* List of entries to be deleted. */
 126static LIST_HEAD(tomoyo_gc_list);
 127/* Length of tomoyo_gc_list. */
 128static int tomoyo_gc_list_len;
 129
 130/**
 131 * tomoyo_add_to_gc - Add an entry to to be deleted list.
 132 *
 133 * @type:    One of values in "enum tomoyo_policy_id".
 134 * @element: Pointer to "struct list_head".
 135 *
 136 * Returns true on success, false otherwise.
 137 *
 138 * Caller holds tomoyo_policy_lock mutex.
 139 *
 140 * Adding an entry needs kmalloc(). Thus, if we try to add thousands of
 141 * entries at once, it will take too long time. Thus, do not add more than 128
 142 * entries per a scan. But to be able to handle worst case where all entries
 143 * are in-use, we accept one more entry per a scan.
 144 *
 145 * If we use singly linked list using "struct list_head"->prev (which is
 146 * LIST_POISON2), we can avoid kmalloc().
 147 */
 148static bool tomoyo_add_to_gc(const int type, struct list_head *element)
 149{
 150        struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 151        if (!entry)
 152                return false;
 153        entry->type = type;
 154        if (type == TOMOYO_ID_ACL)
 155                entry->size = tomoyo_acl_size[
 156                              container_of(element,
 157                                           typeof(struct tomoyo_acl_info),
 158                                           list)->type];
 159        else if (type == TOMOYO_ID_NAME)
 160                entry->size = strlen(container_of(element,
 161                                                  typeof(struct tomoyo_name),
 162                                                  head.list)->entry.name) + 1;
 163        else if (type == TOMOYO_ID_CONDITION)
 164                entry->size =
 165                        container_of(element, typeof(struct tomoyo_condition),
 166                                     head.list)->size;
 167        else
 168                entry->size = tomoyo_element_size[type];
 169        entry->element = element;
 170        list_add(&entry->list, &tomoyo_gc_list);
 171        list_del_rcu(element);
 172        return tomoyo_gc_list_len++ < 128;
 173}
 174
 175/**
 176 * tomoyo_element_linked_by_gc - Validate next element of an entry.
 177 *
 178 * @element: Pointer to an element.
 179 * @size:    Size of @element in byte.
 180 *
 181 * Returns true if @element is linked by other elements in the garbage
 182 * collector's queue, false otherwise.
 183 */
 184static bool tomoyo_element_linked_by_gc(const u8 *element, const size_t size)
 185{
 186        struct tomoyo_gc *p;
 187        list_for_each_entry(p, &tomoyo_gc_list, list) {
 188                const u8 *ptr = (const u8 *) p->element->next;
 189                if (ptr < element || element + size < ptr)
 190                        continue;
 191                return true;
 192        }
 193        return false;
 194}
 195
 196/**
 197 * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
 198 *
 199 * @element: Pointer to "struct list_head".
 200 *
 201 * Returns nothing.
 202 */
 203static void tomoyo_del_transition_control(struct list_head *element)
 204{
 205        struct tomoyo_transition_control *ptr =
 206                container_of(element, typeof(*ptr), head.list);
 207        tomoyo_put_name(ptr->domainname);
 208        tomoyo_put_name(ptr->program);
 209}
 210
 211/**
 212 * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator".
 213 *
 214 * @element: Pointer to "struct list_head".
 215 *
 216 * Returns nothing.
 217 */
 218static void tomoyo_del_aggregator(struct list_head *element)
 219{
 220        struct tomoyo_aggregator *ptr =
 221                container_of(element, typeof(*ptr), head.list);
 222        tomoyo_put_name(ptr->original_name);
 223        tomoyo_put_name(ptr->aggregated_name);
 224}
 225
 226/**
 227 * tomoyo_del_manager - Delete members in "struct tomoyo_manager".
 228 *
 229 * @element: Pointer to "struct list_head".
 230 *
 231 * Returns nothing.
 232 */
 233static void tomoyo_del_manager(struct list_head *element)
 234{
 235        struct tomoyo_manager *ptr =
 236                container_of(element, typeof(*ptr), head.list);
 237        tomoyo_put_name(ptr->manager);
 238}
 239
 240/**
 241 * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info".
 242 *
 243 * @element: Pointer to "struct list_head".
 244 *
 245 * Returns nothing.
 246 */
 247static void tomoyo_del_acl(struct list_head *element)
 248{
 249        struct tomoyo_acl_info *acl =
 250                container_of(element, typeof(*acl), list);
 251        tomoyo_put_condition(acl->cond);
 252        switch (acl->type) {
 253        case TOMOYO_TYPE_PATH_ACL:
 254                {
 255                        struct tomoyo_path_acl *entry
 256                                = container_of(acl, typeof(*entry), head);
 257                        tomoyo_put_name_union(&entry->name);
 258                }
 259                break;
 260        case TOMOYO_TYPE_PATH2_ACL:
 261                {
 262                        struct tomoyo_path2_acl *entry
 263                                = container_of(acl, typeof(*entry), head);
 264                        tomoyo_put_name_union(&entry->name1);
 265                        tomoyo_put_name_union(&entry->name2);
 266                }
 267                break;
 268        case TOMOYO_TYPE_PATH_NUMBER_ACL:
 269                {
 270                        struct tomoyo_path_number_acl *entry
 271                                = container_of(acl, typeof(*entry), head);
 272                        tomoyo_put_name_union(&entry->name);
 273                        tomoyo_put_number_union(&entry->number);
 274                }
 275                break;
 276        case TOMOYO_TYPE_MKDEV_ACL:
 277                {
 278                        struct tomoyo_mkdev_acl *entry
 279                                = container_of(acl, typeof(*entry), head);
 280                        tomoyo_put_name_union(&entry->name);
 281                        tomoyo_put_number_union(&entry->mode);
 282                        tomoyo_put_number_union(&entry->major);
 283                        tomoyo_put_number_union(&entry->minor);
 284                }
 285                break;
 286        case TOMOYO_TYPE_MOUNT_ACL:
 287                {
 288                        struct tomoyo_mount_acl *entry
 289                                = container_of(acl, typeof(*entry), head);
 290                        tomoyo_put_name_union(&entry->dev_name);
 291                        tomoyo_put_name_union(&entry->dir_name);
 292                        tomoyo_put_name_union(&entry->fs_type);
 293                        tomoyo_put_number_union(&entry->flags);
 294                }
 295                break;
 296        }
 297}
 298
 299/**
 300 * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info".
 301 *
 302 * @element: Pointer to "struct list_head".
 303 *
 304 * Returns true if deleted, false otherwise.
 305 */
 306static bool tomoyo_del_domain(struct list_head *element)
 307{
 308        struct tomoyo_domain_info *domain =
 309                container_of(element, typeof(*domain), list);
 310        struct tomoyo_acl_info *acl;
 311        struct tomoyo_acl_info *tmp;
 312        /*
 313         * Since we don't protect whole execve() operation using SRCU,
 314         * we need to recheck domain->users at this point.
 315         *
 316         * (1) Reader starts SRCU section upon execve().
 317         * (2) Reader traverses tomoyo_domain_list and finds this domain.
 318         * (3) Writer marks this domain as deleted.
 319         * (4) Garbage collector removes this domain from tomoyo_domain_list
 320         *     because this domain is marked as deleted and used by nobody.
 321         * (5) Reader saves reference to this domain into
 322         *     "struct linux_binprm"->cred->security .
 323         * (6) Reader finishes SRCU section, although execve() operation has
 324         *     not finished yet.
 325         * (7) Garbage collector waits for SRCU synchronization.
 326         * (8) Garbage collector kfree() this domain because this domain is
 327         *     used by nobody.
 328         * (9) Reader finishes execve() operation and restores this domain from
 329         *     "struct linux_binprm"->cred->security.
 330         *
 331         * By updating domain->users at (5), we can solve this race problem
 332         * by rechecking domain->users at (8).
 333         */
 334        if (atomic_read(&domain->users))
 335                return false;
 336        list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
 337                tomoyo_del_acl(&acl->list);
 338                tomoyo_memory_free(acl);
 339        }
 340        tomoyo_put_name(domain->domainname);
 341        return true;
 342}
 343
 344/**
 345 * tomoyo_del_condition - Delete members in "struct tomoyo_condition".
 346 *
 347 * @element: Pointer to "struct list_head".
 348 *
 349 * Returns nothing.
 350 */
 351void tomoyo_del_condition(struct list_head *element)
 352{
 353        struct tomoyo_condition *cond = container_of(element, typeof(*cond),
 354                                                     head.list);
 355        const u16 condc = cond->condc;
 356        const u16 numbers_count = cond->numbers_count;
 357        const u16 names_count = cond->names_count;
 358        const u16 argc = cond->argc;
 359        const u16 envc = cond->envc;
 360        unsigned int i;
 361        const struct tomoyo_condition_element *condp
 362                = (const struct tomoyo_condition_element *) (cond + 1);
 363        struct tomoyo_number_union *numbers_p
 364                = (struct tomoyo_number_union *) (condp + condc);
 365        struct tomoyo_name_union *names_p
 366                = (struct tomoyo_name_union *) (numbers_p + numbers_count);
 367        const struct tomoyo_argv *argv
 368                = (const struct tomoyo_argv *) (names_p + names_count);
 369        const struct tomoyo_envp *envp
 370                = (const struct tomoyo_envp *) (argv + argc);
 371        for (i = 0; i < numbers_count; i++)
 372                tomoyo_put_number_union(numbers_p++);
 373        for (i = 0; i < names_count; i++)
 374                tomoyo_put_name_union(names_p++);
 375        for (i = 0; i < argc; argv++, i++)
 376                tomoyo_put_name(argv->value);
 377        for (i = 0; i < envc; envp++, i++) {
 378                tomoyo_put_name(envp->name);
 379                tomoyo_put_name(envp->value);
 380        }
 381}
 382
 383/**
 384 * tomoyo_del_name - Delete members in "struct tomoyo_name".
 385 *
 386 * @element: Pointer to "struct list_head".
 387 *
 388 * Returns nothing.
 389 */
 390static void tomoyo_del_name(struct list_head *element)
 391{
 392        const struct tomoyo_name *ptr =
 393                container_of(element, typeof(*ptr), head.list);
 394}
 395
 396/**
 397 * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group".
 398 *
 399 * @element: Pointer to "struct list_head".
 400 *
 401 * Returns nothing.
 402 */
 403static void tomoyo_del_path_group(struct list_head *element)
 404{
 405        struct tomoyo_path_group *member =
 406                container_of(element, typeof(*member), head.list);
 407        tomoyo_put_name(member->member_name);
 408}
 409
 410/**
 411 * tomoyo_del_group - Delete "struct tomoyo_group".
 412 *
 413 * @element: Pointer to "struct list_head".
 414 *
 415 * Returns nothing.
 416 */
 417static void tomoyo_del_group(struct list_head *element)
 418{
 419        struct tomoyo_group *group =
 420                container_of(element, typeof(*group), head.list);
 421        tomoyo_put_name(group->group_name);
 422}
 423
 424/**
 425 * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
 426 *
 427 * @element: Pointer to "struct list_head".
 428 *
 429 * Returns nothing.
 430 */
 431static void tomoyo_del_number_group(struct list_head *element)
 432{
 433        struct tomoyo_number_group *member =
 434                container_of(element, typeof(*member), head.list);
 435}
 436
 437/**
 438 * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head".
 439 *
 440 * @id:          One of values in "enum tomoyo_policy_id".
 441 * @member_list: Pointer to "struct list_head".
 442 *
 443 * Returns true if some elements are deleted, false otherwise.
 444 */
 445static bool tomoyo_collect_member(const enum tomoyo_policy_id id,
 446                                  struct list_head *member_list)
 447{
 448        struct tomoyo_acl_head *member;
 449        list_for_each_entry(member, member_list, list) {
 450                if (!member->is_deleted)
 451                        continue;
 452                if (!tomoyo_add_to_gc(id, &member->list))
 453                        return false;
 454        }
 455        return true;
 456}
 457
 458/**
 459 * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info".
 460 *
 461 * @list: Pointer to "struct list_head".
 462 *
 463 * Returns true if some elements are deleted, false otherwise.
 464 */
 465static bool tomoyo_collect_acl(struct list_head *list)
 466{
 467        struct tomoyo_acl_info *acl;
 468        list_for_each_entry(acl, list, list) {
 469                if (!acl->is_deleted)
 470                        continue;
 471                if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list))
 472                        return false;
 473        }
 474        return true;
 475}
 476
 477/**
 478 * tomoyo_collect_entry - Scan lists for deleted elements.
 479 *
 480 * Returns nothing.
 481 */
 482static void tomoyo_collect_entry(void)
 483{
 484        int i;
 485        enum tomoyo_policy_id id;
 486        struct tomoyo_policy_namespace *ns;
 487        int idx;
 488        if (mutex_lock_interruptible(&tomoyo_policy_lock))
 489                return;
 490        idx = tomoyo_read_lock();
 491        {
 492                struct tomoyo_domain_info *domain;
 493                list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
 494                        if (!tomoyo_collect_acl(&domain->acl_info_list))
 495                                goto unlock;
 496                        if (!domain->is_deleted || atomic_read(&domain->users))
 497                                continue;
 498                        /*
 499                         * Nobody is referring this domain. But somebody may
 500                         * refer this domain after successful execve().
 501                         * We recheck domain->users after SRCU synchronization.
 502                         */
 503                        if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list))
 504                                goto unlock;
 505                }
 506        }
 507        list_for_each_entry_rcu(ns, &tomoyo_namespace_list, namespace_list) {
 508                for (id = 0; id < TOMOYO_MAX_POLICY; id++)
 509                        if (!tomoyo_collect_member(id, &ns->policy_list[id]))
 510                                goto unlock;
 511                for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
 512                        if (!tomoyo_collect_acl(&ns->acl_group[i]))
 513                                goto unlock;
 514                for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
 515                        struct list_head *list = &ns->group_list[i];
 516                        struct tomoyo_group *group;
 517                        switch (i) {
 518                        case 0:
 519                                id = TOMOYO_ID_PATH_GROUP;
 520                                break;
 521                        default:
 522                                id = TOMOYO_ID_NUMBER_GROUP;
 523                                break;
 524                        }
 525                        list_for_each_entry(group, list, head.list) {
 526                                if (!tomoyo_collect_member
 527                                    (id, &group->member_list))
 528                                        goto unlock;
 529                                if (!list_empty(&group->member_list) ||
 530                                    atomic_read(&group->head.users))
 531                                        continue;
 532                                if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP,
 533                                                      &group->head.list))
 534                                        goto unlock;
 535                        }
 536                }
 537        }
 538        id = TOMOYO_ID_CONDITION;
 539        for (i = 0; i < TOMOYO_MAX_HASH + 1; i++) {
 540                struct list_head *list = !i ?
 541                        &tomoyo_condition_list : &tomoyo_name_list[i - 1];
 542                struct tomoyo_shared_acl_head *ptr;
 543                list_for_each_entry(ptr, list, list) {
 544                        if (atomic_read(&ptr->users))
 545                                continue;
 546                        if (!tomoyo_add_to_gc(id, &ptr->list))
 547                                goto unlock;
 548                }
 549                id = TOMOYO_ID_NAME;
 550        }
 551unlock:
 552        tomoyo_read_unlock(idx);
 553        mutex_unlock(&tomoyo_policy_lock);
 554}
 555
 556/**
 557 * tomoyo_kfree_entry - Delete entries in tomoyo_gc_list.
 558 *
 559 * Returns true if some entries were kfree()d, false otherwise.
 560 */
 561static bool tomoyo_kfree_entry(void)
 562{
 563        struct tomoyo_gc *p;
 564        struct tomoyo_gc *tmp;
 565        bool result = false;
 566
 567        list_for_each_entry_safe(p, tmp, &tomoyo_gc_list, list) {
 568                struct list_head *element = p->element;
 569
 570                /*
 571                 * list_del_rcu() in tomoyo_add_to_gc() guarantees that the
 572                 * list element became no longer reachable from the list which
 573                 * the element was originally on (e.g. tomoyo_domain_list).
 574                 * Also, synchronize_srcu() in tomoyo_gc_thread() guarantees
 575                 * that the list element became no longer referenced by syscall
 576                 * users.
 577                 *
 578                 * However, there are three users which may still be using the
 579                 * list element. We need to defer until all of these users
 580                 * forget the list element.
 581                 *
 582                 * Firstly, defer until "struct tomoyo_io_buffer"->r.{domain,
 583                 * group,acl} and "struct tomoyo_io_buffer"->w.domain forget
 584                 * the list element.
 585                 */
 586                if (tomoyo_struct_used_by_io_buffer(element))
 587                        continue;
 588                /*
 589                 * Secondly, defer until all other elements in the
 590                 * tomoyo_gc_list list forget the list element.
 591                 */
 592                if (tomoyo_element_linked_by_gc((const u8 *) element, p->size))
 593                        continue;
 594                switch (p->type) {
 595                case TOMOYO_ID_TRANSITION_CONTROL:
 596                        tomoyo_del_transition_control(element);
 597                        break;
 598                case TOMOYO_ID_AGGREGATOR:
 599                        tomoyo_del_aggregator(element);
 600                        break;
 601                case TOMOYO_ID_MANAGER:
 602                        tomoyo_del_manager(element);
 603                        break;
 604                case TOMOYO_ID_CONDITION:
 605                        tomoyo_del_condition(element);
 606                        break;
 607                case TOMOYO_ID_NAME:
 608                        /*
 609                         * Thirdly, defer until all "struct tomoyo_io_buffer"
 610                         * ->r.w[] forget the list element.
 611                         */
 612                        if (tomoyo_name_used_by_io_buffer(
 613                            container_of(element, typeof(struct tomoyo_name),
 614                                         head.list)->entry.name, p->size))
 615                                continue;
 616                        tomoyo_del_name(element);
 617                        break;
 618                case TOMOYO_ID_ACL:
 619                        tomoyo_del_acl(element);
 620                        break;
 621                case TOMOYO_ID_DOMAIN:
 622                        if (!tomoyo_del_domain(element))
 623                                continue;
 624                        break;
 625                case TOMOYO_ID_PATH_GROUP:
 626                        tomoyo_del_path_group(element);
 627                        break;
 628                case TOMOYO_ID_GROUP:
 629                        tomoyo_del_group(element);
 630                        break;
 631                case TOMOYO_ID_NUMBER_GROUP:
 632                        tomoyo_del_number_group(element);
 633                        break;
 634                case TOMOYO_MAX_POLICY:
 635                        break;
 636                }
 637                tomoyo_memory_free(element);
 638                list_del(&p->list);
 639                kfree(p);
 640                tomoyo_gc_list_len--;
 641                result = true;
 642        }
 643        return result;
 644}
 645
 646/**
 647 * tomoyo_gc_thread - Garbage collector thread function.
 648 *
 649 * @unused: Unused.
 650 *
 651 * In case OOM-killer choose this thread for termination, we create this thread
 652 * as a short live thread whenever /sys/kernel/security/tomoyo/ interface was
 653 * close()d.
 654 *
 655 * Returns 0.
 656 */
 657static int tomoyo_gc_thread(void *unused)
 658{
 659        /* Garbage collector thread is exclusive. */
 660        static DEFINE_MUTEX(tomoyo_gc_mutex);
 661        if (!mutex_trylock(&tomoyo_gc_mutex))
 662                goto out;
 663        daemonize("GC for TOMOYO");
 664        do {
 665                tomoyo_collect_entry();
 666                if (list_empty(&tomoyo_gc_list))
 667                        break;
 668                synchronize_srcu(&tomoyo_ss);
 669        } while (tomoyo_kfree_entry());
 670        {
 671                struct tomoyo_io_buffer *head;
 672                struct tomoyo_io_buffer *tmp;
 673
 674                spin_lock(&tomoyo_io_buffer_list_lock);
 675                list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list,
 676                                         list) {
 677                        if (head->users)
 678                                continue;
 679                        list_del(&head->list);
 680                        kfree(head->read_buf);
 681                        kfree(head->write_buf);
 682                        kfree(head);
 683                }
 684                spin_unlock(&tomoyo_io_buffer_list_lock);
 685        }
 686        mutex_unlock(&tomoyo_gc_mutex);
 687out:
 688        /* This acts as do_exit(0). */
 689        return 0;
 690}
 691
 692/**
 693 * tomoyo_notify_gc - Register/unregister /sys/kernel/security/tomoyo/ users.
 694 *
 695 * @head:        Pointer to "struct tomoyo_io_buffer".
 696 * @is_register: True if register, false if unregister.
 697 *
 698 * Returns nothing.
 699 */
 700void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register)
 701{
 702        bool is_write = false;
 703
 704        spin_lock(&tomoyo_io_buffer_list_lock);
 705        if (is_register) {
 706                head->users = 1;
 707                list_add(&head->list, &tomoyo_io_buffer_list);
 708        } else {
 709                is_write = head->write_buf != NULL;
 710                if (!--head->users) {
 711                        list_del(&head->list);
 712                        kfree(head->read_buf);
 713                        kfree(head->write_buf);
 714                        kfree(head);
 715                }
 716        }
 717        spin_unlock(&tomoyo_io_buffer_list_lock);
 718        if (is_write) {
 719                struct task_struct *task = kthread_create(tomoyo_gc_thread,
 720                                                          NULL,
 721                                                          "GC for TOMOYO");
 722                if (!IS_ERR(task))
 723                        wake_up_process(task);
 724        }
 725}
 726