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