~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to security/tomoyo/domain.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * security/tomoyo/domain.c
3
3
 *
4
 
 * Implementation of the Domain-Based Mandatory Access Control.
5
 
 *
6
 
 * Copyright (C) 2005-2009  NTT DATA CORPORATION
7
 
 *
8
 
 * Version: 2.2.0   2009/04/01
9
 
 *
 
4
 * Domain transition functions for TOMOYO.
 
5
 *
 
6
 * Copyright (C) 2005-2010  NTT DATA CORPORATION
10
7
 */
11
8
 
12
9
#include "common.h"
13
 
#include "tomoyo.h"
14
 
#include "realpath.h"
15
10
#include <linux/binfmts.h>
 
11
#include <linux/slab.h>
16
12
 
17
13
/* Variables definitions.*/
18
14
 
19
15
/* The initial domain. */
20
16
struct tomoyo_domain_info tomoyo_kernel_domain;
21
17
 
22
 
/*
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.
26
 
 *
27
 
 * An entry is added by
28
 
 *
29
 
 * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \
30
 
 *                                  /sys/kernel/security/tomoyo/domain_policy
31
 
 *
32
 
 * and is deleted by
33
 
 *
34
 
 * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \
35
 
 *                                  /sys/kernel/security/tomoyo/domain_policy
36
 
 *
37
 
 * and all entries are retrieved by
38
 
 *
39
 
 * # cat /sys/kernel/security/tomoyo/domain_policy
40
 
 *
41
 
 * A domain is added by
42
 
 *
43
 
 * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy
44
 
 *
45
 
 * and is deleted by
46
 
 *
47
 
 * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy
48
 
 *
49
 
 * and all domains are retrieved by
50
 
 *
51
 
 * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy
52
 
 *
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
56
 
 * execve()".
57
 
 * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for
58
 
 * exceptions.
59
 
 */
 
18
/**
 
19
 * tomoyo_update_policy - Update an entry for exception policy.
 
20
 *
 
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.
 
26
 *
 
27
 * Returns 0 on success, negative value otherwise.
 
28
 *
 
29
 * Caller holds tomoyo_read_lock().
 
30
 */
 
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
 
34
                                                  *,
 
35
                                                  const struct tomoyo_acl_head
 
36
                                                  *))
 
37
{
 
38
        int error = is_delete ? -ENOENT : -ENOMEM;
 
39
        struct tomoyo_acl_head *entry;
 
40
 
 
41
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
 
42
                return -ENOMEM;
 
43
        list_for_each_entry_rcu(entry, list, list) {
 
44
                if (!check_duplicate(entry, new_entry))
 
45
                        continue;
 
46
                entry->is_deleted = is_delete;
 
47
                error = 0;
 
48
                break;
 
49
        }
 
50
        if (error && !is_delete) {
 
51
                entry = tomoyo_commit_ok(new_entry, size);
 
52
                if (entry) {
 
53
                        list_add_tail_rcu(&entry->list, list);
 
54
                        error = 0;
 
55
                }
 
56
        }
 
57
        mutex_unlock(&tomoyo_policy_lock);
 
58
        return error;
 
59
}
 
60
 
 
61
/**
 
62
 * tomoyo_update_domain - Update an entry for domain policy.
 
63
 *
 
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.
 
70
 *
 
71
 * Returns 0 on success, negative value otherwise.
 
72
 *
 
73
 * Caller holds tomoyo_read_lock().
 
74
 */
 
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
 
78
                                                  *,
 
79
                                                  const struct tomoyo_acl_info
 
80
                                                  *),
 
81
                         bool (*merge_duplicate) (struct tomoyo_acl_info *,
 
82
                                                  struct tomoyo_acl_info *,
 
83
                                                  const bool))
 
84
{
 
85
        int error = is_delete ? -ENOENT : -ENOMEM;
 
86
        struct tomoyo_acl_info *entry;
 
87
 
 
88
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
 
89
                return error;
 
90
        list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
 
91
                if (!check_duplicate(entry, new_entry))
 
92
                        continue;
 
93
                if (merge_duplicate)
 
94
                        entry->is_deleted = merge_duplicate(entry, new_entry,
 
95
                                                            is_delete);
 
96
                else
 
97
                        entry->is_deleted = is_delete;
 
98
                error = 0;
 
99
                break;
 
100
        }
 
101
        if (error && !is_delete) {
 
102
                entry = tomoyo_commit_ok(new_entry, size);
 
103
                if (entry) {
 
104
                        list_add_tail_rcu(&entry->list, &domain->acl_info_list);
 
105
                        error = 0;
 
106
                }
 
107
        }
 
