Commit 7c2ea22e3c5463627ca98924cd65cb9e480dc29c

Authored by Tetsuo Handa
Committed by James Morris
1 parent 31845e8c6d

TOMOYO: Merge path_group and number_group.

Use common code for "path_group" and "number_group".

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>

Showing 9 changed files with 199 additions and 282 deletions Side-by-side Diff

security/tomoyo/Makefile
1   -obj-y = common.o domain.o file.o gc.o load_policy.o memory.o mount.o number_group.o path_group.o realpath.o securityfs_if.o tomoyo.o util.o
  1 +obj-y = common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o
security/tomoyo/common.c
... ... @@ -1186,9 +1186,9 @@
1186 1186 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE))
1187 1187 return tomoyo_write_no_rewrite_policy(data, is_delete);
1188 1188 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP))
1189   - return tomoyo_write_path_group_policy(data, is_delete);
  1189 + return tomoyo_write_group(data, is_delete, TOMOYO_PATH_GROUP);
1190 1190 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NUMBER_GROUP))
1191   - return tomoyo_write_number_group_policy(data, is_delete);
  1191 + return tomoyo_write_group(data, is_delete, TOMOYO_NUMBER_GROUP);
1192 1192 return -EINVAL;
1193 1193 }
1194 1194  
security/tomoyo/common.h
... ... @@ -838,12 +838,10 @@
838 838 int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete);
839 839 /* Create "file_pattern" entry in exception policy. */
840 840 int tomoyo_write_pattern_policy(char *data, const bool is_delete);
841   -/* Create "path_group" entry in exception policy. */
842   -int tomoyo_write_path_group_policy(char *data, const bool is_delete);
  841 +/* Create "path_group"/"number_group" entry in exception policy. */
  842 +int tomoyo_write_group(char *data, const bool is_delete, const u8 type);
843 843 int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
844 844 __attribute__ ((format(printf, 2, 3)));
845   -/* Create "number_group" entry in exception policy. */
846   -int tomoyo_write_number_group_policy(char *data, const bool is_delete);
847 845 /* Find a domain by the given name. */
848 846 struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
849 847 /* Find or create a domain by the given name. */
... ... @@ -851,9 +849,10 @@
851 849 domainname,
852 850 const u8 profile);
853 851 struct tomoyo_profile *tomoyo_profile(const u8 profile);
854   -/* Allocate memory for "struct tomoyo_path_group". */
855   -struct tomoyo_group *tomoyo_get_path_group(const char *group_name);
856   -struct tomoyo_group *tomoyo_get_number_group(const char *group_name);
  852 +/*
  853 + * Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
  854 + */
  855 +struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 type);
857 856  
858 857 /* Check mode for specified functionality. */
859 858 unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
security/tomoyo/gc.c
... ... @@ -266,33 +266,25 @@
266 266 goto unlock;
267 267 }
268 268 }
269   - {
  269 + for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
  270 + struct list_head *list = &tomoyo_group_list[i];
  271 + int id;
270 272 struct tomoyo_group *group;
271   - list_for_each_entry_rcu(group,
272   - &tomoyo_group_list[TOMOYO_PATH_GROUP],
273   - list) {
274   - tomoyo_collect_member(&group->member_list,
275   - TOMOYO_ID_PATH_GROUP);
276   - if (!list_empty(&group->member_list) ||
277   - atomic_read(&group->users))
278   - continue;
279   - if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP,
280   - &group->list))
281   - goto unlock;
  273 + switch (i) {
  274 + case 0:
  275 + id = TOMOYO_ID_PATH_GROUP;
  276 + break;
  277 + default:
  278 + id = TOMOYO_ID_NUMBER_GROUP;
  279 + break;
282 280 }
283   - }
284   - {
285   - struct tomoyo_group *group;
286   - list_for_each_entry_rcu(group,
287   - &tomoyo_group_list[TOMOYO_NUMBER_GROUP],
288   - list) {
289   - tomoyo_collect_member(&group->member_list,
290   - TOMOYO_ID_NUMBER_GROUP);
  281 + list_for_each_entry(group, list, list) {
  282 + if (!tomoyo_collect_member(&group->member_list, id))
  283 + goto unlock;
291 284 if (!list_empty(&group->member_list) ||
292 285 atomic_read(&group->users))
293 286 continue;
294   - if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP,
295   - &group->list))
  287 + if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list))
