linux/security/tomoyo/gc.c
<<
>>
Prefs
   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 */
  21static 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". */
  28static LIST_HEAD(tomoyo_io_buffer_list);
  29/* Lock for protecting tomoyo_io_buffer_list. */
  30static 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 */
  40static 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 */
  71static 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 */
 109static 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 */
 125static 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 */
 141static 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 */
 156static 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 */
 251static 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 */
 277void 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 */
 317static 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 */
 329static 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 */
 344static 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 */
 359static 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 */
 371static 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 */
 386static 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;
 464reinject:
 465        /*
 466         * We can safely reinject this element here because
 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 */
 485static 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 */
 506static 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 */
 524static 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 */
 612static 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);
 637out:
 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 */
 650void 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}
 671