108
        mutex_unlock(&tomoyo_policy_lock);
 
109
        return error;
 
110
}
 
111
 
 
112
void tomoyo_check_acl(struct tomoyo_request_info *r,
 
113
                      bool (*check_entry) (struct tomoyo_request_info *,
 
114
                                           const struct tomoyo_acl_info *))
 
115
{
 
116
        const struct tomoyo_domain_info *domain = r->domain;
 
117
        struct tomoyo_acl_info *ptr;
 
118
 
 
119
        list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
 
120
                if (ptr->is_deleted || ptr->type != r->param_type)
 
121
                        continue;
 
122
                if (check_entry(r, ptr)) {
 
123
                        r->granted = true;
 
124
                        return;
 
125
                }
 
126
        }
 
127
        r->granted = false;
 
128
}
 
129
 
 
130
/* The list for "struct tomoyo_domain_info". */
60
131
LIST_HEAD(tomoyo_domain_list);
61
 
DECLARE_RWSEM(tomoyo_domain_list_lock);
62
 
 
63
 
/*
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.
67
 
 *
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
73
 
 *      otherwise.
74
 
 *  (5) "is_not" is a bool which is true if "no_initialize_domain", false
75
 
 *      otherwise.
76
 
 *  (6) "is_last_name" is a bool which is true if "domainname" is "the last
77
 
 *      component of a domainname", false otherwise.
78
 
 */
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;
83
 
        bool is_deleted;
84
 
        bool is_not;       /* True if this entry is "no_initialize_domain".  */
85
 
        /* True if the domainname is tomoyo_get_last_name(). */
86
 
        bool is_last_name;
87
 
};
88
 
 
89
 
/*
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.
93
 
 *
94
 
 *  (1) "list" which is linked to tomoyo_domain_keeper_list .
95
 
 *  (2) "domainname" which is "a domainname" or "the last component of a
96
 
 *      domainname".
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
100
 
 *      otherwise.
101
 
 *  (5) "is_not" is a bool which is true if "no_initialize_domain", false
102
 
 *      otherwise.
103
 
 *  (6) "is_last_name" is a bool which is true if "domainname" is "the last
104
 
 *      component of a domainname", false otherwise.
105
 
 */
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 */
110
 
        bool is_deleted;
111
 
        bool is_not;       /* True if this entry is "no_keep_domain".        */
112
 
        /* True if the domainname is tomoyo_get_last_name(). */
113
 
        bool is_last_name;
114
 
};
115
 
 
116
 
/*
117
 
 * tomoyo_alias_entry is a structure which is used for holding "alias" entries.
118
 
 * It has following fields.
119
 
 *
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
124
 
 *      otherwise.
125
 
 */
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;
130
 
        bool is_deleted;
131
 
};
132
 
 
133
 
/**
134
 
 * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
135
 
 *
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.
139
 
 *
140
 
 * Returns nothing.
141
 
 */
142
 
void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
143
 
                            const bool is_delete, const u8 flags)
144
 
{
145
 
        /* We need to serialize because this is bitfield operation. */
146
 
        static DEFINE_SPINLOCK(lock);
147
 
        spin_lock(&lock);
148
 
        if (!is_delete)
149
 
                domain->flags |= flags;
150
 
        else
151
 
                domain->flags &= ~flags;
152
 
        spin_unlock(&lock);
153
 
}
154
 
 
155
 
/**
156
 
 * tomoyo_get_last_name - Get last component of a domainname.
157
 
 *
158
 
 * @domain: Pointer to "struct tomoyo_domain_info".
159
 
 *
160
 
 * Returns the last component of the domainname.
161
 
 */
162
 
const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
163
 
{
164
 
        const char *cp0 = domain->domainname->name;
165
 
        const char *cp1 = strrchr(cp0, ' ');
166
 
 
167
 
        if (cp1)
168
 
                return cp1 + 1;
169
 
        return cp0;
170
 
}
171
 
 
172
 
/*
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.
179
 
 *
180
 
 * An entry is added by
181
 
 *
182
 
 * # echo 'initialize_domain /usr/sbin/httpd' > \
183
 
 *                               /sys/kernel/security/tomoyo/exception_policy
184
 
 *
185
 
 * and is deleted by
186
 
 *
187
 
 * # echo 'delete initialize_domain /usr/sbin/httpd' > \
188
 
 *                               /sys/kernel/security/tomoyo/exception_policy
189
 
 *
190
 
 * and all entries are retrieved by
191
 
 *
192
 
 * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy
193
 
 *
194
 
 * In the example above, /usr/sbin/httpd will belong to
195
 
 * "<kernel> /usr/sbin/httpd" domain.
196
 
 *
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.
201
 
 *
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.
207
 
 */