296 288 goto unlock;
297 289 }
298 290 }
security/tomoyo/group.c
  1 +/*
  2 + * security/tomoyo/group.c
  3 + *
  4 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
  5 + */
  6 +
  7 +#include <linux/slab.h>
  8 +#include "common.h"
  9 +
  10 +static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
  11 + const struct tomoyo_acl_head *b)
  12 +{
  13 + return container_of(a, struct tomoyo_path_group, head)->member_name ==
  14 + container_of(b, struct tomoyo_path_group, head)->member_name;
  15 +}
  16 +
  17 +static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
  18 + const struct tomoyo_acl_head *b)
  19 +{
  20 + return !memcmp(&container_of(a, struct tomoyo_number_group, head)
  21 + ->number,
  22 + &container_of(b, struct tomoyo_number_group, head)
  23 + ->number,
  24 + sizeof(container_of(a, struct tomoyo_number_group, head)
  25 + ->number));
  26 +}
  27 +
  28 +/**
  29 + * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list.
  30 + *
  31 + * @data: String to parse.
  32 + * @is_delete: True if it is a delete request.
  33 + * @type: Type of this group.
  34 + *
  35 + * Returns 0 on success, negative value otherwise.
  36 + */
  37 +int tomoyo_write_group(char *data, const bool is_delete, const u8 type)
  38 +{
  39 + struct tomoyo_group *group;
  40 + struct list_head *member;
  41 + char *w[2];
  42 + int error = -EINVAL;
  43 + if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
  44 + return -EINVAL;
  45 + group = tomoyo_get_group(w[0], type);
  46 + if (!group)
  47 + return -ENOMEM;
  48 + member = &group->member_list;
  49 + if (type == TOMOYO_PATH_GROUP) {
  50 + struct tomoyo_path_group e = { };
  51 + e.member_name = tomoyo_get_name(w[1]);
  52 + if (!e.member_name) {
  53 + error = -ENOMEM;
  54 + goto out;
  55 + }
  56 + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
  57 + member, tomoyo_same_path_group);
  58 + tomoyo_put_name(e.member_name);
  59 + } else if (type == TOMOYO_NUMBER_GROUP) {
  60 + struct tomoyo_number_group e = { };
  61 + if (w[1][0] == '@'
  62 + || !tomoyo_parse_number_union(w[1], &e.number)
  63 + || e.number.values[0] > e.number.values[1])
  64 + goto out;
  65 + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
  66 + member, tomoyo_same_number_group);
  67 + /*
  68 + * tomoyo_put_number_union() is not needed because
  69 + * w[1][0] != '@'.
  70 + */
  71 + }
  72 + out:
  73 + tomoyo_put_group(group);
  74 + return error;
  75 +}
  76 +
  77 +/**
  78 + * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group.
  79 + *
  80 + * @pathname: The name of pathname.
  81 + * @group: Pointer to "struct tomoyo_path_group".
  82 + *
  83 + * Returns true if @pathname matches pathnames in @group, false otherwise.
  84 + *
  85 + * Caller holds tomoyo_read_lock().
  86 + */
  87 +bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
  88 + const struct tomoyo_group *group)
  89 +{
  90 + struct tomoyo_path_group *member;
  91 + bool matched = false;
  92 + list_for_each_entry_rcu(member, &group->member_list, head.list) {
  93 + if (member->head.is_deleted)
  94 + continue;
  95 + if (!tomoyo_path_matches_pattern(pathname, member->member_name))
  96 + continue;
  97 + matched = true;
  98 + break;
  99 + }
  100 + return matched;
  101 +}
  102 +
  103 +/**
  104 + * tomoyo_number_matches_group - Check whether the given number matches members of the given number group.
  105 + *
  106 + * @min: Min number.
  107 + * @max: Max number.
  108 + * @group: Pointer to "struct tomoyo_number_group".
  109 + *
  110 + * Returns true if @min and @max partially overlaps @group, false otherwise.
  111 + *
  112 + * Caller holds tomoyo_read_lock().
  113 + */
  114 +bool tomoyo_number_matches_group(const unsigned long min,
  115 + const unsigned long max,
  116 + const struct tomoyo_group *group)
  117 +{
  118 + struct tomoyo_number_group *member;
  119 + bool matched = false;
  120 + list_for_each_entry_rcu(member, &group->member_list, head.list) {
  121 + if (member->head.is_deleted)
  122 + continue;
  123 + if (min > member->number.values[1] ||
  124 + max < member->number.values[0])
  125 + continue;
  126 + matched = true;
  127 + break;
  128 + }
  129 + return matched;
  130 +}
