linux/security/tomoyo/group.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * security/tomoyo/group.c
   4 *
   5 * Copyright (C) 2005-2011  NTT DATA CORPORATION
   6 */
   7
   8#include <linux/slab.h>
   9#include <linux/rculist.h>
  10
  11#include "common.h"
  12
  13/**
  14 * tomoyo_same_path_group - Check for duplicated "struct tomoyo_path_group" entry.
  15 *
  16 * @a: Pointer to "struct tomoyo_acl_head".
  17 * @b: Pointer to "struct tomoyo_acl_head".
  18 *
  19 * Returns true if @a == @b, false otherwise.
  20 */
  21static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
  22                                   const struct tomoyo_acl_head *b)
  23{
  24        return container_of(a, struct tomoyo_path_group, head)->member_name ==
  25                container_of(b, struct tomoyo_path_group, head)->member_name;
  26}
  27
  28/**
  29 * tomoyo_same_number_group - Check for duplicated "struct tomoyo_number_group" entry.
  30 *
  31 * @a: Pointer to "struct tomoyo_acl_head".
  32 * @b: Pointer to "struct tomoyo_acl_head".
  33 *
  34 * Returns true if @a == @b, false otherwise.
  35 */
  36static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
  37                                     const struct tomoyo_acl_head *b)
  38{
  39        return !memcmp(&container_of(a, struct tomoyo_number_group, head)
  40                       ->number,
  41                       &container_of(b, struct tomoyo_number_group, head)
  42                       ->number,
  43                       sizeof(container_of(a, struct tomoyo_number_group, head)
  44                              ->number));
  45}
  46
  47/**
  48 * tomoyo_same_address_group - Check for duplicated "struct tomoyo_address_group" entry.
  49 *
  50 * @a: Pointer to "struct tomoyo_acl_head".
  51 * @b: Pointer to "struct tomoyo_acl_head".
  52 *
  53 * Returns true if @a == @b, false otherwise.
  54 */
  55static bool tomoyo_same_address_group(const struct tomoyo_acl_head *a,
  56                                      const struct tomoyo_acl_head *b)
  57{
  58        const struct tomoyo_address_group *p1 = container_of(a, typeof(*p1),
  59                                                             head);
  60        const struct tomoyo_address_group *p2 = container_of(b, typeof(*p2),
  61                                                             head);
  62
  63        return tomoyo_same_ipaddr_union(&p1->address, &p2->address);
  64}
  65
  66/**
  67 * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group"/"struct tomoyo_address_group" list.
  68 *
  69 * @param: Pointer to "struct tomoyo_acl_param".
  70 * @type:  Type of this group.
  71 *
  72 * Returns 0 on success, negative value otherwise.
  73 */
  74int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type)
  75{
  76        struct tomoyo_group *group = tomoyo_get_group(param, type);
  77        int error = -EINVAL;
  78        if (!group)
  79                return -ENOMEM;
  80        param->list = &group->member_list;
  81        if (type == TOMOYO_PATH_GROUP) {
  82                struct tomoyo_path_group e = { };
  83                e.member_name = tomoyo_get_name(tomoyo_read_token(param));
  84                if (!e.member_name) {
  85                        error = -ENOMEM;
  86                        goto out;
  87                }
  88                error = tomoyo_update_policy(&e.head, sizeof(e), param,
  89                                          tomoyo_same_path_group);
  90                tomoyo_put_name(e.member_name);
  91        } else if (type == TOMOYO_NUMBER_GROUP) {
  92                struct tomoyo_number_group e = { };
  93                if (param->data[0] == '@' ||
  94                    !tomoyo_parse_number_union(param, &e.number))
  95                        goto out;
  96                error = tomoyo_update_policy(&e.head, sizeof(e), param,
  97                                          tomoyo_same_number_group);
  98                /*
  99                 * tomoyo_put_number_union() is not needed because
 100                 * param->data[0] != '@'.
 101                 */
 102        } else {
 103                struct tomoyo_address_group e = { };
 104
 105                if (param->data[0] == '@' ||
 106                    !tomoyo_parse_ipaddr_union(param, &e.address))
 107                        goto out;
 108                error = tomoyo_update_policy(&e.head, sizeof(e), param,
 109                                             tomoyo_same_address_group);
 110        }
 111out:
 112        tomoyo_put_group(group);
 113        return error;
 114}
 115
 116/**
 117 * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group.
 118 *
 119 * @pathname: The name of pathname.
 120 * @group:    Pointer to "struct tomoyo_path_group".
 121 *
 122 * Returns matched member's pathname if @pathname matches pathnames in @group,
 123 * NULL otherwise.
 124 *
 125 * Caller holds tomoyo_read_lock().
 126 */
 127const struct tomoyo_path_info *
 128tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
 129                          const struct tomoyo_group *group)
 130{
 131        struct tomoyo_path_group *member;
 132        list_for_each_entry_rcu(member, &group->member_list, head.list) {
 133                if (member->head.is_deleted)
 134                        continue;
 135                if (!tomoyo_path_matches_pattern(pathname, member->member_name))
 136                        continue;
 137                return member->member_name;
 138        }
 139        return NULL;
 140}
 141
 142/**
 143 * tomoyo_number_matches_group - Check whether the given number matches members of the given number group.
 144 *
 145 * @min:   Min number.
 146 * @max:   Max number.
 147 * @group: Pointer to "struct tomoyo_number_group".
 148 *
 149 * Returns true if @min and @max partially overlaps @group, false otherwise.
 150 *
 151 * Caller holds tomoyo_read_lock().
 152 */
 153bool tomoyo_number_matches_group(const unsigned long min,
 154                                 const unsigned long max,
 155                                 const struct tomoyo_group *group)
 156{
 157        struct tomoyo_number_group *member;
 158        bool matched = false;
 159        list_for_each_entry_rcu(member, &group->member_list, head.list) {
 160                if (member->head.is_deleted)
 161                        continue;
 162                if (min > member->number.values[1] ||
 163                    max < member->number.values[0])
 164                        continue;
 165                matched = true;
 166                break;
 167        }
 168        return matched;
 169}
 170
 171/**
 172 * tomoyo_address_matches_group - Check whether the given address matches members of the given address group.
 173 *
 174 * @is_ipv6: True if @address is an IPv6 address.
 175 * @address: An IPv4 or IPv6 address.
 176 * @group:   Pointer to "struct tomoyo_address_group".
 177 *
 178 * Returns true if @address matches addresses in @group group, false otherwise.
 179 *
 180 * Caller holds tomoyo_read_lock().
 181 */
 182bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address,
 183                                  const struct tomoyo_group *group)
 184{
 185        struct tomoyo_address_group *member;
 186        bool matched = false;
 187        const u8 size = is_ipv6 ? 16 : 4;
 188
 189        list_for_each_entry_rcu(member, &group->member_list, head.list) {
 190                if (member->head.is_deleted)
 191                        continue;
 192                if (member->address.is_ipv6 != is_ipv6)
 193                        continue;
 194                if (memcmp(&member->address.ip[0], address, size) > 0 ||
 195                    memcmp(address, &member->address.ip[1], size) > 0)
 196                        continue;
 197                matched = true;
 198                break;
 199        }
 200        return matched;
 201}
 202