208
 
static LIST_HEAD(tomoyo_domain_initializer_list);
209
 
static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
210
 
 
211
 
/**
212
 
 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
213
 
 *
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.
 
132
 
 
133
struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY];
 
134
struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP];
 
135
 
 
136
/**
 
137
 * tomoyo_last_word - Get last component of a domainname.
 
138
 *
 
139
 * @domainname: Domainname to check.
 
140
 *
 
141
 * Returns the last word of @domainname.
 
142
 */
 
143
static const char *tomoyo_last_word(const char *name)
 
144
{
 
145
        const char *cp = strrchr(name, ' ');
 
146
        if (cp)
 
147
                return cp + 1;
 
148
        return name;
 
149
}
 
150
 
 
151
static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
 
152
                                           const struct tomoyo_acl_head *b)
 
153
{
 
154
        const struct tomoyo_transition_control *p1 = container_of(a,
 
155
                                                                  typeof(*p1),
 
156
                                                                  head);
 
157
        const struct tomoyo_transition_control *p2 = container_of(b,
 
158
                                                                  typeof(*p2),
 
159
                                                                  head);
 
160
        return p1->type == p2->type && p1->is_last_name == p2->is_last_name
 
161
                && p1->domainname == p2->domainname
 
162
                && p1->program == p2->program;
 
163
}
 
164
 
 
165
/**
 
166
 * tomoyo_update_transition_control_entry - Update "struct tomoyo_transition_control" list.
 
167
 *
 
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.
218
172
 *
219
173
 * Returns 0 on success, negative value otherwise.
220
174
 */
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,
223
 
                                                  const bool is_not,
 
177
                                                  const u8 type,
224
178
                                                  const bool is_delete)
225
179
{
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;
230
 
        int error = -ENOMEM;
231
 
        bool is_last_name = false;
232
 
 
233
 
        if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
234
 
                return -EINVAL; /* No patterns allowed. */
235
 
        if (domainname) {
236
 
                if (!tomoyo_is_domain_def(domainname) &&
237
 
                    tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
238
 
                        is_last_name = true;
239
 
                else if (!tomoyo_is_correct_domain(domainname, __func__))
 
180
        struct tomoyo_transition_control e = { .type = type };
 
181
        int error = is_delete ? -ENOENT : -ENOMEM;
 
182
        if (program) {
 
183
                if (!tomoyo_correct_path(program))
240
184
                        return -EINVAL;
241
 
                saved_domainname = tomoyo_save_name(domainname);
242
 
                if (!saved_domainname)
243
 
                        return -ENOMEM;
244
 
        }
245
 
        saved_program = tomoyo_save_name(program);
246
 
        if (!saved_program)
247
 
                return -ENOMEM;
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)
253
 
                        continue;
254
 
                ptr->is_deleted = is_delete;
255
 
                error = 0;
256
 
                goto out;
257
 
        }
258
 
        if (is_delete) {
259
 
                error = -ENOENT;
260
 
                goto out;
261
 
        }
262
 
        new_entry = tomoyo_alloc_element(sizeof(*new_entry));
263
 
        if (!new_entry)
264
 
                goto out;
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);
270
 
        error = 0;
 
185
                e.program = tomoyo_get_name(program);
 
186
                if (!e.program)
 
187
                        goto out;
 
188
        }
 
189
        if (domainname) {
 
190
                if (!tomoyo_correct_domain(domainname)) {
 
191
                        if (!tomoyo_correct_path(domainname))
 
192
                                goto out;
 
193
                        e.is_last_name = true;
 
194
                }
 
195
                e.domainname = tomoyo_get_name(domainname);
 
196
                if (!e.domainname)
 
197
                        goto out;
 
198
        }
 
199
        error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
 
200
                                     &tomoyo_policy_list
 
201
                                     [TOMOYO_ID_TRANSITION_CONTROL],
 
202
                                     tomoyo_same_transition_control);
271
203
 out:
272
 
        up_write(&tomoyo_domain_initializer_list_lock);
 
204
        tomoyo_put_name(e.domainname);
 
205
        tomoyo_put_name(e.program);
273
206
        return error;
274
207
}
275
208
 
276
209
/**
277
 
 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
278
 
 *
279
 
 * @head: Pointer to "struct tomoyo_io_buffer".
280
 
 *
281
 
 * Returns true on success, false otherwise.
282
 
 */
283
 
bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
284
 