security/tomoyo/memory.c
... ... @@ -89,6 +89,50 @@
89 89 kfree(ptr);
90 90 }
91 91  
  92 +/**
  93 + * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
  94 + *
  95 + * @group_name: The name of address group.
  96 + * @idx: Index number.
  97 + *
  98 + * Returns pointer to "struct tomoyo_group" on success, NULL otherwise.
  99 + */
  100 +struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
  101 +{
  102 + struct tomoyo_group e = { };
  103 + struct tomoyo_group *group = NULL;
  104 + bool found = false;
  105 + if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)
  106 + return NULL;
  107 + e.group_name = tomoyo_get_name(group_name);
  108 + if (!e.group_name)
  109 + return NULL;
  110 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
  111 + goto out;
  112 + list_for_each_entry(group, &tomoyo_group_list[idx], list) {
  113 + if (e.group_name != group->group_name)
  114 + continue;
  115 + atomic_inc(&group->users);
  116 + found = true;
  117 + break;
  118 + }
  119 + if (!found) {
  120 + struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e));
  121 + if (entry) {
  122 + INIT_LIST_HEAD(&entry->member_list);
  123 + atomic_set(&entry->users, 1);
  124 + list_add_tail_rcu(&entry->list,
  125 + &tomoyo_group_list[idx]);
  126 + group = entry;
  127 + found = true;
  128 + }
  129 + }
  130 + mutex_unlock(&tomoyo_policy_lock);
  131 + out:
  132 + tomoyo_put_name(e.group_name);
  133 + return found ? group : NULL;
  134 +}
  135 +
