2
2
* security/tomoyo/domain.c
4
* Implementation of the Domain-Based Mandatory Access Control.
6
* Copyright (C) 2005-2009 NTT DATA CORPORATION
8
* Version: 2.2.0 2009/04/01
4
* Domain transition functions for TOMOYO.
6
* Copyright (C) 2005-2010 NTT DATA CORPORATION
15
10
#include <linux/binfmts.h>
11
#include <linux/slab.h>
17
13
/* Variables definitions.*/
19
15
/* The initial domain. */
20
16
struct tomoyo_domain_info tomoyo_kernel_domain;
23
* tomoyo_domain_list is used for holding list of domains.
24
* The ->acl_info_list of "struct tomoyo_domain_info" is used for holding
25
* permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
27
* An entry is added by
29
* # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \
30
* /sys/kernel/security/tomoyo/domain_policy
34
* # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \
35
* /sys/kernel/security/tomoyo/domain_policy
37
* and all entries are retrieved by
39
* # cat /sys/kernel/security/tomoyo/domain_policy
41
* A domain is added by
43
* # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy
47
* # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy
49
* and all domains are retrieved by
51
* # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy
53
* Normally, a domainname is monotonically getting longer because a domainname
54
* which the process will belong to if an execve() operation succeeds is
55
* defined as a concatenation of "current domainname" + "pathname passed to
57
* See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for
19
* tomoyo_update_policy - Update an entry for exception policy.
21
* @new_entry: Pointer to "struct tomoyo_acl_info".
22
* @size: Size of @new_entry in bytes.
23
* @is_delete: True if it is a delete request.
24
* @list: Pointer to "struct list_head".
25
* @check_duplicate: Callback function to find duplicated entry.
27
* Returns 0 on success, negative value otherwise.
29
* Caller holds tomoyo_read_lock().
31
int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
32
bool is_delete, struct list_head *list,
33
bool (*check_duplicate) (const struct tomoyo_acl_head
35
const struct tomoyo_acl_head
38
int error = is_delete ? -ENOENT : -ENOMEM;
39
struct tomoyo_acl_head *entry;
41
if (mutex_lock_interruptible(&tomoyo_policy_lock))
43
list_for_each_entry_rcu(entry, list, list) {
44
if (!check_duplicate(entry, new_entry))
46
entry->is_deleted = is_delete;
50
if (error && !is_delete) {
51
entry = tomoyo_commit_ok(new_entry, size);
53
list_add_tail_rcu(&entry->list, list);
57
mutex_unlock(&tomoyo_policy_lock);
62
* tomoyo_update_domain - Update an entry for domain policy.
64
* @new_entry: Pointer to "struct tomoyo_acl_info".
65
* @size: Size of @new_entry in bytes.
66
* @is_delete: True if it is a delete request.
67
* @domain: Pointer to "struct tomoyo_domain_info".
68
* @check_duplicate: Callback function to find duplicated entry.
69
* @merge_duplicate: Callback function to merge duplicated entry.
71
* Returns 0 on success, negative value otherwise.
73
* Caller holds tomoyo_read_lock().
75
int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
76
bool is_delete, struct tomoyo_domain_info *domain,
77
bool (*check_duplicate) (const struct tomoyo_acl_info
79
const struct tomoyo_acl_info
81
bool (*merge_duplicate) (struct tomoyo_acl_info *,
82
struct tomoyo_acl_info *,
85
int error = is_delete ? -ENOENT : -ENOMEM;
86
struct tomoyo_acl_info *entry;
88
if (mutex_lock_interruptible(&tomoyo_policy_lock))
90
list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
91
if (!check_duplicate(entry, new_entry))
94
entry->is_deleted = merge_duplicate(entry, new_entry,
97
entry->is_deleted = is_delete;
101
if (error && !is_delete) {
102
entry = tomoyo_commit_ok(new_entry, size);
104
list_add_tail_rcu(&entry->list, &domain->acl_info_list);
108
mutex_unlock(&tomoyo_policy_lock);
112
void tomoyo_check_acl(struct tomoyo_request_info *r,
113
bool (*check_entry) (struct tomoyo_request_info *,
114
const struct tomoyo_acl_info *))
116
const struct tomoyo_domain_info *domain = r->domain;
117
struct tomoyo_acl_info *ptr;
119
list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
120
if (ptr->is_deleted || ptr->type != r->param_type)
122
if (check_entry(r, ptr)) {
130
/* The list for "struct tomoyo_domain_info". */
60
131
LIST_HEAD(tomoyo_domain_list);
61
DECLARE_RWSEM(tomoyo_domain_list_lock);
64
* tomoyo_domain_initializer_entry is a structure which is used for holding
65
* "initialize_domain" and "no_initialize_domain" entries.
66
* It has following fields.
68
* (1) "list" which is linked to tomoyo_domain_initializer_list .
69
* (2) "domainname" which is "a domainname" or "the last component of a
70
* domainname". This field is NULL if "from" clause is not specified.
71
* (3) "program" which is a program's pathname.
72
* (4) "is_deleted" is a bool which is true if marked as deleted, false
74
* (5) "is_not" is a bool which is true if "no_initialize_domain", false
76
* (6) "is_last_name" is a bool which is true if "domainname" is "the last
77
* component of a domainname", false otherwise.
79
struct tomoyo_domain_initializer_entry {
80
struct list_head list;
81
const struct tomoyo_path_info *domainname; /* This may be NULL */
82
const struct tomoyo_path_info *program;
84
bool is_not; /* True if this entry is "no_initialize_domain". */
85
/* True if the domainname is tomoyo_get_last_name(). */
90
* tomoyo_domain_keeper_entry is a structure which is used for holding
91
* "keep_domain" and "no_keep_domain" entries.
92
* It has following fields.
94
* (1) "list" which is linked to tomoyo_domain_keeper_list .
95
* (2) "domainname" which is "a domainname" or "the last component of a
97
* (3) "program" which is a program's pathname.
98
* This field is NULL if "from" clause is not specified.
99
* (4) "is_deleted" is a bool which is true if marked as deleted, false
101
* (5) "is_not" is a bool which is true if "no_initialize_domain", false
103
* (6) "is_last_name" is a bool which is true if "domainname" is "the last
104
* component of a domainname", false otherwise.
106
struct tomoyo_domain_keeper_entry {
107
struct list_head list;
108
const struct tomoyo_path_info *domainname;
109
const struct tomoyo_path_info *program; /* This may be NULL */
111
bool is_not; /* True if this entry is "no_keep_domain". */
112
/* True if the domainname is tomoyo_get_last_name(). */
117
* tomoyo_alias_entry is a structure which is used for holding "alias" entries.
118
* It has following fields.
120
* (1) "list" which is linked to tomoyo_alias_list .
121
* (2) "original_name" which is a dereferenced pathname.
122
* (3) "aliased_name" which is a symlink's pathname.
123
* (4) "is_deleted" is a bool which is true if marked as deleted, false
126
struct tomoyo_alias_entry {
127
struct list_head list;
128
const struct tomoyo_path_info *original_name;
129
const struct tomoyo_path_info *aliased_name;
134
* tomoyo_set_domain_flag - Set or clear domain's attribute flags.
136
* @domain: Pointer to "struct tomoyo_domain_info".
137
* @is_delete: True if it is a delete request.
138
* @flags: Flags to set or clear.
142
void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
143
const bool is_delete, const u8 flags)
145
/* We need to serialize because this is bitfield operation. */
146
static DEFINE_SPINLOCK(lock);
149
domain->flags |= flags;
151
domain->flags &= ~flags;
156
* tomoyo_get_last_name - Get last component of a domainname.
158
* @domain: Pointer to "struct tomoyo_domain_info".
160
* Returns the last component of the domainname.
162
const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
164
const char *cp0 = domain->domainname->name;
165
const char *cp1 = strrchr(cp0, ' ');
173
* tomoyo_domain_initializer_list is used for holding list of programs which
174
* triggers reinitialization of domainname. Normally, a domainname is
175
* monotonically getting longer. But sometimes, we restart daemon programs.
176
* It would be convenient for us that "a daemon started upon system boot" and
177
* "the daemon restarted from console" belong to the same domain. Thus, TOMOYO
178
* provides a way to shorten domainnames.
180
* An entry is added by
182
* # echo 'initialize_domain /usr/sbin/httpd' > \
183
* /sys/kernel/security/tomoyo/exception_policy
187
* # echo 'delete initialize_domain /usr/sbin/httpd' > \
188
* /sys/kernel/security/tomoyo/exception_policy
190
* and all entries are retrieved by
192
* # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy
194
* In the example above, /usr/sbin/httpd will belong to
195
* "<kernel> /usr/sbin/httpd" domain.
197
* You may specify a domainname using "from" keyword.
198
* "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
199
* will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd"
200
* domain to belong to "<kernel> /usr/sbin/httpd" domain.
202
* You may add "no_" prefix to "initialize_domain".
203
* "initialize_domain /usr/sbin/httpd" and
204
* "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
205
* will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
206
* unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
208
static LIST_HEAD(tomoyo_domain_initializer_list);
209
static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
212
* tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
214
* @domainname: The name of domain. May be NULL.
215
* @program: The name of program.
216
* @is_not: True if it is "no_initialize_domain" entry.
133
struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY];
134
struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP];
137
* tomoyo_last_word - Get last component of a domainname.
139
* @domainname: Domainname to check.
141
* Returns the last word of @domainname.
143
static const char *tomoyo_last_word(const char *name)
145
const char *cp = strrchr(name, ' ');
151
static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
152
const struct tomoyo_acl_head *b)
154
const struct tomoyo_transition_control *p1 = container_of(a,
157
const struct tomoyo_transition_control *p2 = container_of(b,
160
return p1->type == p2->type && p1->is_last_name == p2->is_last_name
161
&& p1->domainname == p2->domainname
162
&& p1->program == p2->program;
166
* tomoyo_update_transition_control_entry - Update "struct tomoyo_transition_control" list.
168
* @domainname: The name of domain. Maybe NULL.
169
* @program: The name of program. Maybe NULL.
170
* @type: Type of transition.
217
171
* @is_delete: True if it is a delete request.
219
173
* Returns 0 on success, negative value otherwise.
221
static int tomoyo_update_domain_initializer_entry(const char *domainname,
175
static int tomoyo_update_transition_control_entry(const char *domainname,
222
176
const char *program,
224
178
const bool is_delete)
226
struct tomoyo_domain_initializer_entry *new_entry;
227
struct tomoyo_domain_initializer_entry *ptr;
228
const struct tomoyo_path_info *saved_program;
229
const struct tomoyo_path_info *saved_domainname = NULL;
231
bool is_last_name = false;
233
if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
234
return -EINVAL; /* No patterns allowed. */
236
if (!tomoyo_is_domain_def(domainname) &&
237
tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
239
else if (!tomoyo_is_correct_domain(domainname, __func__))
180
struct tomoyo_transition_control e = { .type = type };
181
int error = is_delete ? -ENOENT : -ENOMEM;
183
if (!tomoyo_correct_path(program))
241
saved_domainname = tomoyo_save_name(domainname);
242
if (!saved_domainname)
245
saved_program = tomoyo_save_name(program);
248
down_write(&tomoyo_domain_initializer_list_lock);
249
list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
250
if (ptr->is_not != is_not ||
251
ptr->domainname != saved_domainname ||
252
ptr->program != saved_program)
254
ptr->is_deleted = is_delete;
262
new_entry = tomoyo_alloc_element(sizeof(*new_entry));
265
new_entry->domainname = saved_domainname;
266
new_entry->program = saved_program;
267
new_entry->is_not = is_not;
268
new_entry->is_last_name = is_last_name;
269
list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list);
185
e.program = tomoyo_get_name(program);
190
if (!tomoyo_correct_domain(domainname)) {
191
if (!tomoyo_correct_path(domainname))
193
e.is_last_name = true;
195
e.domainname = tomoyo_get_name(domainname);
199
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
201
[TOMOYO_ID_TRANSITION_CONTROL],
202
tomoyo_same_transition_control);
272
up_write(&tomoyo_domain_initializer_list_lock);
204
tomoyo_put_name(e.domainname);
205
tomoyo_put_name(e.program);
277
* tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
279
* @head: Pointer to "struct tomoyo_io_buffer".
281
* Returns true on success, false otherwise.
283
bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
285
struct list_head *pos;
288
down_read(&tomoyo_domain_initializer_list_lock);
289
list_for_each_cookie(pos, head->read_var2,
290
&tomoyo_domain_initializer_list) {
292
const char *from = "";
293
const char *domain = "";
294
struct tomoyo_domain_initializer_entry *ptr;
295
ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
299
no = ptr->is_not ? "no_" : "";
300
if (ptr->domainname) {
302
domain = ptr->domainname->name;
304
done = tomoyo_io_printf(head,
305
"%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
306
"%s%s%s\n", no, ptr->program->name,
311
up_read(&tomoyo_domain_initializer_list_lock);
316
* tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
210
* tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
318
212
* @data: String to parse.
319
* @is_not: True if it is "no_initialize_domain" entry.
320
213
* @is_delete: True if it is a delete request.
214
* @type: Type of this entry.
322
216
* Returns 0 on success, negative value otherwise.
324
int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
325
const bool is_delete)
218
int tomoyo_write_transition_control(char *data, const bool is_delete,
327
char *cp = strstr(data, " from ");
331
return tomoyo_update_domain_initializer_entry(cp + 6, data,
221
char *domainname = strstr(data, " from ");
225
} else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
226
type == TOMOYO_TRANSITION_CONTROL_KEEP) {
335
return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
230
return tomoyo_update_transition_control_entry(domainname, data, type,
340
* tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
235
* tomoyo_transition_type - Get domain transition type.
342
237
* @domainname: The name of domain.
343
238
* @program: The name of program.
344
* @last_name: The last component of @domainname.
346
* Returns true if executing @program reinitializes domain transition,
240
* Returns TOMOYO_TRANSITION_CONTROL_INITIALIZE if executing @program
241
* reinitializes domain transition, TOMOYO_TRANSITION_CONTROL_KEEP if executing
242
* @program suppresses domain transition, others otherwise.
244
* Caller holds tomoyo_read_lock().
349
static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
351
const struct tomoyo_path_info *program,
352
const struct tomoyo_path_info *
246
static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
247
const struct tomoyo_path_info *program)
355
struct tomoyo_domain_initializer_entry *ptr;
358
down_read(&tomoyo_domain_initializer_list_lock);
359
list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
362
if (ptr->domainname) {
363
if (!ptr->is_last_name) {
364
if (ptr->domainname != domainname)
367
if (tomoyo_pathcmp(ptr->domainname, last_name))
371
if (tomoyo_pathcmp(ptr->program, program))
249
const struct tomoyo_transition_control *ptr;
250
const char *last_name = tomoyo_last_word(domainname->name);
252
for (type = 0; type < TOMOYO_MAX_TRANSITION_TYPE; type++) {
254
list_for_each_entry_rcu(ptr, &tomoyo_policy_list
255
[TOMOYO_ID_TRANSITION_CONTROL],
257
if (ptr->head.is_deleted || ptr->type != type)
259
if (ptr->domainname) {
260
if (!ptr->is_last_name) {
261
if (ptr->domainname != domainname)
265
* Use direct strcmp() since this is
268
if (strcmp(ptr->domainname->name,
274
tomoyo_pathcmp(ptr->program, program))
276
if (type == TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) {
278
* Do not check for initialize_domain if
279
* no_initialize_domain matched.
281
type = TOMOYO_TRANSITION_CONTROL_NO_KEEP;
379
up_read(&tomoyo_domain_initializer_list_lock);
384
* tomoyo_domain_keeper_list is used for holding list of domainnames which
385
* suppresses domain transition. Normally, a domainname is monotonically
386
* getting longer. But sometimes, we want to suppress domain transition.
387
* It would be convenient for us that programs executed from a login session
388
* belong to the same domain. Thus, TOMOYO provides a way to suppress domain
391
* An entry is added by
393
* # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
394
* /sys/kernel/security/tomoyo/exception_policy
398
* # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
399
* /sys/kernel/security/tomoyo/exception_policy
401
* and all entries are retrieved by
403
* # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy
405
* In the example above, any process which belongs to
406
* "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain,
407
* unless explicitly specified by "initialize_domain" or "no_keep_domain".
409
* You may specify a program using "from" keyword.
410
* "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash"
411
* will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash"
412
* domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain.
414
* You may add "no_" prefix to "keep_domain".
415
* "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and
416
* "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will
417
* cause "/usr/bin/passwd" to belong to
418
* "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
419
* explicitly specified by "initialize_domain".
421
static LIST_HEAD(tomoyo_domain_keeper_list);
422
static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
291
static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a,
292
const struct tomoyo_acl_head *b)
294
const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), head);
295
const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), head);
296
return p1->original_name == p2->original_name &&
297
p1->aggregated_name == p2->aggregated_name;
425
* tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
301
* tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator" list.
427
* @domainname: The name of domain.
428
* @program: The name of program. May be NULL.
429
* @is_not: True if it is "no_keep_domain" entry.
430
* @is_delete: True if it is a delete request.
303
* @original_name: The original program's name.
304
* @aggregated_name: The program name to use.
305
* @is_delete: True if it is a delete request.
432
307
* Returns 0 on success, negative value otherwise.
309
* Caller holds tomoyo_read_lock().
434
static int tomoyo_update_domain_keeper_entry(const char *domainname,
437
const bool is_delete)
311
static int tomoyo_update_aggregator_entry(const char *original_name,
312
const char *aggregated_name,
313
const bool is_delete)
439
struct tomoyo_domain_keeper_entry *new_entry;
440
struct tomoyo_domain_keeper_entry *ptr;
441
const struct tomoyo_path_info *saved_domainname;
442
const struct tomoyo_path_info *saved_program = NULL;
444
bool is_last_name = false;
315
struct tomoyo_aggregator e = { };
316
int error = is_delete ? -ENOENT : -ENOMEM;
446
if (!tomoyo_is_domain_def(domainname) &&
447
tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
449
else if (!tomoyo_is_correct_domain(domainname, __func__))
318
if (!tomoyo_correct_path(original_name) ||
319
!tomoyo_correct_path(aggregated_name))
452
if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
454
saved_program = tomoyo_save_name(program);
458
saved_domainname = tomoyo_save_name(domainname);
459
if (!saved_domainname)
461
down_write(&tomoyo_domain_keeper_list_lock);
462
list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
463
if (ptr->is_not != is_not ||
464
ptr->domainname != saved_domainname ||
465
ptr->program != saved_program)
467
ptr->is_deleted = is_delete;
475
new_entry = tomoyo_alloc_element(sizeof(*new_entry));
478
new_entry->domainname = saved_domainname;
479
new_entry->program = saved_program;
480
new_entry->is_not = is_not;
481
new_entry->is_last_name = is_last_name;
482
list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list);
485
up_write(&tomoyo_domain_keeper_list_lock);
490
* tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
492
* @data: String to parse.
493
* @is_not: True if it is "no_keep_domain" entry.
494
* @is_delete: True if it is a delete request.
497
int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
498
const bool is_delete)
500
char *cp = strstr(data, " from ");
504
return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
507
return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
511
* tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
513
* @head: Pointer to "struct tomoyo_io_buffer".
515
* Returns true on success, false otherwise.
517
bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
519
struct list_head *pos;
522
down_read(&tomoyo_domain_keeper_list_lock);
523
list_for_each_cookie(pos, head->read_var2,
524
&tomoyo_domain_keeper_list) {
525
struct tomoyo_domain_keeper_entry *ptr;
527
const char *from = "";
528
const char *program = "";
530
ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
533
no = ptr->is_not ? "no_" : "";
536
program = ptr->program->name;
538
done = tomoyo_io_printf(head,
539
"%s" TOMOYO_KEYWORD_KEEP_DOMAIN
540
"%s%s%s\n", no, program, from,
541
ptr->domainname->name);
545
up_read(&tomoyo_domain_keeper_list_lock);
550
* tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
552
* @domainname: The name of domain.
553
* @program: The name of program.
554
* @last_name: The last component of @domainname.
556
* Returns true if executing @program supresses domain transition,
559
static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
560
const struct tomoyo_path_info *program,
561
const struct tomoyo_path_info *last_name)
563
struct tomoyo_domain_keeper_entry *ptr;
566
down_read(&tomoyo_domain_keeper_list_lock);
567
list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
570
if (!ptr->is_last_name) {
571
if (ptr->domainname != domainname)
574
if (tomoyo_pathcmp(ptr->domainname, last_name))
577
if (ptr->program && tomoyo_pathcmp(ptr->program, program))
585
up_read(&tomoyo_domain_keeper_list_lock);
590
* tomoyo_alias_list is used for holding list of symlink's pathnames which are
591
* allowed to be passed to an execve() request. Normally, the domainname which
592
* the current process will belong to after execve() succeeds is calculated
593
* using dereferenced pathnames. But some programs behave differently depending
594
* on the name passed to argv[0]. For busybox, calculating domainname using
595
* dereferenced pathnames will cause all programs in the busybox to belong to
596
* the same domain. Thus, TOMOYO provides a way to allow use of symlink's
597
* pathname for checking execve()'s permission and calculating domainname which
598
* the current process will belong to after execve() succeeds.
600
* An entry is added by
602
* # echo 'alias /bin/busybox /bin/cat' > \
603
* /sys/kernel/security/tomoyo/exception_policy
607
* # echo 'delete alias /bin/busybox /bin/cat' > \
608
* /sys/kernel/security/tomoyo/exception_policy
610
* and all entries are retrieved by
612
* # grep ^alias /sys/kernel/security/tomoyo/exception_policy
614
* In the example above, if /bin/cat is a symlink to /bin/busybox and execution
615
* of /bin/cat is requested, permission is checked for /bin/cat rather than
616
* /bin/busybox and domainname which the current process will belong to after
617
* execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
619
static LIST_HEAD(tomoyo_alias_list);
620
static DECLARE_RWSEM(tomoyo_alias_list_lock);
623
* tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
625
* @original_name: The original program's real name.
626
* @aliased_name: The symbolic program's symbolic link's name.
627
* @is_delete: True if it is a delete request.
629
* Returns 0 on success, negative value otherwise.
631
static int tomoyo_update_alias_entry(const char *original_name,
632
const char *aliased_name,
633
const bool is_delete)
635
struct tomoyo_alias_entry *new_entry;
636
struct tomoyo_alias_entry *ptr;
637
const struct tomoyo_path_info *saved_original_name;
638
const struct tomoyo_path_info *saved_aliased_name;
641
if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) ||
642
!tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__))
643
return -EINVAL; /* No patterns allowed. */
644
saved_original_name = tomoyo_save_name(original_name);
645
saved_aliased_name = tomoyo_save_name(aliased_name);
646
if (!saved_original_name || !saved_aliased_name)
648
down_write(&tomoyo_alias_list_lock);
649
list_for_each_entry(ptr, &tomoyo_alias_list, list) {
650
if (ptr->original_name != saved_original_name ||
651
ptr->aliased_name != saved_aliased_name)
653
ptr->is_deleted = is_delete;
661
new_entry = tomoyo_alloc_element(sizeof(*new_entry));
664
new_entry->original_name = saved_original_name;
665
new_entry->aliased_name = saved_aliased_name;
666
list_add_tail(&new_entry->list, &tomoyo_alias_list);
669
up_write(&tomoyo_alias_list_lock);
674
* tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
676
* @head: Pointer to "struct tomoyo_io_buffer".
678
* Returns true on success, false otherwise.
680
bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
682
struct list_head *pos;
685
down_read(&tomoyo_alias_list_lock);
686
list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
687
struct tomoyo_alias_entry *ptr;
689
ptr = list_entry(pos, struct tomoyo_alias_entry, list);
692
done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
693
ptr->original_name->name,
694
ptr->aliased_name->name);
698
up_read(&tomoyo_alias_list_lock);
703
* tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
705
* @data: String to parse.
706
* @is_delete: True if it is a delete request.
708
* Returns 0 on success, negative value otherwise.
710
int tomoyo_write_alias_policy(char *data, const bool is_delete)
321
e.original_name = tomoyo_get_name(original_name);
322
e.aggregated_name = tomoyo_get_name(aggregated_name);
323
if (!e.original_name || !e.aggregated_name ||
324
e.aggregated_name->is_patterned) /* No patterns allowed. */
326
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
327
&tomoyo_policy_list[TOMOYO_ID_AGGREGATOR],
328
tomoyo_same_aggregator);
330
tomoyo_put_name(e.original_name);
331
tomoyo_put_name(e.aggregated_name);
336
* tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
338
* @data: String to parse.
339
* @is_delete: True if it is a delete request.
341
* Returns 0 on success, negative value otherwise.
343
* Caller holds tomoyo_read_lock().
345
int tomoyo_write_aggregator(char *data, const bool is_delete)
712
347
char *cp = strchr(data, ' ');
717
return tomoyo_update_alias_entry(data, cp, is_delete);
352
return tomoyo_update_aggregator_entry(data, cp, is_delete);
721
* tomoyo_find_or_assign_new_domain - Create a domain.
356
* tomoyo_assign_domain - Create a domain.
723
358
* @domainname: The name of domain.
724
359
* @profile: Profile number to assign if the domain was newly created.
726
361
* Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
363
* Caller holds tomoyo_read_lock().
728
struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
365
struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
368
struct tomoyo_domain_info *entry;
732
369
struct tomoyo_domain_info *domain = NULL;
733
370
const struct tomoyo_path_info *saved_domainname;
735
down_write(&tomoyo_domain_list_lock);
736
domain = tomoyo_find_domain(domainname);
739
if (!tomoyo_is_correct_domain(domainname, __func__))
741
saved_domainname = tomoyo_save_name(domainname);
373
if (!tomoyo_correct_domain(domainname))
375
saved_domainname = tomoyo_get_name(domainname);
742
376
if (!saved_domainname)
744
/* Can I reuse memory of deleted domain? */
745
list_for_each_entry(domain, &tomoyo_domain_list, list) {
746
struct task_struct *p;
747
struct tomoyo_acl_info *ptr;
749
if (!domain->is_deleted ||
750
domain->domainname != saved_domainname)
753
read_lock(&tasklist_lock);
754
for_each_process(p) {
755
if (tomoyo_real_domain(p) != domain)
760
read_unlock(&tasklist_lock);
763
list_for_each_entry(ptr, &domain->acl_info_list, list) {
764
ptr->type |= TOMOYO_ACL_DELETED;
766
tomoyo_set_domain_flag(domain, true, domain->flags);
767
domain->profile = profile;
768
domain->quota_warned = false;
769
mb(); /* Avoid out-of-order execution. */
770
domain->is_deleted = false;
773
/* No memory reusable. Create using new memory. */
774
domain = tomoyo_alloc_element(sizeof(*domain));
776
INIT_LIST_HEAD(&domain->acl_info_list);
777
domain->domainname = saved_domainname;
778
domain->profile = profile;
779
list_add_tail(&domain->list, &tomoyo_domain_list);
378
entry = kzalloc(sizeof(*entry), GFP_NOFS);
379
if (mutex_lock_interruptible(&tomoyo_policy_lock))
381
list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
382
if (domain->is_deleted ||
383
tomoyo_pathcmp(saved_domainname, domain->domainname))
388
if (!found && tomoyo_memory_ok(entry)) {
389
INIT_LIST_HEAD(&entry->acl_info_list);
390
entry->domainname = saved_domainname;
391
saved_domainname = NULL;
392
entry->profile = profile;
393
list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
398
mutex_unlock(&tomoyo_policy_lock);
782
up_write(&tomoyo_domain_list_lock);
400
tomoyo_put_name(saved_domainname);
402
return found ? domain : NULL;
789
408
* @bprm: Pointer to "struct linux_binprm".
791
410
* Returns 0 on success, negative value otherwise.
412
* Caller holds tomoyo_read_lock().
793
414
int tomoyo_find_next_domain(struct linux_binprm *bprm)
796
* This function assumes that the size of buffer returned by
797
* tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
799
struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp));
416
struct tomoyo_request_info r;
417
char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
800
418
struct tomoyo_domain_info *old_domain = tomoyo_domain();
801
419
struct tomoyo_domain_info *domain = NULL;
802
const char *old_domain_name = old_domain->domainname->name;
803
420
const char *original_name = bprm->filename;
804
char *new_domain_name = NULL;
805
char *real_program_name = NULL;
806
char *symlink_program_name = NULL;
807
const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
808
const bool is_enforce = (mode == 3);
809
423
int retval = -ENOMEM;
810
struct tomoyo_path_info r; /* real name */
811
struct tomoyo_path_info s; /* symlink name */
812
struct tomoyo_path_info l; /* last name */
813
static bool initialized;
424
bool need_kfree = false;
425
struct tomoyo_path_info rn = { }; /* real name */
427
mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
428
is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
820
* Built-in initializers. This is needed because policies are
821
* not loaded until starting /sbin/init.
823
tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
825
tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
830
/* Get tomoyo_realpath of program. */
437
/* Get symlink's pathname of program. */
831
438
retval = -ENOENT;
832
/* I hope tomoyo_realpath() won't fail with -ENOMEM. */
833
real_program_name = tomoyo_realpath(original_name);
834
if (!real_program_name)
836
/* Get tomoyo_realpath of symbolic link. */
837
symlink_program_name = tomoyo_realpath_nofollow(original_name);
838
if (!symlink_program_name)
841
r.name = real_program_name;
842
tomoyo_fill_path_info(&r);
843
s.name = symlink_program_name;
844
tomoyo_fill_path_info(&s);
845
l.name = tomoyo_get_last_name(old_domain);
846
tomoyo_fill_path_info(&l);
848
/* Check 'alias' directive. */
849
if (tomoyo_pathcmp(&r, &s)) {
850
struct tomoyo_alias_entry *ptr;
851
/* Is this program allowed to be called via symbolic links? */
852
down_read(&tomoyo_alias_list_lock);
853
list_for_each_entry(ptr, &tomoyo_alias_list, list) {
854
if (ptr->is_deleted ||
855
tomoyo_pathcmp(&r, ptr->original_name) ||
856
tomoyo_pathcmp(&s, ptr->aliased_name))
439
rn.name = tomoyo_realpath_nofollow(original_name);
442
tomoyo_fill_path_info(&rn);
445
/* Check 'aggregator' directive. */
447
struct tomoyo_aggregator *ptr;
448
list_for_each_entry_rcu(ptr, &tomoyo_policy_list
449
[TOMOYO_ID_AGGREGATOR], head.list) {
450
if (ptr->head.is_deleted ||
451
!tomoyo_path_matches_pattern(&rn,
858
memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
859
strncpy(real_program_name, ptr->aliased_name->name,
860
TOMOYO_MAX_PATHNAME_LEN - 1);
861
tomoyo_fill_path_info(&r);
456
/* This is OK because it is read only. */
457
rn = *ptr->aggregated_name;
864
up_read(&tomoyo_alias_list_lock);
867
462
/* Check execute permission. */
868
retval = tomoyo_check_exec_perm(old_domain, &r);
463
retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn);
464
if (retval == TOMOYO_RETRY_REQUEST)
469
* To be able to specify domainnames with wildcards, use the
470
* pathname specified in the policy (which may contain
471
* wildcard) rather than the pathname passed to execve()
472
* (which never contains wildcard).
474
if (r.param.path.matched_path) {
478
/* This is OK because it is read only. */
479
rn = *r.param.path.matched_path;
872
new_domain_name = tmp->buffer;
873
if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) {
482
/* Calculate domain to transit to. */
483
switch (tomoyo_transition_type(old_domain->domainname, &rn)) {
484
case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
874
485
/* Transit to the child of tomoyo_kernel_domain domain. */
875
snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
876
TOMOYO_ROOT_NAME " " "%s", real_program_name);
877
} else if (old_domain == &tomoyo_kernel_domain &&
878
!tomoyo_policy_loaded) {
880
* Needn't to transit from kernel domain before starting
881
* /sbin/init. But transit from kernel domain if executing
882
* initializers because they might start before /sbin/init.
885
} else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
486
snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, TOMOYO_ROOT_NAME " "
489
case TOMOYO_TRANSITION_CONTROL_KEEP:
886
490
/* Keep current domain. */
887
491
domain = old_domain;
889
/* Normal domain transition. */
890
snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
891
"%s %s", old_domain_name, real_program_name);
494
if (old_domain == &tomoyo_kernel_domain &&
495
!tomoyo_policy_loaded) {
497
* Needn't to transit from kernel domain before
498
* starting /sbin/init. But transit from kernel domain
499
* if executing initializers because they might start
504
/* Normal domain transition. */
505
snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
506
old_domain->domainname->name, rn.name);
893
if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
510
if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
895
down_read(&tomoyo_domain_list_lock);
896
domain = tomoyo_find_domain(new_domain_name);
897
up_read(&tomoyo_domain_list_lock);
512
domain = tomoyo_find_domain(tmp);
902
domain = tomoyo_find_or_assign_new_domain(new_domain_name,
903
old_domain->profile);
516
int error = tomoyo_supervisor(&r, "# wants to create domain\n"
518
if (error == TOMOYO_RETRY_REQUEST)
523
domain = tomoyo_assign_domain(tmp, old_domain->profile);
907
printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
527
printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
912
tomoyo_set_domain_flag(old_domain, false,
913
TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
531
old_domain->transition_failed = true;
916
534
domain = old_domain;
535
/* Update reference count on "struct tomoyo_domain_info". */
536
atomic_inc(&domain->users);
917
537
bprm->cred->security = domain;
918
tomoyo_free(real_program_name);
919
tomoyo_free(symlink_program_name);