{
285
 
        struct list_head *pos;
286
 
        bool done = true;
287
 
 
288
 
        down_read(&tomoyo_domain_initializer_list_lock);
289
 
        list_for_each_cookie(pos, head->read_var2,
290
 
                             &tomoyo_domain_initializer_list) {
291
 
                const char *no;
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,
296
 
                                  list);
297
 
                if (ptr->is_deleted)
298
 
                        continue;
299
 
                no = ptr->is_not ? "no_" : "";
300
 
                if (ptr->domainname) {
301
 
                        from = " from ";
302
 
                        domain = ptr->domainname->name;
303
 
                }
304
 
                done = tomoyo_io_printf(head,
305
 
                                        "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
306
 
                                        "%s%s%s\n", no, ptr->program->name,
307
 
                                        from, domain);
308
 
                if (!done)
309
 
                        break;
310
 
        }
311
 
        up_read(&tomoyo_domain_initializer_list_lock);
312
 
        return done;
313
 
}
314
 
 
315
 
/**
316
 
 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
 
210
 * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
317
211
 *
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.
321
215
 *
322
216
 * Returns 0 on success, negative value otherwise.
323
217
 */
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,
 
219
                                    const u8 type)
326
220
{
327
 
        char *cp = strstr(data, " from ");
328
 
 
329
 
        if (cp) {
330
 
                *cp = '\0';
331
 
                return tomoyo_update_domain_initializer_entry(cp + 6, data,
332
 
                                                              is_not,
333
 
                                                              is_delete);
 
221
        char *domainname = strstr(data, " from ");
 
222
        if (domainname) {
 
223
                *domainname = '\0';
 
224
                domainname += 6;
 
225
        } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
 
226
                   type == TOMOYO_TRANSITION_CONTROL_KEEP) {
 
227
                domainname = data;
 
228
                data = NULL;
334
229
        }
335
 
        return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
 
230
        return tomoyo_update_transition_control_entry(domainname, data, type,
336
231
                                                      is_delete);
337
232
}
338
233
 
339
234
/**
340
 
 * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
 
235
 * tomoyo_transition_type - Get domain transition type.
341
236
 *
342
237
 * @domainname: The name of domain.
343
238
 * @program:    The name of program.
344
 
 * @last_name:  The last component of @domainname.
345
 
 *
346
 
 * Returns true if executing @program reinitializes domain transition,
347
 
 * false otherwise.
 
239
 *
 
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.
 
243
 *
 
244
 * Caller holds tomoyo_read_lock().
348
245
 */
349
 
static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
350
 
                                         domainname,
351
 
                                         const struct tomoyo_path_info *program,
352
 
                                         const struct tomoyo_path_info *
353
 
                                         last_name)
 
246
static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
 
247
                                 const struct tomoyo_path_info *program)
354
248
{
355
 
        struct tomoyo_domain_initializer_entry *ptr;
356
 
        bool flag = false;
357
 
 
358
 
        down_read(&tomoyo_domain_initializer_list_lock);
359
 
        list_for_each_entry(ptr,  &tomoyo_domain_initializer_list, list) {
360
 
                if (ptr->is_deleted)
361
 
                        continue;
362
 
                if (ptr->domainname) {
363
 
                        if (!ptr->is_last_name) {
364
 
                                if (ptr->domainname != domainname)
365
 
                                        continue;
366
 
                        } else {
367
 
                                if (tomoyo_pathcmp(ptr->domainname, last_name))
368
 
                                        continue;
369
 
                        }
370
 
                }
371
 
                if (tomoyo_pathcmp(ptr->program, program))
372
 
                        continue;
373
 
                if (ptr->is_not) {
374
 
                        flag = false;
375
 
                        break;
376
 
                }
377
 
                flag = true;
 
249
        const struct tomoyo_transition_control *ptr;
 
250
        const char *last_name = tomoyo_last_word(domainname->name);
 
251
        u8 type;
 
252
        for (type = 0; type < TOMOYO_MAX_TRANSITION_TYPE; type++) {
 
253
 next:
 
254
                list_for_each_entry_rcu(ptr, &tomoyo_policy_list
 
255
                                        [TOMOYO_ID_TRANSITION_CONTROL],
 
256
                                        head.list) {
 
257
                        if (ptr->head.is_deleted || ptr->type != type)
 
258
                                continue;
 
259
                        if (ptr->domainname) {
 
260
                                if (!ptr->is_last_name) {
 
261
                                        if (ptr->domainname != domainname)
 
262
                                                continue;
 
263
                                } else {
 
264
                                        /*
 
265
                                         * Use direct strcmp() since this is
 
266
                                         * unlikely used.
 
267
                                         */
 
268
                                        if (strcmp(ptr->domainname->name,
 
269
                                                   last_name))
 
270
                                                continue;
 
271
                                }
 
272
                        }
 
273
                        if (ptr->program &&
 
274
                            tomoyo_pathcmp(ptr->program, program))
 
275
                                continue;
 
276
                        if (type == TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) {
 
277
                                /*
 
278
                                 * Do not check for initialize_domain if
 
279
                                 * no_initialize_domain matched.
 
280
                                 */
 
281
                                type = TOMOYO_TRANSITION_CONTROL_NO_KEEP;
 
282
                                goto next;
 
283
                        }
 
284
                        goto done;
 
285
                }
378
286
        }
379
 
        up_read(&tomoyo_domain_initializer_list_lock);
380
 
        return flag;
 
287
 done:
 
288
        return type;
381
289
}
382
290
 
383
 
/*
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
389
 
 * transition.
390
 
 *
391
 
 * An entry is added by
392
 
 *
393
 
 * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
394
 
 *                              /sys/kernel/security/tomoyo/exception_policy
395
 
 *
396
 
 * and is deleted by
397
 
 *
398
 
 * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
399
 
 *                              /sys/kernel/security/tomoyo/exception_policy
400
 
 *
401
 
 * and all entries are retrieved by
402
 
 *
403
 
 * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy
404
 
 *
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".
408
 
 *
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.
413
 
 *
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".
420
 
 */
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)
 