92 136 /*
93 137 * tomoyo_name_list is used for holding string data used by TOMOYO.
94 138 * Since same string data is likely used for multiple times (e.g.
security/tomoyo/number_group.c
1   -/*
2   - * security/tomoyo/number_group.c
3   - *
4   - * Copyright (C) 2005-2009 NTT DATA CORPORATION
5   - */
6   -
7   -#include <linux/slab.h>
8   -#include "common.h"
9   -
10   -/**
11   - * tomoyo_get_group - Allocate memory for "struct tomoyo_number_group".
12   - *
13   - * @group_name: The name of number group.
14   - *
15   - * Returns pointer to "struct tomoyo_number_group" on success,
16   - * NULL otherwise.
17   - */
18   -struct tomoyo_group *tomoyo_get_number_group(const char *group_name)
19   -{
20   - struct tomoyo_group *entry = NULL;
21   - struct tomoyo_group *group = NULL;
22   - const struct tomoyo_path_info *saved_group_name;
23   - int error = -ENOMEM;
24   - if (!tomoyo_correct_word(group_name))
25   - return NULL;
26   - saved_group_name = tomoyo_get_name(group_name);
27   - if (!saved_group_name)
28   - return NULL;
29   - entry = kzalloc(sizeof(*entry), GFP_NOFS);
30   - if (mutex_lock_interruptible(&tomoyo_policy_lock))
31   - goto out;
32   - list_for_each_entry_rcu(group, &tomoyo_group_list[TOMOYO_NUMBER_GROUP],
33   - list) {
34   - if (saved_group_name != group->group_name)
35   - continue;
36   - atomic_inc(&group->users);
37   - error = 0;
38   - break;
39   - }
40   - if (error && tomoyo_memory_ok(entry)) {
41   - INIT_LIST_HEAD(&entry->member_list);
42   - entry->group_name = saved_group_name;
43   - saved_group_name = NULL;
44   - atomic_set(&entry->users, 1);
45   - list_add_tail_rcu(&entry->list,
46   - &tomoyo_group_list[TOMOYO_NUMBER_GROUP]);
47   - group = entry;
48   - entry = NULL;
49   - error = 0;
50   - }
51   - mutex_unlock(&tomoyo_policy_lock);
52   - out:
53   - tomoyo_put_name(saved_group_name);
54   - kfree(entry);
55   - return !error ? group : NULL;
56   -}
57   -
58   -static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
59   - const struct tomoyo_acl_head *b)
60   -{
61   - return !memcmp(&container_of(a, struct tomoyo_number_group,
62   - head)->number,
63   - &container_of(b, struct tomoyo_number_group,
64   - head)->number,
65   - sizeof(container_of(a,
66   - struct tomoyo_number_group,
67   - head)->number));
68   -}
69   -
70   -/**
71   - * tomoyo_write_number_group_policy - Write "struct tomoyo_number_group" list.
72   - *
73   - * @data: String to parse.
74   - * @is_delete: True if it is a delete request.
75   - *
76   - * Returns 0 on success, nagative value otherwise.
77   - */
78   -int tomoyo_write_number_group_policy(char *data, const bool is_delete)
79   -{
80   - struct tomoyo_group *group;
81   - struct tomoyo_number_group e = { };
82   - int error;
83   - char *w[2];
84   - if (!tomoyo_tokenize(data, w, sizeof(w)))
85   - return -EINVAL;
86   - if (w[1][0] == '@' || !tomoyo_parse_number_union(w[1], &e.number) ||
87   - e.number.values[0] > e.number.values[1])
88   - return -EINVAL;
89   - group = tomoyo_get_number_group(w[0]);
90   - if (!group)
91   - return -ENOMEM;
92   - error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
93   - &group->member_list,
94   - tomoyo_same_number_group);
95   - tomoyo_put_group(group);
96   - return error;
97   -}
98   -
99   -/**
100   - * tomoyo_number_matches_group - Check whether the given number matches members of the given number group.
101   - *
102   - * @min: Min number.
103   - * @max: Max number.
104   - * @group: Pointer to "struct tomoyo_number_group".
105   - *
106   - * Returns true if @min and @max partially overlaps @group, false otherwise.
107   - *
108   - * Caller holds tomoyo_read_lock().
109   - */
110   -bool tomoyo_number_matches_group(const unsigned long min,
111   - const unsigned long max,
112   - const struct tomoyo_group *group)
113   -{
114   - struct tomoyo_number_group *member;
115   - bool matched = false;
116   - list_for_each_entry_rcu(member, &group->member_list, head.list) {
117   - if (member->head.is_deleted)
118   - continue;
119   - if (min > member->number.values[1] ||
120   - max < member->number.values[0])
121   - continue;
122   - matched = true;
123   - break;
124   - }
125   - return matched;
126   -}
security/tomoyo/path_group.c
1   -/*
2   - * security/tomoyo/path_group.c
3   - *
4   - * Copyright (C) 2005-2009 NTT DATA CORPORATION
5   - */
6   -
7   -#include <linux/slab.h>
8   -#include "common.h"
9   -
10   -/**
11   - * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group".
12   - *
13   - * @group_name: The name of pathname group.
14   - *
15   - * Returns pointer to "struct tomoyo_path_group" on success, NULL otherwise.
16   - */
17   -struct tomoyo_group *tomoyo_get_path_group(const char *group_name)
18   -{
19   - struct tomoyo_group *entry = NULL;
20   - struct tomoyo_group *group = NULL;
21   - const struct tomoyo_path_info *saved_group_name;
22   - int error = -ENOMEM;
23   - if (!tomoyo_correct_word(group_name))
24   - return NULL;
25   - saved_group_name = tomoyo_get_name(group_name);
26   - if (!saved_group_name)
27   - return NULL;
28   - entry = kzalloc(sizeof(*entry), GFP_NOFS);
29   - if (mutex_lock_interruptible(&tomoyo_policy_lock))
30   - goto out;
31   - list_for_each_entry_rcu(group, &tomoyo_group_list[TOMOYO_PATH_GROUP],
32   - list) {
33   - if (saved_group_name != group->group_name)
34   - continue;
35   - atomic_inc(&group->users);
36   - error = 0;
37   - break;
38   - }
39   - if (error && tomoyo_memory_ok(entry)) {
40   - INIT_LIST_HEAD(&entry->member_list);
41   - entry->group_name = saved_group_name;
42   - saved_group_name = NULL;
43   - atomic_set(&entry->users, 1);
44   - list_add_tail_rcu(&entry->list,
45   - &tomoyo_group_list[TOMOYO_PATH_GROUP]);
46   - group = entry;
47   - entry = NULL;
48   - error = 0;
49   - }
50   - mutex_unlock(&tomoyo_policy_lock);
51   - out:
52   - tomoyo_put_name(saved_group_name);
53   - kfree(entry);
54   - return !error ? group : NULL;
55   -}
56   -
57   -static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
58   - const struct tomoyo_acl_head *b)
59   -{
60   - return container_of(a, struct tomoyo_path_group, head)
61   - ->member_name ==
62   - container_of(b, struct tomoyo_path_group, head)
63   - ->member_name;
64   -}
65   -
66   -/**
67   - * tomoyo_write_path_group_policy - Write "struct tomoyo_path_group" list.
68   - *
69   - * @data: String to parse.
70   - * @is_delete: True if it is a delete request.
71   - *
72   - * Returns 0 on success, nagative value otherwise.
73   - */
74   -int tomoyo_write_path_group_policy(char *data, const bool is_delete)
75   -{
76   - struct tomoyo_group *group;
77   - struct tomoyo_path_group e = { };
78   - int error = is_delete ? -ENOENT : -ENOMEM;
79   - char *w[2];
80   - if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
81   - return -EINVAL;
82   - group = tomoyo_get_path_group(w[0]);
83   - if (!group)
84   - return -ENOMEM;
85   - e.member_name = tomoyo_get_name(w[1]);
86   - if (!e.member_name)
87   - goto out;
88   - error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
89   - &group->member_list,
90   - tomoyo_same_path_group);
91   - out:
92   - tomoyo_put_name(e.member_name);
93   - tomoyo_put_group(group);
94   - return error;
95   -}
96   -
97   -/**
98   - * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group.
99   - *
100   - * @pathname: The name of pathname.
101   - * @group: Pointer to "struct tomoyo_path_group".
102   - *
103   - * Returns true if @pathname matches pathnames in @group, false otherwise.
104   - *
105   - * Caller holds tomoyo_read_lock().
106   - */
107   -bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
108   - const struct tomoyo_group *group)
109   -{
110   - struct tomoyo_path_group *member;
111   - bool matched = false;
112   - list_for_each_entry_rcu(member, &group->member_list, head.list) {
113   - if (member->head.is_deleted)
114   - continue;
115   - if (!tomoyo_path_matches_pattern(pathname,
116   - member->member_name))
117   - continue;
118   - matched = true;
119   - break;
120   - }
121   - return matched;
122   -}
security/tomoyo/util.c
... ... @@ -92,7 +92,7 @@
92 92 if (!tomoyo_correct_word(filename))
93 93 return false;
94 94 if (filename[0] == '@') {
95   - ptr->group = tomoyo_get_path_group(filename + 1);
  95 + ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP);
96 96 ptr->is_group = true;
97 97 return ptr->group != NULL;
98 98 }
... ... @@ -117,7 +117,7 @@
117 117 if (data[0] == '@') {
118 118 if (!tomoyo_correct_word(data))
119 119 return false;
120   - num->group = tomoyo_get_number_group(data + 1);
  120 + num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP);
121 121 num->is_group = true;
122 122 return num->group != NULL;
123 123 }