aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo/file.c')
-rw-r--r--security/tomoyo/file.c1533
1 files changed, 712 insertions, 821 deletions
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 1c6f8238ec4..9d32f182301 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -1,48 +1,88 @@
1/* 1/*
2 * security/tomoyo/file.c 2 * security/tomoyo/file.c
3 * 3 *
4 * Implementation of the Domain-Based Mandatory Access Control. 4 * Pathname restriction functions.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0 2009/04/01
9 * 5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
10 */ 7 */
11 8
12#include "common.h" 9#include "common.h"
13#include <linux/slab.h> 10#include <linux/slab.h>
14 11
15/* Keyword array for single path operations. */ 12/* Keyword array for operations with one pathname. */
16static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { 13const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = {
17 [TOMOYO_TYPE_READ_WRITE] = "read/write", 14 [TOMOYO_TYPE_READ_WRITE] = "read/write",
18 [TOMOYO_TYPE_EXECUTE] = "execute", 15 [TOMOYO_TYPE_EXECUTE] = "execute",
19 [TOMOYO_TYPE_READ] = "read", 16 [TOMOYO_TYPE_READ] = "read",
20 [TOMOYO_TYPE_WRITE] = "write", 17 [TOMOYO_TYPE_WRITE] = "write",
21 [TOMOYO_TYPE_CREATE] = "create",
22 [TOMOYO_TYPE_UNLINK] = "unlink", 18 [TOMOYO_TYPE_UNLINK] = "unlink",
23 [TOMOYO_TYPE_MKDIR] = "mkdir",
24 [TOMOYO_TYPE_RMDIR] = "rmdir", 19 [TOMOYO_TYPE_RMDIR] = "rmdir",
25 [TOMOYO_TYPE_MKFIFO] = "mkfifo",
26 [TOMOYO_TYPE_MKSOCK] = "mksock",
27 [TOMOYO_TYPE_MKBLOCK] = "mkblock",
28 [TOMOYO_TYPE_MKCHAR] = "mkchar",
29 [TOMOYO_TYPE_TRUNCATE] = "truncate", 20 [TOMOYO_TYPE_TRUNCATE] = "truncate",
30 [TOMOYO_TYPE_SYMLINK] = "symlink", 21 [TOMOYO_TYPE_SYMLINK] = "symlink",
31 [TOMOYO_TYPE_REWRITE] = "rewrite", 22 [TOMOYO_TYPE_REWRITE] = "rewrite",
23 [TOMOYO_TYPE_CHROOT] = "chroot",
24 [TOMOYO_TYPE_UMOUNT] = "unmount",
25};
26
27/* Keyword array for operations with one pathname and three numbers. */
28const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION] = {
29 [TOMOYO_TYPE_MKBLOCK] = "mkblock",
30 [TOMOYO_TYPE_MKCHAR] = "mkchar",
31};
32
33/* Keyword array for operations with two pathnames. */
34const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = {
35 [TOMOYO_TYPE_LINK] = "link",
36 [TOMOYO_TYPE_RENAME] = "rename",
37 [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root",
38};
39
40/* Keyword array for operations with one pathname and one number. */
41const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
42 [TOMOYO_TYPE_CREATE] = "create",
43 [TOMOYO_TYPE_MKDIR] = "mkdir",
44 [TOMOYO_TYPE_MKFIFO] = "mkfifo",
45 [TOMOYO_TYPE_MKSOCK] = "mksock",
32 [TOMOYO_TYPE_IOCTL] = "ioctl", 46 [TOMOYO_TYPE_IOCTL] = "ioctl",
33 [TOMOYO_TYPE_CHMOD] = "chmod", 47 [TOMOYO_TYPE_CHMOD] = "chmod",
34 [TOMOYO_TYPE_CHOWN] = "chown", 48 [TOMOYO_TYPE_CHOWN] = "chown",
35 [TOMOYO_TYPE_CHGRP] = "chgrp", 49 [TOMOYO_TYPE_CHGRP] = "chgrp",
36 [TOMOYO_TYPE_CHROOT] = "chroot",
37 [TOMOYO_TYPE_MOUNT] = "mount",
38 [TOMOYO_TYPE_UMOUNT] = "unmount",
39}; 50};
40 51
41/* Keyword array for double path operations. */ 52static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
42static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { 53 [TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN,
43 [TOMOYO_TYPE_LINK] = "link", 54 [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE,
44 [TOMOYO_TYPE_RENAME] = "rename", 55 [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN,
45 [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", 56 [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN,
57 [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK,
58 [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR,
59 [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE,
60 [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK,
61 [TOMOYO_TYPE_REWRITE] = TOMOYO_MAC_FILE_REWRITE,
62 [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT,
63 [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT,
64};
65
66static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
67 [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
68 [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR,
69};
70
71static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
72 [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK,
73 [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME,
74 [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
75};
76
77static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
78 [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
79 [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR,
80 [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
81 [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
82 [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL,
83 [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD,
84 [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN,
85 [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP,
46}; 86};
47 87
48void tomoyo_put_name_union(struct tomoyo_name_union *ptr) 88void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
@@ -50,56 +90,45 @@ void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
50 if (!ptr) 90 if (!ptr)
51 return; 91 return;
52 if (ptr->is_group) 92 if (ptr->is_group)
53 tomoyo_put_path_group(ptr->group); 93 tomoyo_put_group(ptr->group);
54 else 94 else
55 tomoyo_put_name(ptr->filename); 95 tomoyo_put_name(ptr->filename);
56} 96}
57 97
58bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, 98const struct tomoyo_path_info *
59 const struct tomoyo_name_union *ptr) 99tomoyo_compare_name_union(const struct tomoyo_path_info *name,
100 const struct tomoyo_name_union *ptr)
60{ 101{
61 if (ptr->is_group) 102 if (ptr->is_group)
62 return tomoyo_path_matches_group(name, ptr->group, 1); 103 return tomoyo_path_matches_group(name, ptr->group);
63 return tomoyo_path_matches_pattern(name, ptr->filename); 104 if (tomoyo_path_matches_pattern(name, ptr->filename))
105 return ptr->filename;
106 return NULL;
64} 107}
65 108
66static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info 109void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
67 *name,
68 const struct tomoyo_name_union
69 *ptr, const bool may_use_pattern)
70{ 110{
71 if (ptr->is_group) 111 if (ptr && ptr->is_group)
72 return tomoyo_path_matches_group(name, ptr->group, 112 tomoyo_put_group(ptr->group);
73 may_use_pattern);
74 if (may_use_pattern || !ptr->filename->is_patterned)
75 return tomoyo_path_matches_pattern(name, ptr->filename);
76 return false;
77} 113}
78 114
79/** 115bool tomoyo_compare_number_union(const unsigned long value,
80 * tomoyo_path2keyword - Get the name of single path operation. 116 const struct tomoyo_number_union *ptr)
81 *
82 * @operation: Type of operation.
83 *
84 * Returns the name of single path operation.
85 */
86const char *tomoyo_path2keyword(const u8 operation)
87{ 117{
88 return (operation < TOMOYO_MAX_PATH_OPERATION) 118 if (ptr->is_group)
89 ? tomoyo_path_keyword[operation] : NULL; 119 return tomoyo_number_matches_group(value, value, ptr->group);
120 return value >= ptr->values[0] && value <= ptr->values[1];
90} 121}
91 122
92/** 123static void tomoyo_add_slash(struct tomoyo_path_info *buf)
93 * tomoyo_path22keyword - Get the name of double path operation.
94 *
95 * @operation: Type of operation.
96 *
97 * Returns the name of double path operation.
98 */
99const char *tomoyo_path22keyword(const u8 operation)
100{ 124{
101 return (operation < TOMOYO_MAX_PATH2_OPERATION) 125 if (buf->is_dir)
102 ? tomoyo_path2_keyword[operation] : NULL; 126 return;
127 /*
128 * This is OK because tomoyo_encode() reserves space for appending "/".
129 */
130 strcat((char *) buf->name, "/");
131 tomoyo_fill_path_info(buf);
103} 132}
104 133
105/** 134/**
@@ -121,69 +150,134 @@ static bool tomoyo_strendswith(const char *name, const char *tail)
121} 150}
122 151
123/** 152/**
124 * tomoyo_get_path - Get realpath. 153 * tomoyo_get_realpath - Get realpath.
125 * 154 *
155 * @buf: Pointer to "struct tomoyo_path_info".
126 * @path: Pointer to "struct path". 156 * @path: Pointer to "struct path".
127 * 157 *
128 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. 158 * Returns true on success, false otherwise.
129 */ 159 */
130static struct tomoyo_path_info *tomoyo_get_path(struct path *path) 160static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
131{ 161{
132 int error; 162 buf->name = tomoyo_realpath_from_path(path);
133 struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), 163 if (buf->name) {
134 GFP_NOFS); 164 tomoyo_fill_path_info(buf);
135 165 return true;
136 if (!buf)
137 return NULL;
138 /* Reserve one byte for appending "/". */
139 error = tomoyo_realpath_from_path2(path, buf->body,
140 sizeof(buf->body) - 2);
141 if (!error) {
142 buf->head.name = buf->body;
143 tomoyo_fill_path_info(&buf->head);
144 return &buf->head;
145 } 166 }
146 kfree(buf); 167 return false;
147 return NULL;
148} 168}
149 169
150static int tomoyo_update_path2_acl(const u8 type, const char *filename1, 170/**
151 const char *filename2, 171 * tomoyo_audit_path_log - Audit path request log.
152 struct tomoyo_domain_info *const domain, 172 *
153 const bool is_delete); 173 * @r: Pointer to "struct tomoyo_request_info".
154static int tomoyo_update_path_acl(const u8 type, const char *filename,
155 struct tomoyo_domain_info *const domain,
156 const bool is_delete);
157
158/*
159 * tomoyo_globally_readable_list is used for holding list of pathnames which
160 * are by default allowed to be open()ed for reading by any process.
161 * 174 *
162 * An entry is added by 175 * Returns 0 on success, negative value otherwise.
176 */
177static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
178{
179 const char *operation = tomoyo_path_keyword[r->param.path.operation];
180 const struct tomoyo_path_info *filename = r->param.path.filename;
181 if (r->granted)
182 return 0;
183 tomoyo_warn_log(r, "%s %s", operation, filename->name);
184 return tomoyo_supervisor(r, "allow_%s %s\n", operation,
185 tomoyo_pattern(filename));
186}
187
188/**
189 * tomoyo_audit_path2_log - Audit path/path request log.
163 * 190 *
164 * # echo 'allow_read /lib/libc-2.5.so' > \ 191 * @r: Pointer to "struct tomoyo_request_info".
165 * /sys/kernel/security/tomoyo/exception_policy
166 * 192 *
167 * and is deleted by 193 * Returns 0 on success, negative value otherwise.
194 */
195static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
196{
197 const char *operation = tomoyo_path2_keyword[r->param.path2.operation];
198 const struct tomoyo_path_info *filename1 = r->param.path2.filename1;
199 const struct tomoyo_path_info *filename2 = r->param.path2.filename2;
200 if (r->granted)
201 return 0;
202 tomoyo_warn_log(r, "%s %s %s", operation, filename1->name,
203 filename2->name);
204 return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
205 tomoyo_pattern(filename1),
206 tomoyo_pattern(filename2));
207}
208
209/**
210 * tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
168 * 211 *
169 * # echo 'delete allow_read /lib/libc-2.5.so' > \ 212 * @r: Pointer to "struct tomoyo_request_info".
170 * /sys/kernel/security/tomoyo/exception_policy
171 * 213 *
172 * and all entries are retrieved by 214 * Returns 0 on success, negative value otherwise.
215 */
216static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
217{
218 const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation];
219 const struct tomoyo_path_info *filename = r->param.mkdev.filename;
220 const unsigned int major = r->param.mkdev.major;
221 const unsigned int minor = r->param.mkdev.minor;
222 const unsigned int mode = r->param.mkdev.mode;
223 if (r->granted)
224 return 0;
225 tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode,
226 major, minor);
227 return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation,
228 tomoyo_pattern(filename), mode, major, minor);
229}
230
231/**
232 * tomoyo_audit_path_number_log - Audit path/number request log.
173 * 233 *
174 * # grep ^allow_read /sys/kernel/security/tomoyo/exception_policy 234 * @r: Pointer to "struct tomoyo_request_info".
235 * @error: Error code.
175 * 236 *
176 * In the example above, any process is allowed to 237 * Returns 0 on success, negative value otherwise.
177 * open("/lib/libc-2.5.so", O_RDONLY).
178 * One exception is, if the domain which current process belongs to is marked
179 * as "ignore_global_allow_read", current process can't do so unless explicitly
180 * given "allow_read /lib/libc-2.5.so" to the domain which current process
181 * belongs to.
182 */ 238 */
183LIST_HEAD(tomoyo_globally_readable_list); 239static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
240{
241 const u8 type = r->param.path_number.operation;
242 u8 radix;
243 const struct tomoyo_path_info *filename = r->param.path_number.filename;
244 const char *operation = tomoyo_path_number_keyword[type];
245 char buffer[64];
246 if (r->granted)
247 return 0;
248 switch (type) {
249 case TOMOYO_TYPE_CREATE:
250 case TOMOYO_TYPE_MKDIR:
251 case TOMOYO_TYPE_MKFIFO:
252 case TOMOYO_TYPE_MKSOCK:
253 case TOMOYO_TYPE_CHMOD:
254 radix = TOMOYO_VALUE_TYPE_OCTAL;
255 break;
256 case TOMOYO_TYPE_IOCTL:
257 radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
258 break;
259 default:
260 radix = TOMOYO_VALUE_TYPE_DECIMAL;
261 break;
262 }
263 tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
264 radix);
265 tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer);
266 return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
267 tomoyo_pattern(filename), buffer);
268}
269
270static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a,
271 const struct tomoyo_acl_head *b)
272{
273 return container_of(a, struct tomoyo_readable_file,
274 head)->filename ==
275 container_of(b, struct tomoyo_readable_file,
276 head)->filename;
277}
184 278
185/** 279/**
186 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. 280 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_readable_file" list.
187 * 281 *
188 * @filename: Filename unconditionally permitted to open() for reading. 282 * @filename: Filename unconditionally permitted to open() for reading.
189 * @is_delete: True if it is a delete request. 283 * @is_delete: True if it is a delete request.
@@ -195,41 +289,24 @@ LIST_HEAD(tomoyo_globally_readable_list);
195static int tomoyo_update_globally_readable_entry(const char *filename, 289static int tomoyo_update_globally_readable_entry(const char *filename,
196 const bool is_delete) 290 const bool is_delete)
197{ 291{
198 struct tomoyo_globally_readable_file_entry *ptr; 292 struct tomoyo_readable_file e = { };
199 struct tomoyo_globally_readable_file_entry e = { }; 293 int error;
200 int error = is_delete ? -ENOENT : -ENOMEM;
201 294
202 if (!tomoyo_is_correct_path(filename, 1, 0, -1)) 295 if (!tomoyo_correct_word(filename))
203 return -EINVAL; 296 return -EINVAL;
204 e.filename = tomoyo_get_name(filename); 297 e.filename = tomoyo_get_name(filename);
205 if (!e.filename) 298 if (!e.filename)
206 return -ENOMEM; 299 return -ENOMEM;
207 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 300 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
208 goto out; 301 &tomoyo_policy_list
209 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { 302 [TOMOYO_ID_GLOBALLY_READABLE],
210 if (ptr->filename != e.filename) 303 tomoyo_same_globally_readable);
211 continue;
212 ptr->is_deleted = is_delete;
213 error = 0;
214 break;
215 }
216 if (!is_delete && error) {
217 struct tomoyo_globally_readable_file_entry *entry =
218 tomoyo_commit_ok(&e, sizeof(e));
219 if (entry) {
220 list_add_tail_rcu(&entry->list,
221 &tomoyo_globally_readable_list);
222 error = 0;
223 }
224 }
225 mutex_unlock(&tomoyo_policy_lock);
226 out:
227 tomoyo_put_name(e.filename); 304 tomoyo_put_name(e.filename);
228 return error; 305 return error;
229} 306}
230 307
231/** 308/**
232 * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading. 309 * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
233 * 310 *
234 * @filename: The filename to check. 311 * @filename: The filename to check.
235 * 312 *
@@ -237,14 +314,15 @@ static int tomoyo_update_globally_readable_entry(const char *filename,
237 * 314 *
238 * Caller holds tomoyo_read_lock(). 315 * Caller holds tomoyo_read_lock().
239 */ 316 */
240static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * 317static bool tomoyo_globally_readable_file(const struct tomoyo_path_info *
241 filename) 318 filename)
242{ 319{
243 struct tomoyo_globally_readable_file_entry *ptr; 320 struct tomoyo_readable_file *ptr;
244 bool found = false; 321 bool found = false;
245 322
246 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { 323 list_for_each_entry_rcu(ptr, &tomoyo_policy_list
247 if (!ptr->is_deleted && 324 [TOMOYO_ID_GLOBALLY_READABLE], head.list) {
325 if (!ptr->head.is_deleted &&
248 tomoyo_path_matches_pattern(filename, ptr->filename)) { 326 tomoyo_path_matches_pattern(filename, ptr->filename)) {
249 found = true; 327 found = true;
250 break; 328 break;
@@ -254,7 +332,7 @@ static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
254} 332}
255 333
256/** 334/**
257 * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list. 335 * tomoyo_write_globally_readable - Write "struct tomoyo_readable_file" list.
258 * 336 *
259 * @data: String to parse. 337 * @data: String to parse.
260 * @is_delete: True if it is a delete request. 338 * @is_delete: True if it is a delete request.
@@ -263,74 +341,20 @@ static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
263 * 341 *
264 * Caller holds tomoyo_read_lock(). 342 * Caller holds tomoyo_read_lock().
265 */ 343 */
266int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) 344int tomoyo_write_globally_readable(char *data, const bool is_delete)
267{ 345{
268 return tomoyo_update_globally_readable_entry(data, is_delete); 346 return tomoyo_update_globally_readable_entry(data, is_delete);
269} 347}
270 348
271/** 349static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a,
272 * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list. 350 const struct tomoyo_acl_head *b)
273 *
274 * @head: Pointer to "struct tomoyo_io_buffer".
275 *
276 * Returns true on success, false otherwise.
277 *
278 * Caller holds tomoyo_read_lock().
279 */
280bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
281{ 351{
282 struct list_head *pos; 352 return container_of(a, struct tomoyo_no_pattern, head)->pattern ==
283 bool done = true; 353 container_of(b, struct tomoyo_no_pattern, head)->pattern;
284
285 list_for_each_cookie(pos, head->read_var2,
286 &tomoyo_globally_readable_list) {
287 struct tomoyo_globally_readable_file_entry *ptr;
288 ptr = list_entry(pos,
289 struct tomoyo_globally_readable_file_entry,
290 list);
291 if (ptr->is_deleted)
292 continue;
293 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
294 ptr->filename->name);
295 if (!done)
296 break;
297 }
298 return done;
299} 354}
300 355
301/* tomoyo_pattern_list is used for holding list of pathnames which are used for
302 * converting pathnames to pathname patterns during learning mode.
303 *
304 * An entry is added by
305 *
306 * # echo 'file_pattern /proc/\$/mounts' > \
307 * /sys/kernel/security/tomoyo/exception_policy
308 *
309 * and is deleted by
310 *
311 * # echo 'delete file_pattern /proc/\$/mounts' > \
312 * /sys/kernel/security/tomoyo/exception_policy
313 *
314 * and all entries are retrieved by
315 *
316 * # grep ^file_pattern /sys/kernel/security/tomoyo/exception_policy
317 *
318 * In the example above, if a process which belongs to a domain which is in
319 * learning mode requested open("/proc/1/mounts", O_RDONLY),
320 * "allow_read /proc/\$/mounts" is automatically added to the domain which that
321 * process belongs to.
322 *
323 * It is not a desirable behavior that we have to use /proc/\$/ instead of
324 * /proc/self/ when current process needs to access only current process's
325 * information. As of now, LSM version of TOMOYO is using __d_path() for
326 * calculating pathname. Non LSM version of TOMOYO is using its own function
327 * which pretends as if /proc/self/ is not a symlink; so that we can forbid
328 * current process from accessing other process's information.
329 */
330LIST_HEAD(tomoyo_pattern_list);
331
332/** 356/**
333 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. 357 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_no_pattern" list.
334 * 358 *
335 * @pattern: Pathname pattern. 359 * @pattern: Pathname pattern.
336 * @is_delete: True if it is a delete request. 360 * @is_delete: True if it is a delete request.
@@ -342,39 +366,23 @@ LIST_HEAD(tomoyo_pattern_list);
342static int tomoyo_update_file_pattern_entry(const char *pattern, 366static int tomoyo_update_file_pattern_entry(const char *pattern,
343 const bool is_delete) 367 const bool is_delete)
344{ 368{
345 struct tomoyo_pattern_entry *ptr; 369 struct tomoyo_no_pattern e = { };
346 struct tomoyo_pattern_entry e = { .pattern = tomoyo_get_name(pattern) }; 370 int error;
347 int error = is_delete ? -ENOENT : -ENOMEM;
348 371
372 if (!tomoyo_correct_word(pattern))
373 return -EINVAL;
374 e.pattern = tomoyo_get_name(pattern);
349 if (!e.pattern) 375 if (!e.pattern)
350 return error; 376 return -ENOMEM;
351 if (!e.pattern->is_patterned) 377 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
352 goto out; 378 &tomoyo_policy_list[TOMOYO_ID_PATTERN],
353 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 379 tomoyo_same_pattern);
354 goto out;
355 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
356 if (e.pattern != ptr->pattern)
357 continue;
358 ptr->is_deleted = is_delete;
359 error = 0;
360 break;
361 }
362 if (!is_delete && error) {
363 struct tomoyo_pattern_entry *entry =
364 tomoyo_commit_ok(&e, sizeof(e));
365 if (entry) {
366 list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
367 error = 0;
368 }
369 }
370 mutex_unlock(&tomoyo_policy_lock);
371 out:
372 tomoyo_put_name(e.pattern); 380 tomoyo_put_name(e.pattern);
373 return error; 381 return error;
374} 382}
375 383
376/** 384/**
377 * tomoyo_get_file_pattern - Get patterned pathname. 385 * tomoyo_pattern - Get patterned pathname.
378 * 386 *
379 * @filename: The filename to find patterned pathname. 387 * @filename: The filename to find patterned pathname.
380 * 388 *
@@ -382,14 +390,14 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
382 * 390 *
383 * Caller holds tomoyo_read_lock(). 391 * Caller holds tomoyo_read_lock().
384 */ 392 */
385static const struct tomoyo_path_info * 393const char *tomoyo_pattern(const struct tomoyo_path_info *filename)
386tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
387{ 394{
388 struct tomoyo_pattern_entry *ptr; 395 struct tomoyo_no_pattern *ptr;
389 const struct tomoyo_path_info *pattern = NULL; 396 const struct tomoyo_path_info *pattern = NULL;
390 397
391 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { 398 list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN],
392 if (ptr->is_deleted) 399 head.list) {
400 if (ptr->head.is_deleted)
393 continue; 401 continue;
394 if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) 402 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
395 continue; 403 continue;
@@ -403,11 +411,11 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
403 } 411 }
404 if (pattern) 412 if (pattern)
405 filename = pattern; 413 filename = pattern;
406 return filename; 414 return filename->name;
407} 415}
408 416
409/** 417/**
410 * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list. 418 * tomoyo_write_pattern - Write "struct tomoyo_no_pattern" list.
411 * 419 *
412 * @data: String to parse. 420 * @data: String to parse.
413 * @is_delete: True if it is a delete request. 421 * @is_delete: True if it is a delete request.
@@ -416,71 +424,21 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
416 * 424 *
417 * Caller holds tomoyo_read_lock(). 425 * Caller holds tomoyo_read_lock().
418 */ 426 */
419int tomoyo_write_pattern_policy(char *data, const bool is_delete) 427int tomoyo_write_pattern(char *data, const bool is_delete)
420{ 428{
421 return tomoyo_update_file_pattern_entry(data, is_delete); 429 return tomoyo_update_file_pattern_entry(data, is_delete);
422} 430}
423 431
424/** 432static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a,
425 * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list. 433 const struct tomoyo_acl_head *b)
426 *
427 * @head: Pointer to "struct tomoyo_io_buffer".
428 *
429 * Returns true on success, false otherwise.
430 *
431 * Caller holds tomoyo_read_lock().
432 */
433bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
434{ 434{
435 struct list_head *pos; 435 return container_of(a, struct tomoyo_no_rewrite, head)->pattern
436 bool done = true; 436 == container_of(b, struct tomoyo_no_rewrite, head)
437 437 ->pattern;
438 list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
439 struct tomoyo_pattern_entry *ptr;
440 ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
441 if (ptr->is_deleted)
442 continue;
443 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN
444 "%s\n", ptr->pattern->name);
445 if (!done)
446 break;
447 }
448 return done;
449} 438}
450 439
451/*
452 * tomoyo_no_rewrite_list is used for holding list of pathnames which are by
453 * default forbidden to modify already written content of a file.
454 *
455 * An entry is added by
456 *
457 * # echo 'deny_rewrite /var/log/messages' > \
458 * /sys/kernel/security/tomoyo/exception_policy
459 *
460 * and is deleted by
461 *
462 * # echo 'delete deny_rewrite /var/log/messages' > \
463 * /sys/kernel/security/tomoyo/exception_policy
464 *
465 * and all entries are retrieved by
466 *
467 * # grep ^deny_rewrite /sys/kernel/security/tomoyo/exception_policy
468 *
469 * In the example above, if a process requested to rewrite /var/log/messages ,
470 * the process can't rewrite unless the domain which that process belongs to
471 * has "allow_rewrite /var/log/messages" entry.
472 *
473 * It is not a desirable behavior that we have to add "\040(deleted)" suffix
474 * when we want to allow rewriting already unlink()ed file. As of now,
475 * LSM version of TOMOYO is using __d_path() for calculating pathname.
476 * Non LSM version of TOMOYO is using its own function which doesn't append
477 * " (deleted)" suffix if the file is already unlink()ed; so that we don't
478 * need to worry whether the file is already unlink()ed or not.
479 */
480LIST_HEAD(tomoyo_no_rewrite_list);
481
482/** 440/**
483 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. 441 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite" list.
484 * 442 *
485 * @pattern: Pathname pattern that are not rewritable by default. 443 * @pattern: Pathname pattern that are not rewritable by default.
486 * @is_delete: True if it is a delete request. 444 * @is_delete: True if it is a delete request.
@@ -492,41 +450,23 @@ LIST_HEAD(tomoyo_no_rewrite_list);
492static int tomoyo_update_no_rewrite_entry(const char *pattern, 450static int tomoyo_update_no_rewrite_entry(const char *pattern,
493 const bool is_delete) 451 const bool is_delete)
494{ 452{
495 struct tomoyo_no_rewrite_entry *ptr; 453 struct tomoyo_no_rewrite e = { };
496 struct tomoyo_no_rewrite_entry e = { }; 454 int error;
497 int error = is_delete ? -ENOENT : -ENOMEM;
498 455
499 if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) 456 if (!tomoyo_correct_word(pattern))
500 return -EINVAL; 457 return -EINVAL;
501 e.pattern = tomoyo_get_name(pattern); 458 e.pattern = tomoyo_get_name(pattern);
502 if (!e.pattern) 459 if (!e.pattern)
503 return error; 460 return -ENOMEM;
504 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 461 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
505 goto out; 462 &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
506 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 463 tomoyo_same_no_rewrite);
507 if (ptr->pattern != e.pattern)
508 continue;
509 ptr->is_deleted = is_delete;
510 error = 0;
511 break;
512 }
513 if (!is_delete && error) {
514 struct tomoyo_no_rewrite_entry *entry =
515 tomoyo_commit_ok(&e, sizeof(e));
516 if (entry) {
517 list_add_tail_rcu(&entry->list,
518 &tomoyo_no_rewrite_list);
519 error = 0;
520 }
521 }
522 mutex_unlock(&tomoyo_policy_lock);
523 out:
524 tomoyo_put_name(e.pattern); 464 tomoyo_put_name(e.pattern);
525 return error; 465 return error;
526} 466}
527 467
528/** 468/**
529 * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. 469 * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
530 * 470 *
531 * @filename: Filename to check. 471 * @filename: Filename to check.
532 * 472 *
@@ -535,13 +475,14 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern,
535 * 475 *
536 * Caller holds tomoyo_read_lock(). 476 * Caller holds tomoyo_read_lock().
537 */ 477 */
538static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) 478static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename)
539{ 479{
540 struct tomoyo_no_rewrite_entry *ptr; 480 struct tomoyo_no_rewrite *ptr;
541 bool found = false; 481 bool found = false;
542 482
543 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 483 list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
544 if (ptr->is_deleted) 484 head.list) {
485 if (ptr->head.is_deleted)
545 continue; 486 continue;
546 if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) 487 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
547 continue; 488 continue;
@@ -552,7 +493,7 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
552} 493}
553 494
554/** 495/**
555 * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list. 496 * tomoyo_write_no_rewrite - Write "struct tomoyo_no_rewrite" list.
556 * 497 *
557 * @data: String to parse. 498 * @data: String to parse.
558 * @is_delete: True if it is a delete request. 499 * @is_delete: True if it is a delete request.
@@ -561,214 +502,103 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
561 * 502 *
562 * Caller holds tomoyo_read_lock(). 503 * Caller holds tomoyo_read_lock().
563 */ 504 */
564int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) 505int tomoyo_write_no_rewrite(char *data, const bool is_delete)
565{ 506{
566 return tomoyo_update_no_rewrite_entry(data, is_delete); 507 return tomoyo_update_no_rewrite_entry(data, is_delete);
567} 508}
568 509
569/** 510static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
570 * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list. 511 const struct tomoyo_acl_info *ptr)
571 *
572 * @head: Pointer to "struct tomoyo_io_buffer".
573 *
574 * Returns true on success, false otherwise.
575 *
576 * Caller holds tomoyo_read_lock().
577 */
578bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
579{ 512{
580 struct list_head *pos; 513 const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
581 bool done = true; 514 head);
582 515 if (acl->perm & (1 << r->param.path.operation)) {
583 list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) { 516 r->param.path.matched_path =
584 struct tomoyo_no_rewrite_entry *ptr; 517 tomoyo_compare_name_union(r->param.path.filename,
585 ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); 518 &acl->name);
586 if (ptr->is_deleted) 519 return r->param.path.matched_path != NULL;
587 continue;
588 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE
589 "%s\n", ptr->pattern->name);
590 if (!done)
591 break;
592 } 520 }
593 return done; 521 return false;
594} 522}
595 523
596/** 524static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
597 * tomoyo_update_file_acl - Update file's read/write/execute ACL. 525 const struct tomoyo_acl_info *ptr)
598 *
599 * @filename: Filename.
600 * @perm: Permission (between 1 to 7).
601 * @domain: Pointer to "struct tomoyo_domain_info".
602 * @is_delete: True if it is a delete request.
603 *
604 * Returns 0 on success, negative value otherwise.
605 *
606 * This is legacy support interface for older policy syntax.
607 * Current policy syntax uses "allow_read/write" instead of "6",
608 * "allow_read" instead of "4", "allow_write" instead of "2",
609 * "allow_execute" instead of "1".
610 *
611 * Caller holds tomoyo_read_lock().
612 */
613static int tomoyo_update_file_acl(const char *filename, u8 perm,
614 struct tomoyo_domain_info * const domain,
615 const bool is_delete)
616{ 526{
617 if (perm > 7 || !perm) { 527 const struct tomoyo_path_number_acl *acl =
618 printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n", 528 container_of(ptr, typeof(*acl), head);
619 __func__, perm, filename); 529 return (acl->perm & (1 << r->param.path_number.operation)) &&
620 return -EINVAL; 530 tomoyo_compare_number_union(r->param.path_number.number,
621 } 531 &acl->number) &&
622 if (filename[0] != '@' && tomoyo_strendswith(filename, "/")) 532 tomoyo_compare_name_union(r->param.path_number.filename,
623 /* 533 &acl->name);
624 * Only 'allow_mkdir' and 'allow_rmdir' are valid for
625 * directory permissions.
626 */
627 return 0;
628 if (perm & 4)
629 tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain,
630 is_delete);
631 if (perm & 2)
632 tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain,
633 is_delete);
634 if (perm & 1)
635 tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain,
636 is_delete);
637 return 0;
638} 534}
639 535
640/** 536static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
641 * tomoyo_path_acl2 - Check permission for single path operation. 537 const struct tomoyo_acl_info *ptr)
642 *
643 * @domain: Pointer to "struct tomoyo_domain_info".
644 * @filename: Filename to check.
645 * @perm: Permission.
646 * @may_use_pattern: True if patterned ACL is permitted.
647 *
648 * Returns 0 on success, -EPERM otherwise.
649 *
650 * Caller holds tomoyo_read_lock().
651 */
652static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain,
653 const struct tomoyo_path_info *filename,
654 const u32 perm, const bool may_use_pattern)
655{ 538{
656 struct tomoyo_acl_info *ptr; 539 const struct tomoyo_path2_acl *acl =
657 int error = -EPERM; 540 container_of(ptr, typeof(*acl), head);
658 541 return (acl->perm & (1 << r->param.path2.operation)) &&
659 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 542 tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
660 struct tomoyo_path_acl *acl; 543 && tomoyo_compare_name_union(r->param.path2.filename2,
661 if (ptr->type != TOMOYO_TYPE_PATH_ACL) 544 &acl->name2);
662 continue;
663 acl = container_of(ptr, struct tomoyo_path_acl, head);
664 if (perm <= 0xFFFF) {
665 if (!(acl->perm & perm))
666 continue;
667 } else {
668 if (!(acl->perm_high & (perm >> 16)))
669 continue;
670 }
671 if (!tomoyo_compare_name_union_pattern(filename, &acl->name,
672 may_use_pattern))
673 continue;
674 error = 0;
675 break;
676 }
677 return error;
678} 545}
679 546
680/** 547static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
681 * tomoyo_check_file_acl - Check permission for opening files. 548 const struct tomoyo_acl_info *ptr)
682 *
683 * @domain: Pointer to "struct tomoyo_domain_info".
684 * @filename: Filename to check.
685 * @operation: Mode ("read" or "write" or "read/write" or "execute").
686 *
687 * Returns 0 on success, -EPERM otherwise.
688 *
689 * Caller holds tomoyo_read_lock().
690 */
691static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
692 const struct tomoyo_path_info *filename,
693 const u8 operation)
694{ 549{
695 u32 perm = 0; 550 const struct tomoyo_mkdev_acl *acl =
696 551 container_of(ptr, typeof(*acl), head);
697 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) 552 return (acl->perm & (1 << r->param.mkdev.operation)) &&
698 return 0; 553 tomoyo_compare_number_union(r->param.mkdev.mode,
699 if (operation == 6) 554 &acl->mode) &&
700 perm = 1 << TOMOYO_TYPE_READ_WRITE; 555 tomoyo_compare_number_union(r->param.mkdev.major,
701 else if (operation == 4) 556 &acl->major) &&
702 perm = 1 << TOMOYO_TYPE_READ; 557 tomoyo_compare_number_union(r->param.mkdev.minor,
703 else if (operation == 2) 558 &acl->minor) &&
704 perm = 1 << TOMOYO_TYPE_WRITE; 559 tomoyo_compare_name_union(r->param.mkdev.filename,
705 else if (operation == 1) 560 &acl->name);
706 perm = 1 << TOMOYO_TYPE_EXECUTE;
707 else
708 BUG();
709 return tomoyo_path_acl2(domain, filename, perm, operation != 1);
710} 561}
711 562
712/** 563static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
713 * tomoyo_check_file_perm2 - Check permission for opening files. 564 const struct tomoyo_acl_info *b)
714 *
715 * @domain: Pointer to "struct tomoyo_domain_info".
716 * @filename: Filename to check.
717 * @perm: Mode ("read" or "write" or "read/write" or "execute").
718 * @operation: Operation name passed used for verbose mode.
719 * @mode: Access control mode.
720 *
721 * Returns 0 on success, negative value otherwise.
722 *
723 * Caller holds tomoyo_read_lock().
724 */
725static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
726 const struct tomoyo_path_info *filename,
727 const u8 perm, const char *operation,
728 const u8 mode)
729{ 565{
730 const bool is_enforce = (mode == 3); 566 const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
731 const char *msg = "<unknown>"; 567 const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
732 int error = 0; 568 return tomoyo_same_acl_head(&p1->head, &p2->head) &&
569 tomoyo_same_name_union(&p1->name, &p2->name);
570}
733 571
734 if (!filename) 572static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
735 return 0; 573 struct tomoyo_acl_info *b,
736 error = tomoyo_check_file_acl(domain, filename, perm); 574 const bool is_delete)
737 if (error && perm == 4 && !domain->ignore_global_allow_read 575{
738 && tomoyo_is_globally_readable_file(filename)) 576 u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
739 error = 0; 577 ->perm;
740 if (perm == 6) 578 u16 perm = *a_perm;
741 msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE); 579 const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
742 else if (perm == 4) 580 if (is_delete) {
743 msg = tomoyo_path2keyword(TOMOYO_TYPE_READ); 581 perm &= ~b_perm;
744 else if (perm == 2) 582 if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK)
745 msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE); 583 perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
746 else if (perm == 1) 584 else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE)))
747 msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE); 585 perm &= ~TOMOYO_RW_MASK;
748 else 586 } else {
749 BUG(); 587 perm |= b_perm;
750 if (!error) 588 if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK)
751 return 0; 589 perm |= (1 << TOMOYO_TYPE_READ_WRITE);
752 if (tomoyo_verbose_mode(domain)) 590 else if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
753 printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied " 591 perm |= TOMOYO_RW_MASK;
754 "for %s\n", tomoyo_get_msg(is_enforce), msg, operation,
755 filename->name, tomoyo_get_last_name(domain));
756 if (is_enforce)
757 return error;
758 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
759 /* Don't use patterns for execute permission. */
760 const struct tomoyo_path_info *patterned_file = (perm != 1) ?
761 tomoyo_get_file_pattern(filename) : filename;
762 tomoyo_update_file_acl(patterned_file->name, perm,
763 domain, false);
764 } 592 }
765 return 0; 593 *a_perm = perm;
594 return !perm;
766} 595}
767 596
768/** 597/**
769 * tomoyo_write_file_policy - Update file related list. 598 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
770 * 599 *
771 * @data: String to parse. 600 * @type: Type of operation.
601 * @filename: Filename.
772 * @domain: Pointer to "struct tomoyo_domain_info". 602 * @domain: Pointer to "struct tomoyo_domain_info".
773 * @is_delete: True if it is a delete request. 603 * @is_delete: True if it is a delete request.
774 * 604 *
@@ -776,48 +606,65 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
776 * 606 *
777 * Caller holds tomoyo_read_lock(). 607 * Caller holds tomoyo_read_lock().
778 */ 608 */
779int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, 609static int tomoyo_update_path_acl(const u8 type, const char *filename,
780 const bool is_delete) 610 struct tomoyo_domain_info * const domain,
611 const bool is_delete)
781{ 612{
782 char *filename = strchr(data, ' '); 613 struct tomoyo_path_acl e = {
783 char *filename2; 614 .head.type = TOMOYO_TYPE_PATH_ACL,
784 unsigned int perm; 615 .perm = 1 << type
785 u8 type; 616 };
786 617 int error;
787 if (!filename) 618 if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE))
619 e.perm |= TOMOYO_RW_MASK;
620 if (!tomoyo_parse_name_union(filename, &e.name))
788 return -EINVAL; 621 return -EINVAL;
789 *filename++ = '\0'; 622 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
790 if (sscanf(data, "%u", &perm) == 1) 623 tomoyo_same_path_acl,
791 return tomoyo_update_file_acl(filename, (u8) perm, domain, 624 tomoyo_merge_path_acl);
792 is_delete); 625 tomoyo_put_name_union(&e.name);
793 if (strncmp(data, "allow_", 6)) 626 return error;
794 goto out; 627}
795 data += 6; 628
796 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { 629static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
797 if (strcmp(data, tomoyo_path_keyword[type])) 630 const struct tomoyo_acl_info *b)
798 continue; 631{
799 return tomoyo_update_path_acl(type, filename, domain, 632 const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1),
800 is_delete); 633 head);
801 } 634 const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2),
802 filename2 = strchr(filename, ' '); 635 head);
803 if (!filename2) 636 return tomoyo_same_acl_head(&p1->head, &p2->head)
804 goto out; 637 && tomoyo_same_name_union(&p1->name, &p2->name)
805 *filename2++ = '\0'; 638 && tomoyo_same_number_union(&p1->mode, &p2->mode)
806 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { 639 && tomoyo_same_number_union(&p1->major, &p2->major)
807 if (strcmp(data, tomoyo_path2_keyword[type])) 640 && tomoyo_same_number_union(&p1->minor, &p2->minor);
808 continue; 641}
809 return tomoyo_update_path2_acl(type, filename, filename2, 642
810 domain, is_delete); 643static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
811 } 644 struct tomoyo_acl_info *b,
812 out: 645 const bool is_delete)
813 return -EINVAL; 646{
647 u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
648 head)->perm;
649 u8 perm = *a_perm;
650 const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
651 ->perm;
652 if (is_delete)
653 perm &= ~b_perm;
654 else
655 perm |= b_perm;
656 *a_perm = perm;
657 return !perm;
814} 658}
815 659
816/** 660/**
817 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. 661 * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
818 * 662 *
819 * @type: Type of operation. 663 * @type: Type of operation.
820 * @filename: Filename. 664 * @filename: Filename.
665 * @mode: Create mode.
666 * @major: Device major number.
667 * @minor: Device minor number.
821 * @domain: Pointer to "struct tomoyo_domain_info". 668 * @domain: Pointer to "struct tomoyo_domain_info".
822 * @is_delete: True if it is a delete request. 669 * @is_delete: True if it is a delete request.
823 * 670 *
@@ -825,71 +672,58 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
825 * 672 *
826 * Caller holds tomoyo_read_lock(). 673 * Caller holds tomoyo_read_lock().
827 */ 674 */
828static int tomoyo_update_path_acl(const u8 type, const char *filename, 675static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
829 struct tomoyo_domain_info *const domain, 676 char *mode, char *major, char *minor,
830 const bool is_delete) 677 struct tomoyo_domain_info * const
678 domain, const bool is_delete)
831{ 679{
832 static const u32 tomoyo_rw_mask = 680 struct tomoyo_mkdev_acl e = {
833 (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); 681 .head.type = TOMOYO_TYPE_MKDEV_ACL,
834 const u32 perm = 1 << type; 682 .perm = 1 << type
835 struct tomoyo_acl_info *ptr;
836 struct tomoyo_path_acl e = {
837 .head.type = TOMOYO_TYPE_PATH_ACL,
838 .perm_high = perm >> 16,
839 .perm = perm
840 }; 683 };
841 int error = is_delete ? -ENOENT : -ENOMEM; 684 int error = is_delete ? -ENOENT : -ENOMEM;
842 685 if (!tomoyo_parse_name_union(filename, &e.name) ||
843 if (type == TOMOYO_TYPE_READ_WRITE) 686 !tomoyo_parse_number_union(mode, &e.mode) ||
844 e.perm |= tomoyo_rw_mask; 687 !tomoyo_parse_number_union(major, &e.major) ||
845 if (!domain) 688 !tomoyo_parse_number_union(minor, &e.minor))
846 return -EINVAL;
847 if (!tomoyo_parse_name_union(filename, &e.name))
848 return -EINVAL;
849 if (mutex_lock_interruptible(&tomoyo_policy_lock))
850 goto out; 689 goto out;
851 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 690 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
852 struct tomoyo_path_acl *acl = 691 tomoyo_same_mkdev_acl,
853 container_of(ptr, struct tomoyo_path_acl, head); 692 tomoyo_merge_mkdev_acl);
854 if (!tomoyo_is_same_path_acl(acl, &e))
855 continue;
856 if (is_delete) {
857 if (perm <= 0xFFFF)
858 acl->perm &= ~perm;
859 else
860 acl->perm_high &= ~(perm >> 16);
861 if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask)
862 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
863 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)))
864 acl->perm &= ~tomoyo_rw_mask;
865 } else {
866 if (perm <= 0xFFFF)
867 acl->perm |= perm;
868 else
869 acl->perm_high |= (perm >> 16);
870 if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask)
871 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
872 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))
873 acl->perm |= tomoyo_rw_mask;
874 }
875 error = 0;
876 break;
877 }
878 if (!is_delete && error) {
879 struct tomoyo_path_acl *entry =
880 tomoyo_commit_ok(&e, sizeof(e));
881 if (entry) {
882 list_add_tail_rcu(&entry->head.list,
883 &domain->acl_info_list);
884 error = 0;
885 }
886 }
887 mutex_unlock(&tomoyo_policy_lock);
888 out: 693 out:
889 tomoyo_put_name_union(&e.name); 694 tomoyo_put_name_union(&e.name);
695 tomoyo_put_number_union(&e.mode);
696 tomoyo_put_number_union(&e.major);
697 tomoyo_put_number_union(&e.minor);
890 return error; 698 return error;
891} 699}
892 700
701static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
702 const struct tomoyo_acl_info *b)
703{
704 const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
705 const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
706 return tomoyo_same_acl_head(&p1->head, &p2->head)
707 && tomoyo_same_name_union(&p1->name1, &p2->name1)
708 && tomoyo_same_name_union(&p1->name2, &p2->name2);
709}
710
711static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
712 struct tomoyo_acl_info *b,
713 const bool is_delete)
714{
715 u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
716 ->perm;
717 u8 perm = *a_perm;
718 const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
719 if (is_delete)
720 perm &= ~b_perm;
721 else
722 perm |= b_perm;
723 *a_perm = perm;
724 return !perm;
725}
726
893/** 727/**
894 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. 728 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
895 * 729 *
@@ -905,46 +739,20 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
905 */ 739 */
906static int tomoyo_update_path2_acl(const u8 type, const char *filename1, 740static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
907 const char *filename2, 741 const char *filename2,
908 struct tomoyo_domain_info *const domain, 742 struct tomoyo_domain_info * const domain,
909 const bool is_delete) 743 const bool is_delete)
910{ 744{
911 const u8 perm = 1 << type;
912 struct tomoyo_path2_acl e = { 745 struct tomoyo_path2_acl e = {
913 .head.type = TOMOYO_TYPE_PATH2_ACL, 746 .head.type = TOMOYO_TYPE_PATH2_ACL,
914 .perm = perm 747 .perm = 1 << type
915 }; 748 };
916 struct tomoyo_acl_info *ptr;
917 int error = is_delete ? -ENOENT : -ENOMEM; 749 int error = is_delete ? -ENOENT : -ENOMEM;
918
919 if (!domain)
920 return -EINVAL;
921 if (!tomoyo_parse_name_union(filename1, &e.name1) || 750 if (!tomoyo_parse_name_union(filename1, &e.name1) ||
922 !tomoyo_parse_name_union(filename2, &e.name2)) 751 !tomoyo_parse_name_union(filename2, &e.name2))
923 goto out; 752 goto out;
924 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 753 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
925 goto out; 754 tomoyo_same_path2_acl,
926 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 755 tomoyo_merge_path2_acl);
927 struct tomoyo_path2_acl *acl =
928 container_of(ptr, struct tomoyo_path2_acl, head);
929 if (!tomoyo_is_same_path2_acl(acl, &e))
930 continue;
931 if (is_delete)
932 acl->perm &= ~perm;
933 else
934 acl->perm |= perm;
935 error = 0;
936 break;
937 }
938 if (!is_delete && error) {
939 struct tomoyo_path2_acl *entry =
940 tomoyo_commit_ok(&e, sizeof(e));
941 if (entry) {
942 list_add_tail_rcu(&entry->head.list,
943 &domain->acl_info_list);
944 error = 0;
945 }
946 }
947 mutex_unlock(&tomoyo_policy_lock);
948 out: 756 out:
949 tomoyo_put_name_union(&e.name1); 757 tomoyo_put_name_union(&e.name1);
950 tomoyo_put_name_union(&e.name2); 758 tomoyo_put_name_union(&e.name2);
@@ -952,134 +760,158 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
952} 760}
953 761
954/** 762/**
955 * tomoyo_path_acl - Check permission for single path operation. 763 * tomoyo_path_permission - Check permission for single path operation.
956 *
957 * @domain: Pointer to "struct tomoyo_domain_info".
958 * @type: Type of operation.
959 * @filename: Filename to check.
960 *
961 * Returns 0 on success, negative value otherwise.
962 *
963 * Caller holds tomoyo_read_lock().
964 */
965static int tomoyo_path_acl(struct tomoyo_domain_info *domain, const u8 type,
966 const struct tomoyo_path_info *filename)
967{
968 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
969 return 0;
970 return tomoyo_path_acl2(domain, filename, 1 << type, 1);
971}
972
973/**
974 * tomoyo_path2_acl - Check permission for double path operation.
975 * 764 *
976 * @domain: Pointer to "struct tomoyo_domain_info". 765 * @r: Pointer to "struct tomoyo_request_info".
977 * @type: Type of operation.
978 * @filename1: First filename to check.
979 * @filename2: Second filename to check.
980 *
981 * Returns 0 on success, -EPERM otherwise.
982 *
983 * Caller holds tomoyo_read_lock().
984 */
985static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain,
986 const u8 type,
987 const struct tomoyo_path_info *filename1,
988 const struct tomoyo_path_info *filename2)
989{
990 struct tomoyo_acl_info *ptr;
991 const u8 perm = 1 << type;
992 int error = -EPERM;
993
994 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
995 return 0;
996 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
997 struct tomoyo_path2_acl *acl;
998 if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
999 continue;
1000 acl = container_of(ptr, struct tomoyo_path2_acl, head);
1001 if (!(acl->perm & perm))
1002 continue;
1003 if (!tomoyo_compare_name_union(filename1, &acl->name1))
1004 continue;
1005 if (!tomoyo_compare_name_union(filename2, &acl->name2))
1006 continue;
1007 error = 0;
1008 break;
1009 }
1010 return error;
1011}
1012
1013/**
1014 * tomoyo_path_permission2 - Check permission for single path operation.
1015 *
1016 * @domain: Pointer to "struct tomoyo_domain_info".
1017 * @operation: Type of operation. 766 * @operation: Type of operation.
1018 * @filename: Filename to check. 767 * @filename: Filename to check.
1019 * @mode: Access control mode.
1020 * 768 *
1021 * Returns 0 on success, negative value otherwise. 769 * Returns 0 on success, negative value otherwise.
1022 * 770 *
1023 * Caller holds tomoyo_read_lock(). 771 * Caller holds tomoyo_read_lock().
1024 */ 772 */
1025static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain, 773int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
1026 u8 operation, 774 const struct tomoyo_path_info *filename)
1027 const struct tomoyo_path_info *filename,
1028 const u8 mode)
1029{ 775{
1030 const char *msg;
1031 int error; 776 int error;
1032 const bool is_enforce = (mode == 3);
1033 777
1034 if (!mode)
1035 return 0;
1036 next: 778 next:
1037 error = tomoyo_path_acl(domain, operation, filename); 779 r->type = tomoyo_p2mac[operation];
1038 msg = tomoyo_path2keyword(operation); 780 r->mode = tomoyo_get_mode(r->profile, r->type);
1039 if (!error) 781 if (r->mode == TOMOYO_CONFIG_DISABLED)
1040 goto ok; 782 return 0;
1041 if (tomoyo_verbose_mode(domain)) 783 r->param_type = TOMOYO_TYPE_PATH_ACL;
1042 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n", 784 r->param.path.filename = filename;
1043 tomoyo_get_msg(is_enforce), msg, filename->name, 785 r->param.path.operation = operation;
1044 tomoyo_get_last_name(domain)); 786 do {
1045 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { 787 tomoyo_check_acl(r, tomoyo_check_path_acl);
1046 const char *name = tomoyo_get_file_pattern(filename)->name; 788 if (!r->granted && operation == TOMOYO_TYPE_READ &&
1047 tomoyo_update_path_acl(operation, name, domain, false); 789 !r->domain->ignore_global_allow_read &&
1048 } 790 tomoyo_globally_readable_file(filename))
1049 if (!is_enforce) 791 r->granted = true;
1050 error = 0; 792 error = tomoyo_audit_path_log(r);
1051 ok: 793 /*
794 * Do not retry for execute request, for alias may have
795 * changed.
796 */
797 } while (error == TOMOYO_RETRY_REQUEST &&
798 operation != TOMOYO_TYPE_EXECUTE);
1052 /* 799 /*
1053 * Since "allow_truncate" doesn't imply "allow_rewrite" permission, 800 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
1054 * we need to check "allow_rewrite" permission if the filename is 801 * we need to check "allow_rewrite" permission if the filename is
1055 * specified by "deny_rewrite" keyword. 802 * specified by "deny_rewrite" keyword.
1056 */ 803 */
1057 if (!error && operation == TOMOYO_TYPE_TRUNCATE && 804 if (!error && operation == TOMOYO_TYPE_TRUNCATE &&
1058 tomoyo_is_no_rewrite_file(filename)) { 805 tomoyo_no_rewrite_file(filename)) {
1059 operation = TOMOYO_TYPE_REWRITE; 806 operation = TOMOYO_TYPE_REWRITE;
1060 goto next; 807 goto next;
1061 } 808 }
1062 return error; 809 return error;
1063} 810}
1064 811
812static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
813 const struct tomoyo_acl_info *b)
814{
815 const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
816 head);
817 const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
818 head);
819 return tomoyo_same_acl_head(&p1->head, &p2->head)
820 && tomoyo_same_name_union(&p1->name, &p2->name)
821 && tomoyo_same_number_union(&p1->number, &p2->number);
822}
823
824static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
825 struct tomoyo_acl_info *b,
826 const bool is_delete)
827{
828 u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
829 head)->perm;
830 u8 perm = *a_perm;
831 const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
832 ->perm;
833 if (is_delete)
834 perm &= ~b_perm;
835 else
836 perm |= b_perm;
837 *a_perm = perm;
838 return !perm;
839}
840
1065/** 841/**
1066 * tomoyo_check_exec_perm - Check permission for "execute". 842 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
843 *
844 * @type: Type of operation.
845 * @filename: Filename.
846 * @number: Number.
847 * @domain: Pointer to "struct tomoyo_domain_info".
848 * @is_delete: True if it is a delete request.
1067 * 849 *
1068 * @domain: Pointer to "struct tomoyo_domain_info". 850 * Returns 0 on success, negative value otherwise.
1069 * @filename: Check permission for "execute". 851 */
852static int tomoyo_update_path_number_acl(const u8 type, const char *filename,
853 char *number,
854 struct tomoyo_domain_info * const
855 domain,
856 const bool is_delete)
857{
858 struct tomoyo_path_number_acl e = {
859 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
860 .perm = 1 << type
861 };
862 int error = is_delete ? -ENOENT : -ENOMEM;
863 if (!tomoyo_parse_name_union(filename, &e.name))
864 return -EINVAL;
865 if (!tomoyo_parse_number_union(number, &e.number))
866 goto out;
867 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
868 tomoyo_same_path_number_acl,
869 tomoyo_merge_path_number_acl);
870 out:
871 tomoyo_put_name_union(&e.name);
872 tomoyo_put_number_union(&e.number);
873 return error;
874}
875
876/**
877 * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
1070 * 878 *
1071 * Returns 0 on success, negativevalue otherwise. 879 * @type: Type of operation.
880 * @path: Pointer to "struct path".
881 * @number: Number.
1072 * 882 *
1073 * Caller holds tomoyo_read_lock(). 883 * Returns 0 on success, negative value otherwise.
1074 */ 884 */
1075int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, 885int tomoyo_path_number_perm(const u8 type, struct path *path,
1076 const struct tomoyo_path_info *filename) 886 unsigned long number)
1077{ 887{
1078 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 888 struct tomoyo_request_info r;
889 int error = -ENOMEM;
890 struct tomoyo_path_info buf;
891 int idx;
1079 892
1080 if (!mode) 893 if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
894 == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry)
1081 return 0; 895 return 0;
1082 return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode); 896 idx = tomoyo_read_lock();
897 if (!tomoyo_get_realpath(&buf, path))
898 goto out;
899 if (type == TOMOYO_TYPE_MKDIR)
900 tomoyo_add_slash(&buf);
901 r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
902 r.param.path_number.operation = type;
903 r.param.path_number.filename = &buf;
904 r.param.path_number.number = number;
905 do {
906 tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
907 error = tomoyo_audit_path_number_log(&r);
908 } while (error == TOMOYO_RETRY_REQUEST);
909 kfree(buf.name);
910 out:
911 tomoyo_read_unlock(idx);
912 if (r.mode != TOMOYO_CONFIG_ENFORCING)
913 error = 0;
914 return error;
1083} 915}
1084 916
1085/** 917/**
@@ -1096,24 +928,17 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1096{ 928{
1097 const u8 acc_mode = ACC_MODE(flag); 929 const u8 acc_mode = ACC_MODE(flag);
1098 int error = -ENOMEM; 930 int error = -ENOMEM;
1099 struct tomoyo_path_info *buf; 931 struct tomoyo_path_info buf;
1100 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 932 struct tomoyo_request_info r;
1101 const bool is_enforce = (mode == 3);
1102 int idx; 933 int idx;
1103 934
1104 if (!mode || !path->mnt) 935 if (!path->mnt ||
1105 return 0; 936 (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)))
1106 if (acc_mode == 0)
1107 return 0;
1108 if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
1109 /*
1110 * I don't check directories here because mkdir() and rmdir()
1111 * don't call me.
1112 */
1113 return 0; 937 return 0;
938 buf.name = NULL;
939 r.mode = TOMOYO_CONFIG_DISABLED;
1114 idx = tomoyo_read_lock(); 940 idx = tomoyo_read_lock();
1115 buf = tomoyo_get_path(path); 941 if (!tomoyo_get_realpath(&buf, path))
1116 if (!buf)
1117 goto out; 942 goto out;
1118 error = 0; 943 error = 0;
1119 /* 944 /*
@@ -1121,28 +946,43 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1121 * we need to check "allow_rewrite" permission when the filename is not 946 * we need to check "allow_rewrite" permission when the filename is not
1122 * opened for append mode or the filename is truncated at open time. 947 * opened for append mode or the filename is truncated at open time.
1123 */ 948 */
1124 if ((acc_mode & MAY_WRITE) && 949 if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND)
1125 ((flag & O_TRUNC) || !(flag & O_APPEND)) && 950 && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE)
1126 (tomoyo_is_no_rewrite_file(buf))) { 951 != TOMOYO_CONFIG_DISABLED) {
1127 error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, 952 if (!tomoyo_get_realpath(&buf, path)) {
1128 buf, mode); 953 error = -ENOMEM;
954 goto out;
955 }
956 if (tomoyo_no_rewrite_file(&buf))
957 error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE,
958 &buf);
959 }
960 if (!error && acc_mode &&
961 tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
962 != TOMOYO_CONFIG_DISABLED) {
963 u8 operation;
964 if (!buf.name && !tomoyo_get_realpath(&buf, path)) {
965 error = -ENOMEM;
966 goto out;
967 }
968 if (acc_mode == (MAY_READ | MAY_WRITE))
969 operation = TOMOYO_TYPE_READ_WRITE;
970 else if (acc_mode == MAY_READ)
971 operation = TOMOYO_TYPE_READ;
972 else
973 operation = TOMOYO_TYPE_WRITE;
974 error = tomoyo_path_permission(&r, operation, &buf);
1129 } 975 }
1130 if (!error)
1131 error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
1132 mode);
1133 if (!error && (flag & O_TRUNC))
1134 error = tomoyo_path_permission2(domain, TOMOYO_TYPE_TRUNCATE,
1135 buf, mode);
1136 out: 976 out:
1137 kfree(buf); 977 kfree(buf.name);
1138 tomoyo_read_unlock(idx); 978 tomoyo_read_unlock(idx);
1139 if (!is_enforce) 979 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1140 error = 0; 980 error = 0;
1141 return error; 981 return error;
1142} 982}
1143 983
1144/** 984/**
1145 * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount". 985 * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount".
1146 * 986 *
1147 * @operation: Type of operation. 987 * @operation: Type of operation.
1148 * @path: Pointer to "struct path". 988 * @path: Pointer to "struct path".
@@ -1152,71 +992,79 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1152int tomoyo_path_perm(const u8 operation, struct path *path) 992int tomoyo_path_perm(const u8 operation, struct path *path)
1153{ 993{
1154 int error = -ENOMEM; 994 int error = -ENOMEM;
1155 struct tomoyo_path_info *buf; 995 struct tomoyo_path_info buf;
1156 struct tomoyo_domain_info *domain = tomoyo_domain(); 996 struct tomoyo_request_info r;
1157 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1158 const bool is_enforce = (mode == 3);
1159 int idx; 997 int idx;
1160 998
1161 if (!mode || !path->mnt) 999 if (!path->mnt)
1162 return 0; 1000 return 0;
1001 if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
1002 == TOMOYO_CONFIG_DISABLED)
1003 return 0;
1004 buf.name = NULL;
1163 idx = tomoyo_read_lock(); 1005 idx = tomoyo_read_lock();
1164 buf = tomoyo_get_path(path); 1006 if (!tomoyo_get_realpath(&buf, path))
1165 if (!buf)
1166 goto out; 1007 goto out;
1167 switch (operation) { 1008 switch (operation) {
1168 case TOMOYO_TYPE_MKDIR: 1009 case TOMOYO_TYPE_REWRITE:
1010 if (!tomoyo_no_rewrite_file(&buf)) {
1011 error = 0;
1012 goto out;
1013 }
1014 break;
1169 case TOMOYO_TYPE_RMDIR: 1015 case TOMOYO_TYPE_RMDIR:
1170 case TOMOYO_TYPE_CHROOT: 1016 case TOMOYO_TYPE_CHROOT:
1171 if (!buf->is_dir) { 1017 case TOMOYO_TYPE_UMOUNT:
1172 /* 1018 tomoyo_add_slash(&buf);
1173 * tomoyo_get_path() reserves space for appending "/." 1019 break;
1174 */
1175 strcat((char *) buf->name, "/");
1176 tomoyo_fill_path_info(buf);
1177 }
1178 } 1020 }
1179 error = tomoyo_path_permission2(domain, operation, buf, mode); 1021 error = tomoyo_path_permission(&r, operation, &buf);
1180 out: 1022 out:
1181 kfree(buf); 1023 kfree(buf.name);
1182 tomoyo_read_unlock(idx); 1024 tomoyo_read_unlock(idx);
1183 if (!is_enforce) 1025 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1184 error = 0; 1026 error = 0;
1185 return error; 1027 return error;
1186} 1028}
1187 1029
1188/** 1030/**
1189 * tomoyo_check_rewrite_permission - Check permission for "rewrite". 1031 * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
1190 * 1032 *
1191 * @filp: Pointer to "struct file". 1033 * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
1034 * @path: Pointer to "struct path".
1035 * @mode: Create mode.
1036 * @dev: Device number.
1192 * 1037 *
1193 * Returns 0 on success, negative value otherwise. 1038 * Returns 0 on success, negative value otherwise.
1194 */ 1039 */
1195int tomoyo_check_rewrite_permission(struct file *filp) 1040int tomoyo_mkdev_perm(const u8 operation, struct path *path,
1041 const unsigned int mode, unsigned int dev)
1196{ 1042{
1043 struct tomoyo_request_info r;
1197 int error = -ENOMEM; 1044 int error = -ENOMEM;
1198 struct tomoyo_domain_info *domain = tomoyo_domain(); 1045 struct tomoyo_path_info buf;
1199 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1200 const bool is_enforce = (mode == 3);
1201 struct tomoyo_path_info *buf;
1202 int idx; 1046 int idx;
1203 1047
1204 if (!mode || !filp->f_path.mnt) 1048 if (!path->mnt ||
1049 tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
1050 == TOMOYO_CONFIG_DISABLED)
1205 return 0; 1051 return 0;
1206
1207 idx = tomoyo_read_lock(); 1052 idx = tomoyo_read_lock();
1208 buf = tomoyo_get_path(&filp->f_path); 1053 error = -ENOMEM;
1209 if (!buf) 1054 if (tomoyo_get_realpath(&buf, path)) {
1210 goto out; 1055 dev = new_decode_dev(dev);
1211 if (!tomoyo_is_no_rewrite_file(buf)) { 1056 r.param_type = TOMOYO_TYPE_MKDEV_ACL;
1212 error = 0; 1057 r.param.mkdev.filename = &buf;
1213 goto out; 1058 r.param.mkdev.operation = operation;
1059 r.param.mkdev.mode = mode;
1060 r.param.mkdev.major = MAJOR(dev);
1061 r.param.mkdev.minor = MINOR(dev);
1062 tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
1063 error = tomoyo_audit_mkdev_log(&r);
1064 kfree(buf.name);
1214 } 1065 }
1215 error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, buf, mode);
1216 out:
1217 kfree(buf);
1218 tomoyo_read_unlock(idx); 1066 tomoyo_read_unlock(idx);
1219 if (!is_enforce) 1067 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1220 error = 0; 1068 error = 0;
1221 return error; 1069 return error;
1222} 1070}
@@ -1234,56 +1082,99 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
1234 struct path *path2) 1082 struct path *path2)
1235{ 1083{
1236 int error = -ENOMEM; 1084 int error = -ENOMEM;
1237 struct tomoyo_path_info *buf1, *buf2; 1085 struct tomoyo_path_info buf1;
1238 struct tomoyo_domain_info *domain = tomoyo_domain(); 1086 struct tomoyo_path_info buf2;
1239 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 1087 struct tomoyo_request_info r;
1240 const bool is_enforce = (mode == 3);
1241 const char *msg;
1242 int idx; 1088 int idx;
1243 1089
1244 if (!mode || !path1->mnt || !path2->mnt) 1090 if (!path1->mnt || !path2->mnt ||
1091 tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
1092 == TOMOYO_CONFIG_DISABLED)
1245 return 0; 1093 return 0;
1094 buf1.name = NULL;
1095 buf2.name = NULL;
1246 idx = tomoyo_read_lock(); 1096 idx = tomoyo_read_lock();
1247 buf1 = tomoyo_get_path(path1); 1097 if (!tomoyo_get_realpath(&buf1, path1) ||
1248 buf2 = tomoyo_get_path(path2); 1098 !tomoyo_get_realpath(&buf2, path2))
1249 if (!buf1 || !buf2)
1250 goto out;
1251 {
1252 struct dentry *dentry = path1->dentry;
1253 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
1254 /*
1255 * tomoyo_get_path() reserves space for appending "/."
1256 */
1257 if (!buf1->is_dir) {
1258 strcat((char *) buf1->name, "/");
1259 tomoyo_fill_path_info(buf1);
1260 }
1261 if (!buf2->is_dir) {
1262 strcat((char *) buf2->name, "/");
1263 tomoyo_fill_path_info(buf2);
1264 }
1265 }
1266 }
1267 error = tomoyo_path2_acl(domain, operation, buf1, buf2);
1268 msg = tomoyo_path22keyword(operation);
1269 if (!error)
1270 goto out; 1099 goto out;
1271 if (tomoyo_verbose_mode(domain)) 1100 switch (operation) {
1272 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' " 1101 struct dentry *dentry;
1273 "denied for %s\n", tomoyo_get_msg(is_enforce), 1102 case TOMOYO_TYPE_RENAME:
1274 msg, buf1->name, buf2->name, 1103 case TOMOYO_TYPE_LINK:
1275 tomoyo_get_last_name(domain)); 1104 dentry = path1->dentry;
1276 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { 1105 if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
1277 const char *name1 = tomoyo_get_file_pattern(buf1)->name; 1106 break;
1278 const char *name2 = tomoyo_get_file_pattern(buf2)->name; 1107 /* fall through */
1279 tomoyo_update_path2_acl(operation, name1, name2, domain, 1108 case TOMOYO_TYPE_PIVOT_ROOT:
1280 false); 1109 tomoyo_add_slash(&buf1);
1281 } 1110 tomoyo_add_slash(&buf2);
1111 break;
1112 }
1113 r.param_type = TOMOYO_TYPE_PATH2_ACL;
1114 r.param.path2.operation = operation;
1115 r.param.path2.filename1 = &buf1;
1116 r.param.path2.filename2 = &buf2;
1117 do {
1118 tomoyo_check_acl(&r, tomoyo_check_path2_acl);
1119 error = tomoyo_audit_path2_log(&r);
1120 } while (error == TOMOYO_RETRY_REQUEST);
1282 out: 1121 out:
1283 kfree(buf1); 1122 kfree(buf1.name);
1284 kfree(buf2); 1123 kfree(buf2.name);
1285 tomoyo_read_unlock(idx); 1124 tomoyo_read_unlock(idx);
1286 if (!is_enforce) 1125 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1287 error = 0; 1126 error = 0;
1288 return error; 1127 return error;
1289} 1128}
1129
1130/**
1131 * tomoyo_write_file - Update file related list.
1132 *
1133 * @data: String to parse.
1134 * @domain: Pointer to "struct tomoyo_domain_info".
1135 * @is_delete: True if it is a delete request.
1136 *
1137 * Returns 0 on success, negative value otherwise.
1138 *
1139 * Caller holds tomoyo_read_lock().
1140 */
1141int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain,
1142 const bool is_delete)
1143{
1144 char *w[5];
1145 u8 type;
1146 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
1147 return -EINVAL;
1148 if (strncmp(w[0], "allow_", 6))
1149 goto out;
1150 w[0] += 6;
1151 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
1152 if (strcmp(w[0], tomoyo_path_keyword[type]))
1153 continue;
1154 return tomoyo_update_path_acl(type, w[1], domain, is_delete);
1155 }
1156 if (!w[2][0])
1157 goto out;
1158 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) {
1159 if (strcmp(w[0], tomoyo_path2_keyword[type]))
1160 continue;
1161 return tomoyo_update_path2_acl(type, w[1], w[2], domain,
1162 is_delete);
1163 }
1164 for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) {
1165 if (strcmp(w[0], tomoyo_path_number_keyword[type]))
1166 continue;
1167 return tomoyo_update_path_number_acl(type, w[1], w[2], domain,
1168 is_delete);
1169 }
1170 if (!w[3][0] || !w[4][0])
1171 goto out;
1172 for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) {
1173 if (strcmp(w[0], tomoyo_mkdev_keyword[type]))
1174 continue;
1175 return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3],
1176 w[4], domain, is_delete);
1177 }
1178 out:
1179 return -EINVAL;
1180}