293
{
 
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;
 
298
}
423
299
 
424
300
/**
425
 
 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
 
301
 * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator" list.
426
302
 *
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.
431
306
 *
432
307
 * Returns 0 on success, negative value otherwise.
 
308
 *
 
309
 * Caller holds tomoyo_read_lock().
433
310
 */
434
 
static int tomoyo_update_domain_keeper_entry(const char *domainname,
435
 
                                             const char *program,
436
 
                                             const bool is_not,
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)
438
314
{
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;
443
 
        int error = -ENOMEM;
444
 
        bool is_last_name = false;
 
315
        struct tomoyo_aggregator e = { };
 
316
        int error = is_delete ? -ENOENT : -ENOMEM;
445
317
 
446
 
        if (!tomoyo_is_domain_def(domainname) &&
447
 
            tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
448
 
                is_last_name = true;
449
 
        else if (!tomoyo_is_correct_domain(domainname, __func__))
 
318
        if (!tomoyo_correct_path(original_name) ||
 
319
            !tomoyo_correct_path(aggregated_name))
450
320
                return -EINVAL;
451
 
        if (program) {
452
 
                if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
453
 
                        return -EINVAL;
454
 
                saved_program = tomoyo_save_name(program);
455
 
                if (!saved_program)
456
 
                        return -ENOMEM;
457
 
        }
458
 
        saved_domainname = tomoyo_save_name(domainname);
459
 
        if (!saved_domainname)
460
 
                return -ENOMEM;
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)
466
 
                        continue;
467
 
                ptr->is_deleted = is_delete;
468
 
                error = 0;
469
 
                goto out;
470
 
        }
471
 
        if (is_delete) {
472
 
                error = -ENOENT;
473
 
                goto out;
474
 
        }
475
 
        new_entry = tomoyo_alloc_element(sizeof(*new_entry));
476
 
        if (!new_entry)
477
 
                goto out;
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);
483
 
        error = 0;
484
 
 out:
485
 
        up_write(&tomoyo_domain_keeper_list_lock);
486
 
        return error;
487
 
}
488
 
 
489
 
/**
490
 
 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
491
 
 *
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.
495
 
 *
496
 
 */
497
 
int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
498
 
                                      const bool is_delete)
499
 
{
500
 
        char *cp = strstr(data, " from ");
501
 
 
502
 
        if (cp) {
503
 
                *cp = '\0';
504
 
                return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
505
 
                                                         is_delete);
506
 
        }
507
 
        return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
508
 
}
509
 
 
510
 
/**
511
 
 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
512
 
 *
513
 
 * @head: Pointer to "struct tomoyo_io_buffer".
514
 
 *
515
 
 * Returns true on success, false otherwise.
516
 
 */
517
 
bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
518
 
{
519
 
        struct list_head *pos;
520
 
        bool done = true;
521
 
 
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;
526
 
                const char *no;
527
 
                const char *from = "";
528
 
                const char *program = "";
529
 
 
530
 
                ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
531
 
                if (ptr->is_deleted)
532
 
                        continue;
533
 
                no = ptr->is_not ? "no_" : "";
534
 
                if (ptr->program) {
535
 
                        from = " from ";
536
 
                        program = ptr->program->name;
537
 
                }
538
 
                done = tomoyo_io_printf(head,
539
 
                                        "%s" TOMOYO_KEYWORD_KEEP_DOMAIN
540
 
                                        "%s%s%s\n", no, program, from,
541
 
                                        ptr->domainname->name);
542
 
                if (!done)
543
 
                        break;
544
 
        }
545
 
        up_read(&tomoyo_domain_keeper_list_lock);
546
 
        return done;
547
 
}
548
 
 
549
 
/**
550
 
 * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
551
 
 *
552
 
 * @domainname: The name of domain.
553
 
 * @program:    The name of program.
554
 
 * @last_name:  The last component of @domainname.
555
 
 *
556
 
 * Returns true if executing @program supresses domain transition,
557
 
 * false otherwise.
558
 
 */
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)
562
 
{
563
 
        struct tomoyo_domain_keeper_entry *ptr;
564
 
        bool flag = false;
565
 
 
566
 
        down_read(&tomoyo_domain_keeper_list_lock);
567
 
        list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
568
 
                if (ptr->is_deleted)
569
 
                        continue;
570
 
                if (!ptr->is_last_name) {
571
 
                        if (ptr->domainname != domainname)
572
 
                                continue;
573
 
                } else {
574
 
                        if (tomoyo_pathcmp(ptr->domainname, last_name))
575
 
                                continue;
576
 
                }
577
 
                if (ptr->program && tomoyo_pathcmp(ptr->program, program))
578
 
                        continue;
579
 
                if (ptr->is_not) {
580
 
                        flag = false;
581
 
                        break;
582
 
                }
583
 
                flag = true;
584
 
        }
585
 
        up_read(&tomoyo_domain_keeper_list_lock);
586
 
        return flag;
587
 
}
588
 
 
589
 
/*
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.
599
 
 *
600
 
 * An entry is added by
601
 
 *
602
 
 * # echo 'alias /bin/busybox /bin/cat' > \
603
 
 *                            /sys/kernel/security/tomoyo/exception_policy
604
 
 *
605
 
 * and is deleted by
606
 
 *
607
 
 * # echo 'delete alias /bin/busybox /bin/cat' > \
608
 
 *                            /sys/kernel/security/tomoyo/exception_policy
609
 
 *
610
 
 * and all entries are retrieved by
611
 
 *
612
 
 * # grep ^alias /sys/kernel/security/tomoyo/exception_policy
613
 
 *
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 .
618
 
 */
619
 
static LIST_HEAD(tomoyo_alias_list);
620
 
static DECLARE_RWSEM(tomoyo_alias_list_lock);
621
 
 
622
 
/**
623
 
 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
624
 
 *
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.
628
 
 *
629
 
 * Returns 0 on success, negative value otherwise.
630
 
 */
631
 
static int tomoyo_update_alias_entry(const char *original_name,
632
 
                                     const char *aliased_name,
633
 
                                     const bool is_delete)
634
 
{
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;
639
 
        int error = -ENOMEM;
640
 
 
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)
647
 
                return -ENOMEM;
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)
652
 
                        continue;
653
 
                ptr->is_deleted = is_delete;
654
 
                error = 0;
655
 
                goto out;
656
 
        }
657
 
        if (is_delete) {
658
 
                error = -ENOENT;
659
 
                goto out;
660
 
        }
661
 
        new_entry = tomoyo_alloc_element(sizeof(*new_entry));
662
 
        if (!new_entry)
663
 
                goto out;
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);
667
 
        error = 0;
668
 
 out:
669
 
        up_write(&tomoyo_alias_list_lock);
670
 
        return error;
671
 
}
672
 
 
673
 
/**
674
 
 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
675
 
 *
676
 
 * @head: Pointer to "struct tomoyo_io_buffer".
677
 
 *
678
 
 * Returns true on success, false otherwise.
679
 
 */
680
 
bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
681
 
{
682
 
        struct list_head *pos;
683
 
        bool done = true;
684
 
 
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;
688
 
 
689
 
                ptr = list_entry(pos, struct tomoyo_alias_entry, list);
690
 
                if (ptr->is_deleted)
691
 
                        continue;
692
 
                done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
693
 
                                        ptr->original_name->name,
694
 
                                        ptr->aliased_name->name);
695
 
                if (!done)
696
 
                        break;
697
 
        }
698
 
        up_read(&tomoyo_alias_list_lock);
699
 
        return done;
700
 
}
701
 
 
702
 
/**
703
 
 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
704
 
 *
705
 
 * @data:      String to parse.
706
 
 * @is_delete: True if it is a delete request.
707
 
 *
708
 
 * Returns 0 on success, negative value otherwise.
709
 
 */
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. */
 
325
                goto out;
 
326
        error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
 
327
                                     &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR],
 
328
                                     tomoyo_same_aggregator);
 
329
 out:
 
330
        tomoyo_put_name(e.original_name);
 
331
        tomoyo_put_name(e.aggregated_name);
 
332
        return error;
 
333
}
 
334
 
 
335
/**
 
336
 * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
 
337
 *
 
338
 * @data:      String to parse.
 
339
 * @is_delete: True if it is a delete request.
 
340
 *
 
341
 * Returns 0 on success, negative value otherwise.
 
342
 *
 
343
 * Caller holds tomoyo_read_lock().
 
344
 */
 
345
int tomoyo_write_aggregator(char *data, const bool is_delete)
711
346
{
712
347
        char *cp = strchr(data, ' ');
713
348
 
714
349
        if (!cp)
715
350
                return -EINVAL;
716
351
        *cp++ = '\0';
717
 
        return tomoyo_update_alias_entry(data, cp, is_delete);
 
352
        return tomoyo_update_aggregator_entry(data, cp, is_delete);
718
353
}
719
354
 
720
355
/**
721
 
 * tomoyo_find_or_assign_new_domain - Create a domain.
 
356
 * tomoyo_assign_domain - Create a domain.
722
357
 *
723
358
 * @domainname: The name of domain.
724
359
 * @profile:    Profile number to assign if the domain was newly created.
725
360
 *
726
361
 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
 
362
 *
 
363
 * Caller holds tomoyo_read_lock().
727
364
 */
728
 
struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
729
 
                                                            domainname,
730
 
                                                            const u8 profile)
 
365
struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
 
366
                                                const u8 profile)
731
367
{
 
368
        struct tomoyo_domain_info *entry;
732
369
        struct tomoyo_domain_info *domain = NULL;
733
370
        const struct tomoyo_path_info *saved_domainname;
 
371
        bool found = false;
734
372
 
735
 
        down_write(&tomoyo_domain_list_lock);
736
 
        domain = tomoyo_find_domain(domainname);
737
 
        if (domain)
738
 
                goto out;
739
 
        if (!tomoyo_is_correct_domain(domainname, __func__))
740
 
                goto out;
741
 
        saved_domainname = tomoyo_save_name(domainname);
 
373
        if (!tomoyo_correct_domain(domainname))
 
374
                return NULL;
 
375
        saved_domainname = tomoyo_get_name(domainname);
742
376
        if (!saved_domainname)
743
 
                goto out;
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;
748
 
                bool flag;
749
 
                if (!domain->is_deleted ||
750
 
                    domain->domainname != saved_domainname)
751
 
                        continue;
752
 
                flag = false;
753
 
                read_lock(&tasklist_lock);
754
 
                for_each_process(p) {
755
 
                        if (tomoyo_real_domain(p) != domain)
756
 
                                continue;
757
 
                        flag = true;
758
 
                        break;
759
 
                }
760
 
                read_unlock(&tasklist_lock);
761
 
                if (flag)
762
 
                        continue;
763
 
                list_for_each_entry(ptr, &domain->acl_info_list, list) {
764
 
                        ptr->type |= TOMOYO_ACL_DELETED;
765
 
                }
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;
771
 
                goto out;
772
 
        }
773
 
        /* No memory reusable. Create using new memory. */
774
 
        domain = tomoyo_alloc_element(sizeof(*domain));
775
 
        if (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);
780
 
        }
 
377
                return NULL;
 
378
        entry = kzalloc(sizeof(*entry), GFP_NOFS);
 
379
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
 
380
                goto out;
 
381
        list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
 
382
                if (domain->is_deleted ||
 
383
                    tomoyo_pathcmp(saved_domainname, domain->domainname))
 
384
                        continue;
 
385
                found = true;
 
386
                break;
 
387
        }
 
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);
 
394
                domain = entry;
 
395
                entry = NULL;
 
396
                found = true;
 
397
        }
 
398
        mutex_unlock(&tomoyo_policy_lock);
781
399
 out:
782
 
        up_write(&tomoyo_domain_list_lock);
783
 
        return domain;
 
400
        tomoyo_put_name(saved_domainname);
 
401
        kfree(entry);
 
402
        return found ? domain : NULL;
784
403
}
785
404
 
786
405
/**
789
408
 * @bprm: Pointer to "struct linux_binprm".
790
409
 *
791
410
 * Returns 0 on success, negative value otherwise.
 
411
 *
 
412
 * Caller holds tomoyo_read_lock().
792
413
 */
793
414
int tomoyo_find_next_domain(struct linux_binprm *bprm)
794
415
{
795
 
        /*
796
 
         * This function assumes that the size of buffer returned by
797
 
         * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
798
 
         */
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);
 
421
        u8 mode;
 
422
        bool is_enforce;
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 */
814
426
 
 
427
        mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
 
428
        is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
815
429
        if (!tmp)
816
430
                goto out;
817
431
 
818
 
        if (!initialized) {
819
 
                /*
820
 
                 * Built-in initializers. This is needed because policies are
821
 
                 * not loaded until starting /sbin/init.
822
 
                 */
823
 
                tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
824
 
                                                       false, false);
825
 
                tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
826
 
                                                       false, false);
827
 
                initialized = true;
 
432
 retry:
 
433
        if (need_kfree) {
 
434
                kfree(rn.name);
 
435
                need_kfree = false;
828
436
        }
829
 
 
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)
835
 
                goto out;
836
 
        /* Get tomoyo_realpath of symbolic link. */
837
 
        symlink_program_name = tomoyo_realpath_nofollow(original_name);
838
 
        if (!symlink_program_name)
839
 
                goto out;
840
 
 
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);
847
 
 
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);
 
440
        if (!rn.name)
 
441
                goto out;
 
442
        tomoyo_fill_path_info(&rn);
 
443
        need_kfree = true;
 
444
 
 
445
        /* Check 'aggregator' directive. */
 
446
        {
 
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,
 
452
                                                         ptr->original_name))
857
453
                                continue;
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);
 
454
                        kfree(rn.name);
 
455
                        need_kfree = false;
 
456
                        /* This is OK because it is read only. */
 
457
                        rn = *ptr->aggregated_name;
862
458
                        break;
863
459
                }
864
 
                up_read(&tomoyo_alias_list_lock);
865
460
        }
866
461
 
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)
 
465
                goto retry;
869
466
        if (retval < 0)
870
467
                goto out;
 
468
        /*
 
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).
 
473
         */
 
474
        if (r.param.path.matched_path) {
 
475
                if (need_kfree)
 
476
                        kfree(rn.name);
 
477
                need_kfree = false;
 
478
                /* This is OK because it is read only. */
 
479
                rn = *r.param.path.matched_path;
 
480
        }
871
481
 
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) {
879
 
                /*
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.
883
 
                 */
884
 
                domain = old_domain;
885
 
        } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
 
486
                snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, TOMOYO_ROOT_NAME " "
 
487
                         "%s", rn.name);
 
488
                break;
 
489
        case TOMOYO_TRANSITION_CONTROL_KEEP:
886
490
                /* Keep current domain. */
887
491
                domain = old_domain;
888
 
        } else {
889
 
                /* Normal domain transition. */
890
 
                snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
891
 
                         "%s %s", old_domain_name, real_program_name);
 
492
                break;
 
493
        default:
 
494
                if (old_domain == &tomoyo_kernel_domain &&
 
495
                    !tomoyo_policy_loaded) {
 
496
                        /*
 
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
 
500
                         * before /sbin/init.
 
501
                         */
 
502
                        domain = old_domain;
 
503
                } else {
 
504
                        /* Normal domain transition. */
 
505
                        snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
 
506
                                 old_domain->domainname->name, rn.name);
 
507
                }
 
508
                break;
892
509
        }
893
 
        if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
 
510
        if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
894
511
                goto done;
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);
898
513
        if (domain)
899
514
                goto done;
900
 
        if (is_enforce)
901
 
                goto done;
902
 
        domain = tomoyo_find_or_assign_new_domain(new_domain_name,
903
 
                                                  old_domain->profile);
 
515
        if (is_enforce) {
 
516
                int error = tomoyo_supervisor(&r, "# wants to create domain\n"
 
517
                                              "%s\n", tmp);
 
518
                if (error == TOMOYO_RETRY_REQUEST)
 
519
                        goto retry;
 
520
                if (error < 0)
 
521
                        goto done;
 
522
        }
 
523
        domain = tomoyo_assign_domain(tmp, old_domain->profile);
904
524
 done:
905
525
        if (domain)
906
526
                goto out;
907
 
        printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
908
 
               new_domain_name);
 
527
        printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
909
528
        if (is_enforce)
910
529
                retval = -EPERM;
911
530
        else
912
 
                tomoyo_set_domain_flag(old_domain, false,
913
 
                                       TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
 
531
                old_domain->transition_failed = true;
914
532
 out:
915
533
        if (!domain)
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);
920
 
        tomoyo_free(tmp);
 
538
        if (need_kfree)
 
539
                kfree(rn.name);
 
540
        kfree(tmp);
921
541
        return retval;
922
542
}