オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /branches/tomoyo-backport-2.6.35-to-2.6.32.diff

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4642 - (show annotations) (download) (as text)
Thu Feb 17 06:53:23 2011 UTC (13 years, 3 months ago) by kumaneko
File MIME type: text/x-diff
File size: 198831 byte(s)


1 This patch is for backporting TOMOYO in 2.6.35 to 2.6.32.
2 ---
3 fs/namespace.c | 20 -
4 fs/open.c | 27 +
5 include/linux/security.h | 41 ++
6 security/capability.c | 19 +
7 security/security.c | 20 +
8 security/tomoyo/Makefile | 2
9 security/tomoyo/common.c | 695 +++++++++++++++++++------------------
10 security/tomoyo/common.h | 655 ++++++++++++++++++++++++++++------
11 security/tomoyo/domain.c | 413 +++++++---------------
12 security/tomoyo/file.c | 807 ++++++++++++++++++++-----------------------
13 security/tomoyo/gc.c | 412 +++++++++++++++++++++
14 security/tomoyo/path_group.c | 172 +++++++++
15 security/tomoyo/realpath.c | 312 +++++-----------
16 security/tomoyo/realpath.h | 66 ---
17 security/tomoyo/tomoyo.c | 155 +++++---
18 security/tomoyo/tomoyo.h | 96 -----
19 16 files changed, 2328 insertions(+), 1584 deletions(-)
20
21 --- linux-2.6.32.28.orig/fs/namespace.c
22 +++ linux-2.6.32.28/fs/namespace.c
23 @@ -1928,6 +1928,16 @@ long do_mount(char *dev_name, char *dir_
24 if (data_page)
25 ((char *)data_page)[PAGE_SIZE - 1] = 0;
26
27 + /* ... and get the mountpoint */
28 + retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
29 + if (retval)
30 + return retval;
31 +
32 + retval = security_sb_mount(dev_name, &path,
33 + type_page, flags, data_page);
34 + if (retval)
35 + goto dput_out;
36 +
37 /* Default to relatime unless overriden */
38 if (!(flags & MS_NOATIME))
39 mnt_flags |= MNT_RELATIME;
40 @@ -1952,16 +1962,6 @@ long do_mount(char *dev_name, char *dir_
41 MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
42 MS_STRICTATIME);
43
44 - /* ... and get the mountpoint */
45 - retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
46 - if (retval)
47 - return retval;
48 -
49 - retval = security_sb_mount(dev_name, &path,
50 - type_page, flags, data_page);
51 - if (retval)
52 - goto dput_out;
53 -
54 if (flags & MS_REMOUNT)
55 retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
56 data_page);
57 --- linux-2.6.32.28.orig/fs/open.c
58 +++ linux-2.6.32.28/fs/open.c
59 @@ -587,6 +587,9 @@ SYSCALL_DEFINE1(chroot, const char __use
60 error = -EPERM;
61 if (!capable(CAP_SYS_CHROOT))
62 goto dput_and_out;
63 + error = security_path_chroot(&path);
64 + if (error)
65 + goto dput_and_out;
66
67 set_fs_root(current->fs, &path);
68 error = 0;
69 @@ -617,11 +620,15 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd
70 if (err)
71 goto out_putf;
72 mutex_lock(&inode->i_mutex);
73 + err = security_path_chmod(dentry, file->f_vfsmnt, mode);
74 + if (err)
75 + goto out_unlock;
76 if (mode == (mode_t) -1)
77 mode = inode->i_mode;
78 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
79 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
80 err = notify_change(dentry, &newattrs);
81 +out_unlock:
82 mutex_unlock(&inode->i_mutex);
83 mnt_drop_write(file->f_path.mnt);
84 out_putf:
85 @@ -646,11 +653,15 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, cons
86 if (error)
87 goto dput_and_out;
88 mutex_lock(&inode->i_mutex);
89 + error = security_path_chmod(path.dentry, path.mnt, mode);
90 + if (error)
91 + goto out_unlock;
92 if (mode == (mode_t) -1)
93 mode = inode->i_mode;
94 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
95 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
96 error = notify_change(path.dentry, &newattrs);
97 +out_unlock:
98 mutex_unlock(&inode->i_mutex);
99 mnt_drop_write(path.mnt);
100 dput_and_out:
101 @@ -664,9 +675,9 @@ SYSCALL_DEFINE2(chmod, const char __user
102 return sys_fchmodat(AT_FDCWD, filename, mode);
103 }
104
105 -static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
106 +static int chown_common(struct path *path, uid_t user, gid_t group)
107 {
108 - struct inode *inode = dentry->d_inode;
109 + struct inode *inode = path->dentry->d_inode;
110 int error;
111 struct iattr newattrs;
112
113 @@ -683,7 +694,9 @@ static int chown_common(struct dentry *
114 newattrs.ia_valid |=
115 ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
116 mutex_lock(&inode->i_mutex);
117 - error = notify_change(dentry, &newattrs);
118 + error = security_path_chown(path, user, group);
119 + if (!error)
120 + error = notify_change(path->dentry, &newattrs);
121 mutex_unlock(&inode->i_mutex);
122
123 return error;
124 @@ -700,7 +713,7 @@ SYSCALL_DEFINE3(chown, const char __user
125 error = mnt_want_write(path.mnt);
126 if (error)
127 goto out_release;
128 - error = chown_common(path.dentry, user, group);
129 + error = chown_common(&path, user, group);
130 mnt_drop_write(path.mnt);
131 out_release:
132 path_put(&path);
133 @@ -725,7 +738,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, cons
134 error = mnt_want_write(path.mnt);
135 if (error)
136 goto out_release;
137 - error = chown_common(path.dentry, user, group);
138 + error = chown_common(&path, user, group);
139 mnt_drop_write(path.mnt);
140 out_release:
141 path_put(&path);
142 @@ -744,7 +757,7 @@ SYSCALL_DEFINE3(lchown, const char __use
143 error = mnt_want_write(path.mnt);
144 if (error)
145 goto out_release;
146 - error = chown_common(path.dentry, user, group);
147 + error = chown_common(&path, user, group);
148 mnt_drop_write(path.mnt);
149 out_release:
150 path_put(&path);
151 @@ -767,7 +780,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd
152 goto out_fput;
153 dentry = file->f_path.dentry;
154 audit_inode(NULL, dentry);
155 - error = chown_common(dentry, user, group);
156 + error = chown_common(&file->f_path, user, group);
157 mnt_drop_write(file->f_path.mnt);
158 out_fput:
159 fput(file);
160 --- linux-2.6.32.28.orig/include/linux/security.h
161 +++ linux-2.6.32.28/include/linux/security.h
162 @@ -454,6 +454,22 @@ static inline void security_free_mnt_opt
163 * @new_dir contains the path structure for parent of the new link.
164 * @new_dentry contains the dentry structure of the new link.
165 * Return 0 if permission is granted.
166 + * @path_chmod:
167 + * Check for permission to change DAC's permission of a file or directory.
168 + * @dentry contains the dentry structure.
169 + * @mnt contains the vfsmnt structure.
170 + * @mode contains DAC's mode.
171 + * Return 0 if permission is granted.
172 + * @path_chown:
173 + * Check for permission to change owner/group of a file or directory.
174 + * @path contains the path structure.
175 + * @uid contains new owner's ID.
176 + * @gid contains new group's ID.
177 + * Return 0 if permission is granted.
178 + * @path_chroot:
179 + * Check for permission to change root directory.
180 + * @path contains the path structure.
181 + * Return 0 if permission is granted.
182 * @inode_readlink:
183 * Check the permission to read the symbolic link.
184 * @dentry contains the dentry structure for the file link.
185 @@ -1495,6 +1511,10 @@ struct security_operations {
186 struct dentry *new_dentry);
187 int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,
188 struct path *new_dir, struct dentry *new_dentry);
189 + int (*path_chmod) (struct dentry *dentry, struct vfsmount *mnt,
190 + mode_t mode);
191 + int (*path_chown) (struct path *path, uid_t uid, gid_t gid);
192 + int (*path_chroot) (struct path *path);
193 #endif
194
195 int (*inode_alloc_security) (struct inode *inode);
196 @@ -2959,6 +2979,10 @@ int security_path_link(struct dentry *ol
197 struct dentry *new_dentry);
198 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
199 struct path *new_dir, struct dentry *new_dentry);
200 +int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
201 + mode_t mode);
202 +int security_path_chown(struct path *path, uid_t uid, gid_t gid);
203 +int security_path_chroot(struct path *path);
204 #else /* CONFIG_SECURITY_PATH */
205 static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
206 {
207 @@ -3008,6 +3032,23 @@ static inline int security_path_rename(s
208 {
209 return 0;
210 }
211 +
212 +static inline int security_path_chmod(struct dentry *dentry,
213 + struct vfsmount *mnt,
214 + mode_t mode)
215 +{
216 + return 0;
217 +}
218 +
219 +static inline int security_path_chown(struct path *path, uid_t uid, gid_t gid)
220 +{
221 + return 0;
222 +}
223 +
224 +static inline int security_path_chroot(struct path *path)
225 +{
226 + return 0;
227 +}
228 #endif /* CONFIG_SECURITY_PATH */
229
230 #ifdef CONFIG_KEYS
231 --- linux-2.6.32.28.orig/security/capability.c
232 +++ linux-2.6.32.28/security/capability.c
233 @@ -308,6 +308,22 @@ static int cap_path_truncate(struct path
234 {
235 return 0;
236 }
237 +
238 +static int cap_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
239 + mode_t mode)
240 +{
241 + return 0;
242 +}
243 +
244 +static int cap_path_chown(struct path *path, uid_t uid, gid_t gid)
245 +{
246 + return 0;
247 +}
248 +
249 +static int cap_path_chroot(struct path *root)
250 +{
251 + return 0;
252 +}
253 #endif
254
255 static int cap_file_permission(struct file *file, int mask)
256 @@ -977,6 +993,9 @@ void security_fixup_ops(struct security_
257 set_to_cap_if_null(ops, path_link);
258 set_to_cap_if_null(ops, path_rename);
259 set_to_cap_if_null(ops, path_truncate);
260 + set_to_cap_if_null(ops, path_chmod);
261 + set_to_cap_if_null(ops, path_chown);
262 + set_to_cap_if_null(ops, path_chroot);
263 #endif
264 set_to_cap_if_null(ops, file_permission);
265 set_to_cap_if_null(ops, file_alloc_security);
266 --- linux-2.6.32.28.orig/security/security.c
267 +++ linux-2.6.32.28/security/security.c
268 @@ -434,6 +434,26 @@ int security_path_truncate(struct path *
269 return 0;
270 return security_ops->path_truncate(path, length, time_attrs);
271 }
272 +
273 +int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
274 + mode_t mode)
275 +{
276 + if (unlikely(IS_PRIVATE(dentry->d_inode)))
277 + return 0;
278 + return security_ops->path_chmod(dentry, mnt, mode);
279 +}
280 +
281 +int security_path_chown(struct path *path, uid_t uid, gid_t gid)
282 +{
283 + if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
284 + return 0;
285 + return security_ops->path_chown(path, uid, gid);
286 +}
287 +
288 +int security_path_chroot(struct path *path)
289 +{
290 + return security_ops->path_chroot(path);
291 +}
292 #endif
293
294 int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
295 --- linux-2.6.32.28.orig/security/tomoyo/Makefile
296 +++ linux-2.6.32.28/security/tomoyo/Makefile
297 @@ -1 +1 @@
298 -obj-y = common.o realpath.o tomoyo.o domain.o file.o
299 +obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o
300 --- linux-2.6.32.28.orig/security/tomoyo/common.c
301 +++ linux-2.6.32.28/security/tomoyo/common.c
302 @@ -10,11 +10,13 @@
303 */
304
305 #include <linux/uaccess.h>
306 +#include <linux/slab.h>
307 #include <linux/security.h>
308 #include <linux/hardirq.h>
309 -#include "realpath.h"
310 #include "common.h"
311 -#include "tomoyo.h"
312 +
313 +/* Lock for protecting policy. */
314 +DEFINE_MUTEX(tomoyo_policy_lock);
315
316 /* Has loading policy done? */
317 bool tomoyo_policy_loaded;
318 @@ -74,6 +76,49 @@ static int tomoyo_write_control(struct f
319 const int buffer_len);
320
321 /**
322 + * tomoyo_parse_name_union - Parse a tomoyo_name_union.
323 + *
324 + * @filename: Name or name group.
325 + * @ptr: Pointer to "struct tomoyo_name_union".
326 + *
327 + * Returns true on success, false otherwise.
328 + */
329 +bool tomoyo_parse_name_union(const char *filename,
330 + struct tomoyo_name_union *ptr)
331 +{
332 + if (!tomoyo_is_correct_path(filename, 0, 0, 0))
333 + return false;
334 + if (filename[0] == '@') {
335 + ptr->group = tomoyo_get_path_group(filename + 1);
336 + ptr->is_group = true;
337 + return ptr->group != NULL;
338 + }
339 + ptr->filename = tomoyo_get_name(filename);
340 + ptr->is_group = false;
341 + return ptr->filename != NULL;
342 +}
343 +
344 +/**
345 + * tomoyo_print_name_union - Print a tomoyo_name_union.
346 + *
347 + * @head: Pointer to "struct tomoyo_io_buffer".
348 + * @ptr: Pointer to "struct tomoyo_name_union".
349 + *
350 + * Returns true on success, false otherwise.
351 + */
352 +static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head,
353 + const struct tomoyo_name_union *ptr)
354 +{
355 + int pos = head->read_avail;
356 + if (pos && head->read_buf[pos - 1] == ' ')
357 + head->read_avail--;
358 + if (ptr->is_group)
359 + return tomoyo_io_printf(head, " @%s",
360 + ptr->group->group_name->name);
361 + return tomoyo_io_printf(head, " %s", ptr->filename->name);
362 +}
363 +
364 +/**
365 * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value.
366 *
367 * @str: Pointer to the string.
368 @@ -170,6 +215,33 @@ static void tomoyo_normalize_line(unsign
369 }
370
371 /**
372 + * tomoyo_tokenize - Tokenize string.
373 + *
374 + * @buffer: The line to tokenize.
375 + * @w: Pointer to "char *".
376 + * @size: Sizeof @w .
377 + *
378 + * Returns true on success, false otherwise.
379 + */
380 +bool tomoyo_tokenize(char *buffer, char *w[], size_t size)
381 +{
382 + int count = size / sizeof(char *);
383 + int i;
384 + for (i = 0; i < count; i++)
385 + w[i] = "";
386 + for (i = 0; i < count; i++) {
387 + char *cp = strchr(buffer, ' ');
388 + if (cp)
389 + *cp = '\0';
390 + w[i] = buffer;
391 + if (!cp)
392 + break;
393 + buffer = cp + 1;
394 + }
395 + return i < count || !*buffer;
396 +}
397 +
398 +/**
399 * tomoyo_is_correct_path - Validate a pathname.
400 * @filename: The pathname to check.
401 * @start_type: Should the pathname start with '/'?
402 @@ -178,20 +250,19 @@ static void tomoyo_normalize_line(unsign
403 * 1 = must / -1 = must not / 0 = don't care
404 * @end_type: Should the pathname end with '/'?
405 * 1 = must / -1 = must not / 0 = don't care
406 - * @function: The name of function calling me.
407 *
408 * Check whether the given filename follows the naming rules.
409 * Returns true if @filename follows the naming rules, false otherwise.
410 */
411 bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
412 - const s8 pattern_type, const s8 end_type,
413 - const char *function)
414 + const s8 pattern_type, const s8 end_type)
415 {
416 + const char *const start = filename;
417 + bool in_repetition = false;
418 bool contains_pattern = false;
419 unsigned char c;
420 unsigned char d;
421 unsigned char e;
422 - const char *original_filename = filename;
423
424 if (!filename)
425 goto out;
426 @@ -212,9 +283,13 @@ bool tomoyo_is_correct_path(const char *
427 if (c == '/')
428 goto out;
429 }
430 - while ((c = *filename++) != '\0') {
431 + while (1) {
432 + c = *filename++;
433 + if (!c)
434 + break;
435 if (c == '\\') {
436 - switch ((c = *filename++)) {
437 + c = *filename++;
438 + switch (c) {
439 case '\\': /* "\\" */
440 continue;
441 case '$': /* "\$" */
442 @@ -231,6 +306,22 @@ bool tomoyo_is_correct_path(const char *
443 break; /* Must not contain pattern */
444 contains_pattern = true;
445 continue;
446 + case '{': /* "/\{" */
447 + if (filename - 3 < start ||
448 + *(filename - 3) != '/')
449 + break;
450 + if (pattern_type == -1)
451 + break; /* Must not contain pattern */
452 + contains_pattern = true;
453 + in_repetition = true;
454 + continue;
455 + case '}': /* "\}/" */
456 + if (*filename != '/')
457 + break;
458 + if (!in_repetition)
459 + break;
460 + in_repetition = false;
461 + continue;
462 case '0': /* "\ooo" */
463 case '1':
464 case '2':
465 @@ -246,6 +337,8 @@ bool tomoyo_is_correct_path(const char *
466 continue; /* pattern is not \000 */
467 }
468 goto out;
469 + } else if (in_repetition && c == '/') {
470 + goto out;
471 } else if (tomoyo_is_invalid(c)) {
472 goto out;
473 }
474 @@ -254,27 +347,24 @@ bool tomoyo_is_correct_path(const char *
475 if (!contains_pattern)
476 goto out;
477 }
478 + if (in_repetition)
479 + goto out;
480 return true;
481 out:
482 - printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
483 - original_filename);
484 return false;
485 }
486
487 /**
488 * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
489 * @domainname: The domainname to check.
490 - * @function: The name of function calling me.
491 *
492 * Returns true if @domainname follows the naming rules, false otherwise.
493 */
494 -bool tomoyo_is_correct_domain(const unsigned char *domainname,
495 - const char *function)
496 +bool tomoyo_is_correct_domain(const unsigned char *domainname)
497 {
498 unsigned char c;
499 unsigned char d;
500 unsigned char e;
501 - const char *org_domainname = domainname;
502
503 if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
504 TOMOYO_ROOT_NAME_LEN))
505 @@ -317,8 +407,6 @@ bool tomoyo_is_correct_domain(const unsi
506 } while (*domainname);
507 return true;
508 out:
509 - printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function,
510 - org_domainname);
511 return false;
512 }
513
514 @@ -339,10 +427,9 @@ bool tomoyo_is_domain_def(const unsigned
515 *
516 * @domainname: The domainname to find.
517 *
518 - * Caller must call down_read(&tomoyo_domain_list_lock); or
519 - * down_write(&tomoyo_domain_list_lock); .
520 - *
521 * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
522 + *
523 + * Caller holds tomoyo_read_lock().
524 */
525 struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
526 {
527 @@ -351,7 +438,7 @@ struct tomoyo_domain_info *tomoyo_find_d
528
529 name.name = domainname;
530 tomoyo_fill_path_info(&name);
531 - list_for_each_entry(domain, &tomoyo_domain_list, list) {
532 + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
533 if (!domain->is_deleted &&
534 !tomoyo_pathcmp(&name, domain->domainname))
535 return domain;
536 @@ -360,33 +447,6 @@ struct tomoyo_domain_info *tomoyo_find_d
537 }
538
539 /**
540 - * tomoyo_path_depth - Evaluate the number of '/' in a string.
541 - *
542 - * @pathname: The string to evaluate.
543 - *
544 - * Returns path depth of the string.
545 - *
546 - * I score 2 for each of the '/' in the @pathname
547 - * and score 1 if the @pathname ends with '/'.
548 - */
549 -static int tomoyo_path_depth(const char *pathname)
550 -{
551 - int i = 0;
552 -
553 - if (pathname) {
554 - const char *ep = pathname + strlen(pathname);
555 - if (pathname < ep--) {
556 - if (*ep != '/')
557 - i++;
558 - while (pathname <= ep)
559 - if (*ep-- == '/')
560 - i += 2;
561 - }
562 - }
563 - return i;
564 -}
565 -
566 -/**
567 * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
568 *
569 * @filename: The string to evaluate.
570 @@ -444,11 +504,10 @@ void tomoyo_fill_path_info(struct tomoyo
571 ptr->is_dir = len && (name[len - 1] == '/');
572 ptr->is_patterned = (ptr->const_len < len);
573 ptr->hash = full_name_hash(name, len);
574 - ptr->depth = tomoyo_path_depth(name);
575 }
576
577 /**
578 - * tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character
579 + * tomoyo_file_matches_pattern2 - Pattern matching without '/' character
580 * and "\-" pattern.
581 *
582 * @filename: The start of string to check.
583 @@ -458,10 +517,10 @@ void tomoyo_fill_path_info(struct tomoyo
584 *
585 * Returns true if @filename matches @pattern, false otherwise.
586 */
587 -static bool tomoyo_file_matches_to_pattern2(const char *filename,
588 - const char *filename_end,
589 - const char *pattern,
590 - const char *pattern_end)
591 +static bool tomoyo_file_matches_pattern2(const char *filename,
592 + const char *filename_end,
593 + const char *pattern,
594 + const char *pattern_end)
595 {
596 while (filename < filename_end && pattern < pattern_end) {
597 char c;
598 @@ -519,7 +578,7 @@ static bool tomoyo_file_matches_to_patte
599 case '*':
600 case '@':
601 for (i = 0; i <= filename_end - filename; i++) {
602 - if (tomoyo_file_matches_to_pattern2(
603 + if (tomoyo_file_matches_pattern2(
604 filename + i, filename_end,
605 pattern + 1, pattern_end))
606 return true;
607 @@ -550,7 +609,7 @@ static bool tomoyo_file_matches_to_patte
608 j++;
609 }
610 for (i = 1; i <= j; i++) {
611 - if (tomoyo_file_matches_to_pattern2(
612 + if (tomoyo_file_matches_pattern2(
613 filename + i, filename_end,
614 pattern + 1, pattern_end))
615 return true;
616 @@ -567,7 +626,7 @@ static bool tomoyo_file_matches_to_patte
617 }
618
619 /**
620 - * tomoyo_file_matches_to_pattern - Pattern matching without without '/' character.
621 + * tomoyo_file_matches_pattern - Pattern matching without without '/' character.
622 *
623 * @filename: The start of string to check.
624 * @filename_end: The end of string to check.
625 @@ -576,7 +635,7 @@ static bool tomoyo_file_matches_to_patte
626 *
627 * Returns true if @filename matches @pattern, false otherwise.
628 */
629 -static bool tomoyo_file_matches_to_pattern(const char *filename,
630 +static bool tomoyo_file_matches_pattern(const char *filename,
631 const char *filename_end,
632 const char *pattern,
633 const char *pattern_end)
634 @@ -589,10 +648,10 @@ static bool tomoyo_file_matches_to_patte
635 /* Split at "\-" pattern. */
636 if (*pattern++ != '\\' || *pattern++ != '-')
637 continue;
638 - result = tomoyo_file_matches_to_pattern2(filename,
639 - filename_end,
640 - pattern_start,
641 - pattern - 2);
642 + result = tomoyo_file_matches_pattern2(filename,
643 + filename_end,
644 + pattern_start,
645 + pattern - 2);
646 if (first)
647 result = !result;
648 if (result)
649 @@ -600,13 +659,79 @@ static bool tomoyo_file_matches_to_patte
650 first = false;
651 pattern_start = pattern;
652 }
653 - result = tomoyo_file_matches_to_pattern2(filename, filename_end,
654 - pattern_start, pattern_end);
655 + result = tomoyo_file_matches_pattern2(filename, filename_end,
656 + pattern_start, pattern_end);
657 return first ? result : !result;
658 }
659
660 /**
661 + * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
662 + *
663 + * @f: The start of string to check.
664 + * @p: The start of pattern to compare.
665 + *
666 + * Returns true if @f matches @p, false otherwise.
667 + */
668 +static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
669 +{
670 + const char *f_delimiter;
671 + const char *p_delimiter;
672 +
673 + while (*f && *p) {
674 + f_delimiter = strchr(f, '/');
675 + if (!f_delimiter)
676 + f_delimiter = f + strlen(f);
677 + p_delimiter = strchr(p, '/');
678 + if (!p_delimiter)
679 + p_delimiter = p + strlen(p);
680 + if (*p == '\\' && *(p + 1) == '{')
681 + goto recursive;
682 + if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
683 + p_delimiter))
684 + return false;
685 + f = f_delimiter;
686 + if (*f)
687 + f++;
688 + p = p_delimiter;
689 + if (*p)
690 + p++;
691 + }
692 + /* Ignore trailing "\*" and "\@" in @pattern. */
693 + while (*p == '\\' &&
694 + (*(p + 1) == '*' || *(p + 1) == '@'))
695 + p += 2;
696 + return !*f && !*p;
697 + recursive:
698 + /*
699 + * The "\{" pattern is permitted only after '/' character.
700 + * This guarantees that below "*(p - 1)" is safe.
701 + * Also, the "\}" pattern is permitted only before '/' character
702 + * so that "\{" + "\}" pair will not break the "\-" operator.
703 + */
704 + if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
705 + *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
706 + return false; /* Bad pattern. */
707 + do {
708 + /* Compare current component with pattern. */
709 + if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
710 + p_delimiter - 2))
711 + break;
712 + /* Proceed to next component. */
713 + f = f_delimiter;
714 + if (!*f)
715 + break;
716 + f++;
717 + /* Continue comparison. */
718 + if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
719 + return true;
720 + f_delimiter = strchr(f, '/');
721 + } while (f_delimiter);
722 + return false; /* Not matched. */
723 +}
724 +
725 +/**
726 * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
727 + *
728 * @filename: The filename to check.
729 * @pattern: The pattern to compare.
730 *
731 @@ -615,24 +740,24 @@ static bool tomoyo_file_matches_to_patte
732 * The following patterns are available.
733 * \\ \ itself.
734 * \ooo Octal representation of a byte.
735 - * \* More than or equals to 0 character other than '/'.
736 - * \@ More than or equals to 0 character other than '/' or '.'.
737 + * \* Zero or more repetitions of characters other than '/'.
738 + * \@ Zero or more repetitions of characters other than '/' or '.'.
739 * \? 1 byte character other than '/'.
740 - * \$ More than or equals to 1 decimal digit.
741 + * \$ One or more repetitions of decimal digits.
742 * \+ 1 decimal digit.
743 - * \X More than or equals to 1 hexadecimal digit.
744 + * \X One or more repetitions of hexadecimal digits.
745 * \x 1 hexadecimal digit.
746 - * \A More than or equals to 1 alphabet character.
747 + * \A One or more repetitions of alphabet characters.
748 * \a 1 alphabet character.
749 + *
750 * \- Subtraction operator.
751 + *
752 + * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
753 + * /dir/dir/dir/ ).
754 */
755 bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
756 const struct tomoyo_path_info *pattern)
757 {
758 - /*
759 - if (!filename || !pattern)
760 - return false;
761 - */
762 const char *f = filename->name;
763 const char *p = pattern->name;
764 const int len = pattern->const_len;
765 @@ -640,37 +765,15 @@ bool tomoyo_path_matches_pattern(const s
766 /* If @pattern doesn't contain pattern, I can use strcmp(). */
767 if (!pattern->is_patterned)
768 return !tomoyo_pathcmp(filename, pattern);
769 - /* Dont compare if the number of '/' differs. */
770 - if (filename->depth != pattern->depth)
771 + /* Don't compare directory and non-directory. */
772 + if (filename->is_dir != pattern->is_dir)
773 return false;
774 /* Compare the initial length without patterns. */
775 if (strncmp(f, p, len))
776 return false;
777 f += len;
778 p += len;
779 - /* Main loop. Compare each directory component. */
780 - while (*f && *p) {
781 - const char *f_delimiter = strchr(f, '/');
782 - const char *p_delimiter = strchr(p, '/');
783 - if (!f_delimiter)
784 - f_delimiter = f + strlen(f);
785 - if (!p_delimiter)
786 - p_delimiter = p + strlen(p);
787 - if (!tomoyo_file_matches_to_pattern(f, f_delimiter,
788 - p, p_delimiter))
789 - return false;
790 - f = f_delimiter;
791 - if (*f)
792 - f++;
793 - p = p_delimiter;
794 - if (*p)
795 - p++;
796 - }
797 - /* Ignore trailing "\*" and "\@" in @pattern. */
798 - while (*p == '\\' &&
799 - (*(p + 1) == '*' || *(p + 1) == '@'))
800 - p += 2;
801 - return !*f && !*p;
802 + return tomoyo_path_matches_pattern2(f, p);
803 }
804
805 /**
806 @@ -706,7 +809,7 @@ bool tomoyo_io_printf(struct tomoyo_io_b
807 *
808 * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
809 *
810 - * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
811 + * This function uses kzalloc(), so the caller must call kfree()
812 * if this function didn't return NULL.
813 */
814 static const char *tomoyo_get_exe(void)
815 @@ -787,6 +890,8 @@ bool tomoyo_verbose_mode(const struct to
816 * @domain: Pointer to "struct tomoyo_domain_info".
817 *
818 * Returns true if the domain is not exceeded quota, false otherwise.
819 + *
820 + * Caller holds tomoyo_read_lock().
821 */
822 bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
823 {
824 @@ -795,61 +900,29 @@ bool tomoyo_domain_quota_is_ok(struct to
825
826 if (!domain)
827 return true;
828 - down_read(&tomoyo_domain_acl_info_list_lock);
829 - list_for_each_entry(ptr, &domain->acl_info_list, list) {
830 - if (ptr->type & TOMOYO_ACL_DELETED)
831 - continue;
832 - switch (tomoyo_acl_type2(ptr)) {
833 - struct tomoyo_single_path_acl_record *acl1;
834 - struct tomoyo_double_path_acl_record *acl2;
835 - u16 perm;
836 - case TOMOYO_TYPE_SINGLE_PATH_ACL:
837 - acl1 = container_of(ptr,
838 - struct tomoyo_single_path_acl_record,
839 - head);
840 - perm = acl1->perm;
841 - if (perm & (1 << TOMOYO_TYPE_EXECUTE_ACL))
842 - count++;
843 - if (perm &
844 - ((1 << TOMOYO_TYPE_READ_ACL) |
845 - (1 << TOMOYO_TYPE_WRITE_ACL)))
846 - count++;
847 - if (perm & (1 << TOMOYO_TYPE_CREATE_ACL))
848 - count++;
849 - if (perm & (1 << TOMOYO_TYPE_UNLINK_ACL))
850 - count++;
851 - if (perm & (1 << TOMOYO_TYPE_MKDIR_ACL))
852 - count++;
853 - if (perm & (1 << TOMOYO_TYPE_RMDIR_ACL))
854 - count++;
855 - if (perm & (1 << TOMOYO_TYPE_MKFIFO_ACL))
856 - count++;
857 - if (perm & (1 << TOMOYO_TYPE_MKSOCK_ACL))
858 - count++;
859 - if (perm & (1 << TOMOYO_TYPE_MKBLOCK_ACL))
860 - count++;
861 - if (perm & (1 << TOMOYO_TYPE_MKCHAR_ACL))
862 - count++;
863 - if (perm & (1 << TOMOYO_TYPE_TRUNCATE_ACL))
864 - count++;
865 - if (perm & (1 << TOMOYO_TYPE_SYMLINK_ACL))
866 - count++;
867 - if (perm & (1 << TOMOYO_TYPE_REWRITE_ACL))
868 - count++;
869 - break;
870 - case TOMOYO_TYPE_DOUBLE_PATH_ACL:
871 - acl2 = container_of(ptr,
872 - struct tomoyo_double_path_acl_record,
873 - head);
874 - perm = acl2->perm;
875 - if (perm & (1 << TOMOYO_TYPE_LINK_ACL))
876 - count++;
877 - if (perm & (1 << TOMOYO_TYPE_RENAME_ACL))
878 - count++;
879 + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
880 + switch (ptr->type) {
881 + struct tomoyo_path_acl *acl;
882 + u32 perm;
883 + u8 i;
884 + case TOMOYO_TYPE_PATH_ACL:
885 + acl = container_of(ptr, struct tomoyo_path_acl, head);
886 + perm = acl->perm | (((u32) acl->perm_high) << 16);
887 + for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++)
888 + if (perm & (1 << i))
889 + count++;
890 + if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
891 + count -= 2;
892 + break;
893 + case TOMOYO_TYPE_PATH2_ACL:
894 + perm = container_of(ptr, struct tomoyo_path2_acl, head)
895 + ->perm;
896 + for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++)
897 + if (perm & (1 << i))
898 + count++;
899 break;
900 }
901 }
902 - up_read(&tomoyo_domain_acl_info_list_lock);
903 if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
904 return true;
905 if (!domain->quota_warned) {
906 @@ -871,25 +944,28 @@ bool tomoyo_domain_quota_is_ok(struct to
907 static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned
908 int profile)
909 {
910 - static DEFINE_MUTEX(lock);
911 struct tomoyo_profile *ptr = NULL;
912 int i;
913
914 if (profile >= TOMOYO_MAX_PROFILES)
915 return NULL;
916 - mutex_lock(&lock);
917 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
918 + return NULL;
919 ptr = tomoyo_profile_ptr[profile];
920 if (ptr)
921 goto ok;
922 - ptr = tomoyo_alloc_element(sizeof(*ptr));
923 - if (!ptr)
924 + ptr = kmalloc(sizeof(*ptr), GFP_NOFS);
925 + if (!tomoyo_memory_ok(ptr)) {
926 + kfree(ptr);
927 + ptr = NULL;
928 goto ok;
929 + }
930 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
931 ptr->value[i] = tomoyo_control_array[i].current_value;
932 mb(); /* Avoid out-of-order execution. */
933 tomoyo_profile_ptr[profile] = ptr;
934 ok:
935 - mutex_unlock(&lock);
936 + mutex_unlock(&tomoyo_policy_lock);
937 return ptr;
938 }
939
940 @@ -924,7 +1000,9 @@ static int tomoyo_write_profile(struct t
941 return -EINVAL;
942 *cp = '\0';
943 if (!strcmp(data, "COMMENT")) {
944 - profile->comment = tomoyo_save_name(cp + 1);
945 + const struct tomoyo_path_info *old_comment = profile->comment;
946 + profile->comment = tomoyo_get_name(cp + 1);
947 + tomoyo_put_name(old_comment);
948 return 0;
949 }
950 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) {
951 @@ -1019,27 +1097,6 @@ static int tomoyo_read_profile(struct to
952 }
953
954 /*
955 - * tomoyo_policy_manager_entry is a structure which is used for holding list of
956 - * domainnames or programs which are permitted to modify configuration via
957 - * /sys/kernel/security/tomoyo/ interface.
958 - * It has following fields.
959 - *
960 - * (1) "list" which is linked to tomoyo_policy_manager_list .
961 - * (2) "manager" is a domainname or a program's pathname.
962 - * (3) "is_domain" is a bool which is true if "manager" is a domainname, false
963 - * otherwise.
964 - * (4) "is_deleted" is a bool which is true if marked as deleted, false
965 - * otherwise.
966 - */
967 -struct tomoyo_policy_manager_entry {
968 - struct list_head list;
969 - /* A path to program or a domainname. */
970 - const struct tomoyo_path_info *manager;
971 - bool is_domain; /* True if manager is a domainname. */
972 - bool is_deleted; /* True if this entry is deleted. */
973 -};
974 -
975 -/*
976 * tomoyo_policy_manager_list is used for holding list of domainnames or
977 * programs which are permitted to modify configuration via
978 * /sys/kernel/security/tomoyo/ interface.
979 @@ -1069,8 +1126,7 @@ struct tomoyo_policy_manager_entry {
980 *
981 * # cat /sys/kernel/security/tomoyo/manager
982 */
983 -static LIST_HEAD(tomoyo_policy_manager_list);
984 -static DECLARE_RWSEM(tomoyo_policy_manager_list_lock);
985 +LIST_HEAD(tomoyo_policy_manager_list);
986
987 /**
988 * tomoyo_update_manager_entry - Add a manager entry.
989 @@ -1079,48 +1135,48 @@ static DECLARE_RWSEM(tomoyo_policy_manag
990 * @is_delete: True if it is a delete request.
991 *
992 * Returns 0 on success, negative value otherwise.
993 + *
994 + * Caller holds tomoyo_read_lock().
995 */
996 static int tomoyo_update_manager_entry(const char *manager,
997 const bool is_delete)
998 {
999 - struct tomoyo_policy_manager_entry *new_entry;
1000 struct tomoyo_policy_manager_entry *ptr;
1001 - const struct tomoyo_path_info *saved_manager;
1002 - int error = -ENOMEM;
1003 - bool is_domain = false;
1004 + struct tomoyo_policy_manager_entry e = { };
1005 + int error = is_delete ? -ENOENT : -ENOMEM;
1006
1007 if (tomoyo_is_domain_def(manager)) {
1008 - if (!tomoyo_is_correct_domain(manager, __func__))
1009 + if (!tomoyo_is_correct_domain(manager))
1010 return -EINVAL;
1011 - is_domain = true;
1012 + e.is_domain = true;
1013 } else {
1014 - if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__))
1015 + if (!tomoyo_is_correct_path(manager, 1, -1, -1))
1016 return -EINVAL;
1017 }
1018 - saved_manager = tomoyo_save_name(manager);
1019 - if (!saved_manager)
1020 + e.manager = tomoyo_get_name(manager);
1021 + if (!e.manager)
1022 return -ENOMEM;
1023 - down_write(&tomoyo_policy_manager_list_lock);
1024 - list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1025 - if (ptr->manager != saved_manager)
1026 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
1027 + goto out;
1028 + list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
1029 + if (ptr->manager != e.manager)
1030 continue;
1031 ptr->is_deleted = is_delete;
1032 error = 0;
1033 - goto out;
1034 + break;
1035 }
1036 - if (is_delete) {
1037 - error = -ENOENT;
1038 - goto out;
1039 + if (!is_delete && error) {
1040 + struct tomoyo_policy_manager_entry *entry =
1041 + tomoyo_commit_ok(&e, sizeof(e));
1042 + if (entry) {
1043 + list_add_tail_rcu(&entry->list,
1044 + &tomoyo_policy_manager_list);
1045 + error = 0;
1046 + }
1047 }
1048 - new_entry = tomoyo_alloc_element(sizeof(*new_entry));
1049 - if (!new_entry)
1050 - goto out;
1051 - new_entry->manager = saved_manager;
1052 - new_entry->is_domain = is_domain;
1053 - list_add_tail(&new_entry->list, &tomoyo_policy_manager_list);
1054 - error = 0;
1055 + mutex_unlock(&tomoyo_policy_lock);
1056 out:
1057 - up_write(&tomoyo_policy_manager_list_lock);
1058 + tomoyo_put_name(e.manager);
1059 return error;
1060 }
1061
1062 @@ -1130,6 +1186,8 @@ static int tomoyo_update_manager_entry(c
1063 * @head: Pointer to "struct tomoyo_io_buffer".
1064 *
1065 * Returns 0 on success, negative value otherwise.
1066 + *
1067 + * Caller holds tomoyo_read_lock().
1068 */
1069 static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
1070 {
1071 @@ -1149,6 +1207,8 @@ static int tomoyo_write_manager_policy(s
1072 * @head: Pointer to "struct tomoyo_io_buffer".
1073 *
1074 * Returns 0.
1075 + *
1076 + * Caller holds tomoyo_read_lock().
1077 */
1078 static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1079 {
1080 @@ -1157,7 +1217,6 @@ static int tomoyo_read_manager_policy(st
1081
1082 if (head->read_eof)
1083 return 0;
1084 - down_read(&tomoyo_policy_manager_list_lock);
1085 list_for_each_cookie(pos, head->read_var2,
1086 &tomoyo_policy_manager_list) {
1087 struct tomoyo_policy_manager_entry *ptr;
1088 @@ -1169,7 +1228,6 @@ static int tomoyo_read_manager_policy(st
1089 if (!done)
1090 break;
1091 }
1092 - up_read(&tomoyo_policy_manager_list_lock);
1093 head->read_eof = done;
1094 return 0;
1095 }
1096 @@ -1179,6 +1237,8 @@ static int tomoyo_read_manager_policy(st
1097 *
1098 * Returns true if the current process is permitted to modify policy
1099 * via /sys/kernel/security/tomoyo/ interface.
1100 + *
1101 + * Caller holds tomoyo_read_lock().
1102 */
1103 static bool tomoyo_is_policy_manager(void)
1104 {
1105 @@ -1192,29 +1252,25 @@ static bool tomoyo_is_policy_manager(voi
1106 return true;
1107 if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
1108 return false;
1109 - down_read(&tomoyo_policy_manager_list_lock);
1110 - list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1111 + list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
1112 if (!ptr->is_deleted && ptr->is_domain
1113 && !tomoyo_pathcmp(domainname, ptr->manager)) {
1114 found = true;
1115 break;
1116 }
1117 }
1118 - up_read(&tomoyo_policy_manager_list_lock);
1119 if (found)
1120 return true;
1121 exe = tomoyo_get_exe();
1122 if (!exe)
1123 return false;
1124 - down_read(&tomoyo_policy_manager_list_lock);
1125 - list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1126 + list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
1127 if (!ptr->is_deleted && !ptr->is_domain
1128 && !strcmp(exe, ptr->manager->name)) {
1129 found = true;
1130 break;
1131 }
1132 }
1133 - up_read(&tomoyo_policy_manager_list_lock);
1134 if (!found) { /* Reduce error messages. */
1135 static pid_t last_pid;
1136 const pid_t pid = current->pid;
1137 @@ -1224,7 +1280,7 @@ static bool tomoyo_is_policy_manager(voi
1138 last_pid = pid;
1139 }
1140 }
1141 - tomoyo_free(exe);
1142 + kfree(exe);
1143 return found;
1144 }
1145
1146 @@ -1235,6 +1291,8 @@ static bool tomoyo_is_policy_manager(voi
1147 * @data: String to parse.
1148 *
1149 * Returns true on success, false otherwise.
1150 + *
1151 + * Caller holds tomoyo_read_lock().
1152 */
1153 static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1154 const char *data)
1155 @@ -1244,17 +1302,16 @@ static bool tomoyo_is_select_one(struct
1156
1157 if (sscanf(data, "pid=%u", &pid) == 1) {
1158 struct task_struct *p;
1159 + rcu_read_lock();
1160 read_lock(&tasklist_lock);
1161 p = find_task_by_vpid(pid);
1162 if (p)
1163 domain = tomoyo_real_domain(p);
1164 read_unlock(&tasklist_lock);
1165 + rcu_read_unlock();
1166 } else if (!strncmp(data, "domain=", 7)) {
1167 - if (tomoyo_is_domain_def(data + 7)) {
1168 - down_read(&tomoyo_domain_list_lock);
1169 + if (tomoyo_is_domain_def(data + 7))
1170 domain = tomoyo_find_domain(data + 7);
1171 - up_read(&tomoyo_domain_list_lock);
1172 - }
1173 } else
1174 return false;
1175 head->write_var1 = domain;
1176 @@ -1268,13 +1325,11 @@ static bool tomoyo_is_select_one(struct
1177 if (domain) {
1178 struct tomoyo_domain_info *d;
1179 head->read_var1 = NULL;
1180 - down_read(&tomoyo_domain_list_lock);
1181 - list_for_each_entry(d, &tomoyo_domain_list, list) {
1182 + list_for_each_entry_rcu(d, &tomoyo_domain_list, list) {
1183 if (d == domain)
1184 break;
1185 head->read_var1 = &d->list;
1186 }
1187 - up_read(&tomoyo_domain_list_lock);
1188 head->read_var2 = NULL;
1189 head->read_bit = 0;
1190 head->read_step = 0;
1191 @@ -1290,6 +1345,8 @@ static bool tomoyo_is_select_one(struct
1192 * @domainname: The name of domain.
1193 *
1194 * Returns 0.
1195 + *
1196 + * Caller holds tomoyo_read_lock().
1197 */
1198 static int tomoyo_delete_domain(char *domainname)
1199 {
1200 @@ -1298,9 +1355,10 @@ static int tomoyo_delete_domain(char *do
1201
1202 name.name = domainname;
1203 tomoyo_fill_path_info(&name);
1204 - down_write(&tomoyo_domain_list_lock);
1205 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
1206 + return 0;
1207 /* Is there an active domain? */
1208 - list_for_each_entry(domain, &tomoyo_domain_list, list) {
1209 + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
1210 /* Never delete tomoyo_kernel_domain */
1211 if (domain == &tomoyo_kernel_domain)
1212 continue;
1213 @@ -1310,7 +1368,7 @@ static int tomoyo_delete_domain(char *do
1214 domain->is_deleted = true;
1215 break;
1216 }
1217 - up_write(&tomoyo_domain_list_lock);
1218 + mutex_unlock(&tomoyo_policy_lock);
1219 return 0;
1220 }
1221
1222 @@ -1320,6 +1378,8 @@ static int tomoyo_delete_domain(char *do
1223 * @head: Pointer to "struct tomoyo_io_buffer".
1224 *
1225 * Returns 0 on success, negative value otherwise.
1226 + *
1227 + * Caller holds tomoyo_read_lock().
1228 */
1229 static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1230 {
1231 @@ -1342,11 +1402,9 @@ static int tomoyo_write_domain_policy(st
1232 domain = NULL;
1233 if (is_delete)
1234 tomoyo_delete_domain(data);
1235 - else if (is_select) {
1236 - down_read(&tomoyo_domain_list_lock);
1237 + else if (is_select)
1238 domain = tomoyo_find_domain(data);
1239 - up_read(&tomoyo_domain_list_lock);
1240 - } else
1241 + else
1242 domain = tomoyo_find_or_assign_new_domain(data, 0);
1243 head->write_var1 = domain;
1244 return 0;
1245 @@ -1361,46 +1419,39 @@ static int tomoyo_write_domain_policy(st
1246 return 0;
1247 }
1248 if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
1249 - tomoyo_set_domain_flag(domain, is_delete,
1250 - TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);
1251 + domain->ignore_global_allow_read = !is_delete;
1252 return 0;
1253 }
1254 return tomoyo_write_file_policy(data, domain, is_delete);
1255 }
1256
1257 /**
1258 - * tomoyo_print_single_path_acl - Print a single path ACL entry.
1259 + * tomoyo_print_path_acl - Print a single path ACL entry.
1260 *
1261 * @head: Pointer to "struct tomoyo_io_buffer".
1262 - * @ptr: Pointer to "struct tomoyo_single_path_acl_record".
1263 + * @ptr: Pointer to "struct tomoyo_path_acl".
1264 *
1265 * Returns true on success, false otherwise.
1266 */
1267 -static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head,
1268 - struct tomoyo_single_path_acl_record *
1269 - ptr)
1270 +static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head,
1271 + struct tomoyo_path_acl *ptr)
1272 {
1273 int pos;
1274 u8 bit;
1275 - const char *atmark = "";
1276 - const char *filename;
1277 - const u16 perm = ptr->perm;
1278 -
1279 - filename = ptr->filename->name;
1280 - for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION;
1281 - bit++) {
1282 - const char *msg;
1283 + const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16);
1284 +
1285 + for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
1286 if (!(perm & (1 << bit)))
1287 continue;
1288 /* Print "read/write" instead of "read" and "write". */
1289 - if ((bit == TOMOYO_TYPE_READ_ACL ||
1290 - bit == TOMOYO_TYPE_WRITE_ACL)
1291 - && (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
1292 + if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE)
1293 + && (perm & (1 << TOMOYO_TYPE_READ_WRITE)))
1294 continue;
1295 - msg = tomoyo_sp2keyword(bit);
1296 pos = head->read_avail;
1297 - if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg,
1298 - atmark, filename))
1299 + if (!tomoyo_io_printf(head, "allow_%s ",
1300 + tomoyo_path2keyword(bit)) ||
1301 + !tomoyo_print_name_union(head, &ptr->name) ||
1302 + !tomoyo_io_printf(head, "\n"))
1303 goto out;
1304 }
1305 head->read_bit = 0;
1306 @@ -1412,36 +1463,29 @@ static bool tomoyo_print_single_path_acl
1307 }
1308
1309 /**
1310 - * tomoyo_print_double_path_acl - Print a double path ACL entry.
1311 + * tomoyo_print_path2_acl - Print a double path ACL entry.
1312 *
1313 * @head: Pointer to "struct tomoyo_io_buffer".
1314 - * @ptr: Pointer to "struct tomoyo_double_path_acl_record".
1315 + * @ptr: Pointer to "struct tomoyo_path2_acl".
1316 *
1317 * Returns true on success, false otherwise.
1318 */
1319 -static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
1320 - struct tomoyo_double_path_acl_record *
1321 - ptr)
1322 +static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head,
1323 + struct tomoyo_path2_acl *ptr)
1324 {
1325 int pos;
1326 - const char *atmark1 = "";
1327 - const char *atmark2 = "";
1328 - const char *filename1;
1329 - const char *filename2;
1330 const u8 perm = ptr->perm;
1331 u8 bit;
1332
1333 - filename1 = ptr->filename1->name;
1334 - filename2 = ptr->filename2->name;
1335 - for (bit = head->read_bit; bit < TOMOYO_MAX_DOUBLE_PATH_OPERATION;
1336 - bit++) {
1337 - const char *msg;
1338 + for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) {
1339 if (!(perm & (1 << bit)))
1340 continue;
1341 - msg = tomoyo_dp2keyword(bit);
1342 pos = head->read_avail;
1343 - if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg,
1344 - atmark1, filename1, atmark2, filename2))
1345 + if (!tomoyo_io_printf(head, "allow_%s ",
1346 + tomoyo_path22keyword(bit)) ||
1347 + !tomoyo_print_name_union(head, &ptr->name1) ||
1348 + !tomoyo_print_name_union(head, &ptr->name2) ||
1349 + !tomoyo_io_printf(head, "\n"))
1350 goto out;
1351 }
1352 head->read_bit = 0;
1353 @@ -1463,23 +1507,17 @@ static bool tomoyo_print_double_path_acl
1354 static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1355 struct tomoyo_acl_info *ptr)
1356 {
1357 - const u8 acl_type = tomoyo_acl_type2(ptr);
1358 + const u8 acl_type = ptr->type;
1359
1360 - if (acl_type & TOMOYO_ACL_DELETED)
1361 - return true;
1362 - if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) {
1363 - struct tomoyo_single_path_acl_record *acl
1364 - = container_of(ptr,
1365 - struct tomoyo_single_path_acl_record,
1366 - head);
1367 - return tomoyo_print_single_path_acl(head, acl);
1368 - }
1369 - if (acl_type == TOMOYO_TYPE_DOUBLE_PATH_ACL) {
1370 - struct tomoyo_double_path_acl_record *acl
1371 - = container_of(ptr,
1372 - struct tomoyo_double_path_acl_record,
1373 - head);
1374 - return tomoyo_print_double_path_acl(head, acl);
1375 + if (acl_type == TOMOYO_TYPE_PATH_ACL) {
1376 + struct tomoyo_path_acl *acl
1377 + = container_of(ptr, struct tomoyo_path_acl, head);
1378 + return tomoyo_print_path_acl(head, acl);
1379 + }
1380 + if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
1381 + struct tomoyo_path2_acl *acl
1382 + = container_of(ptr, struct tomoyo_path2_acl, head);
1383 + return tomoyo_print_path2_acl(head, acl);
1384 }
1385 BUG(); /* This must not happen. */
1386 return false;
1387 @@ -1491,6 +1529,8 @@ static bool tomoyo_print_entry(struct to
1388 * @head: Pointer to "struct tomoyo_io_buffer".
1389 *
1390 * Returns 0.
1391 + *
1392 + * Caller holds tomoyo_read_lock().
1393 */
1394 static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
1395 {
1396 @@ -1502,7 +1542,6 @@ static int tomoyo_read_domain_policy(str
1397 return 0;
1398 if (head->read_step == 0)
1399 head->read_step = 1;
1400 - down_read(&tomoyo_domain_list_lock);
1401 list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) {
1402 struct tomoyo_domain_info *domain;
1403 const char *quota_exceeded = "";
1404 @@ -1516,10 +1555,9 @@ static int tomoyo_read_domain_policy(str
1405 /* Print domainname and flags. */
1406 if (domain->quota_warned)
1407 quota_exceeded = "quota_exceeded\n";
1408 - if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED)
1409 + if (domain->transition_failed)
1410 transition_failed = "transition_failed\n";
1411 - if (domain->flags &
1412 - TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)
1413 + if (domain->ignore_global_allow_read)
1414 ignore_global_allow_read
1415 = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1416 done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE
1417 @@ -1535,7 +1573,6 @@ acl_loop:
1418 if (head->read_step == 3)
1419 goto tail_mark;
1420 /* Print ACL entries in the domain. */
1421 - down_read(&tomoyo_domain_acl_info_list_lock);
1422 list_for_each_cookie(apos, head->read_var2,
1423 &domain->acl_info_list) {
1424 struct tomoyo_acl_info *ptr
1425 @@ -1545,7 +1582,6 @@ acl_loop:
1426 if (!done)
1427 break;
1428 }
1429 - up_read(&tomoyo_domain_acl_info_list_lock);
1430 if (!done)
1431 break;
1432 head->read_step = 3;
1433 @@ -1557,7 +1593,6 @@ tail_mark:
1434 if (head->read_single_domain)
1435 break;
1436 }
1437 - up_read(&tomoyo_domain_list_lock);
1438 head->read_eof = done;
1439 return 0;
1440 }
1441 @@ -1573,6 +1608,8 @@ tail_mark:
1442 *
1443 * ( echo "select " $domainname; echo "use_profile " $profile ) |
1444 * /usr/lib/ccs/loadpolicy -d
1445 + *
1446 + * Caller holds tomoyo_read_lock().
1447 */
1448 static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
1449 {
1450 @@ -1584,9 +1621,7 @@ static int tomoyo_write_domain_profile(s
1451 if (!cp)
1452 return -EINVAL;
1453 *cp = '\0';
1454 - down_read(&tomoyo_domain_list_lock);
1455 domain = tomoyo_find_domain(cp + 1);
1456 - up_read(&tomoyo_domain_list_lock);
1457 if (strict_strtoul(data, 10, &profile))
1458 return -EINVAL;
1459 if (domain && profile < TOMOYO_MAX_PROFILES
1460 @@ -1608,6 +1643,8 @@ static int tomoyo_write_domain_profile(s
1461 * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1462 * domainname = $0; } else if ( $1 == "use_profile" ) {
1463 * print $2 " " domainname; domainname = ""; } } ; '
1464 + *
1465 + * Caller holds tomoyo_read_lock().
1466 */
1467 static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1468 {
1469 @@ -1616,7 +1653,6 @@ static int tomoyo_read_domain_profile(st
1470
1471 if (head->read_eof)
1472 return 0;
1473 - down_read(&tomoyo_domain_list_lock);
1474 list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) {
1475 struct tomoyo_domain_info *domain;
1476 domain = list_entry(pos, struct tomoyo_domain_info, list);
1477 @@ -1627,7 +1663,6 @@ static int tomoyo_read_domain_profile(st
1478 if (!done)
1479 break;
1480 }
1481 - up_read(&tomoyo_domain_list_lock);
1482 head->read_eof = done;
1483 return 0;
1484 }
1485 @@ -1665,11 +1700,13 @@ static int tomoyo_read_pid(struct tomoyo
1486 const int pid = head->read_step;
1487 struct task_struct *p;
1488 struct tomoyo_domain_info *domain = NULL;
1489 + rcu_read_lock();
1490 read_lock(&tasklist_lock);
1491 p = find_task_by_vpid(pid);
1492 if (p)
1493 domain = tomoyo_real_domain(p);
1494 read_unlock(&tasklist_lock);
1495 + rcu_read_unlock();
1496 if (domain)
1497 tomoyo_io_printf(head, "%d %u %s", pid, domain->profile,
1498 domain->domainname->name);
1499 @@ -1684,6 +1721,8 @@ static int tomoyo_read_pid(struct tomoyo
1500 * @head: Pointer to "struct tomoyo_io_buffer".
1501 *
1502 * Returns 0 on success, negative value otherwise.
1503 + *
1504 + * Caller holds tomoyo_read_lock().
1505 */
1506 static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
1507 {
1508 @@ -1709,6 +1748,8 @@ static int tomoyo_write_exception_policy
1509 return tomoyo_write_pattern_policy(data, is_delete);
1510 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE))
1511 return tomoyo_write_no_rewrite_policy(data, is_delete);
1512 + if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP))
1513 + return tomoyo_write_path_group_policy(data, is_delete);
1514 return -EINVAL;
1515 }
1516
1517 @@ -1718,6 +1759,8 @@ static int tomoyo_write_exception_policy
1518 * @head: Pointer to "struct tomoyo_io_buffer".
1519 *
1520 * Returns 0 on success, -EINVAL otherwise.
1521 + *
1522 + * Caller holds tomoyo_read_lock().
1523 */
1524 static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
1525 {
1526 @@ -1763,6 +1806,12 @@ static int tomoyo_read_exception_policy(
1527 head->read_var2 = NULL;
1528 head->read_step = 9;
1529 case 9:
1530 + if (!tomoyo_read_path_group_policy(head))
1531 + break;
1532 + head->read_var1 = NULL;
1533 + head->read_var2 = NULL;
1534 + head->read_step = 10;
1535 + case 10:
1536 head->read_eof = true;
1537 break;
1538 default:
1539 @@ -1847,15 +1896,13 @@ void tomoyo_load_policy(const char *file
1540 tomoyo_policy_loaded = true;
1541 { /* Check all profiles currently assigned to domains are defined. */
1542 struct tomoyo_domain_info *domain;
1543 - down_read(&tomoyo_domain_list_lock);
1544 - list_for_each_entry(domain, &tomoyo_domain_list, list) {
1545 + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
1546 const u8 profile = domain->profile;
1547 if (tomoyo_profile_ptr[profile])
1548 continue;
1549 panic("Profile %u (used by '%s') not defined.\n",
1550 profile, domain->domainname->name);
1551 }
1552 - up_read(&tomoyo_domain_list_lock);
1553 }
1554 }
1555
1556 @@ -1903,10 +1950,12 @@ static int tomoyo_read_self_domain(struc
1557 * @file: Pointer to "struct file".
1558 *
1559 * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
1560 + *
1561 + * Caller acquires tomoyo_read_lock().
1562 */
1563 static int tomoyo_open_control(const u8 type, struct file *file)
1564 {
1565 - struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head));
1566 + struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_NOFS);
1567
1568 if (!head)
1569 return -ENOMEM;
1570 @@ -1967,9 +2016,9 @@ static int tomoyo_open_control(const u8
1571 } else {
1572 if (!head->readbuf_size)
1573 head->readbuf_size = 4096 * 2;
1574 - head->read_buf = tomoyo_alloc(head->readbuf_size);
1575 + head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS);
1576 if (!head->read_buf) {
1577 - tomoyo_free(head);
1578 + kfree(head);
1579 return -ENOMEM;
1580 }
1581 }
1582 @@ -1981,13 +2030,14 @@ static int tomoyo_open_control(const u8
1583 head->write = NULL;
1584 } else if (head->write) {
1585 head->writebuf_size = 4096 * 2;
1586 - head->write_buf = tomoyo_alloc(head->writebuf_size);
1587 + head->write_buf = kzalloc(head->writebuf_size, GFP_NOFS);
1588 if (!head->write_buf) {
1589 - tomoyo_free(head->read_buf);
1590 - tomoyo_free(head);
1591 + kfree(head->read_buf);
1592 + kfree(head);
1593 return -ENOMEM;
1594 }
1595 }
1596 + head->reader_idx = tomoyo_read_lock();
1597 file->private_data = head;
1598 /*
1599 * Call the handler now if the file is
1600 @@ -2009,6 +2059,8 @@ static int tomoyo_open_control(const u8
1601 * @buffer_len: Size of @buffer.
1602 *
1603 * Returns bytes read on success, negative value otherwise.
1604 + *
1605 + * Caller holds tomoyo_read_lock().
1606 */
1607 static int tomoyo_read_control(struct file *file, char __user *buffer,
1608 const int buffer_len)
1609 @@ -2052,6 +2104,8 @@ static int tomoyo_read_control(struct fi
1610 * @buffer_len: Size of @buffer.
1611 *
1612 * Returns @buffer_len on success, negative value otherwise.
1613 + *
1614 + * Caller holds tomoyo_read_lock().
1615 */
1616 static int tomoyo_write_control(struct file *file, const char __user *buffer,
1617 const int buffer_len)
1618 @@ -2102,52 +2156,29 @@ static int tomoyo_write_control(struct f
1619 * @file: Pointer to "struct file".
1620 *
1621 * Releases memory and returns 0.
1622 + *
1623 + * Caller looses tomoyo_read_lock().
1624 */
1625 static int tomoyo_close_control(struct file *file)
1626 {
1627 struct tomoyo_io_buffer *head = file->private_data;
1628 + const bool is_write = !!head->write_buf;
1629
1630 + tomoyo_read_unlock(head->reader_idx);
1631 /* Release memory used for policy I/O. */
1632 - tomoyo_free(head->read_buf);
1633 + kfree(head->read_buf);
1634 head->read_buf = NULL;
1635 - tomoyo_free(head->write_buf);
1636 + kfree(head->write_buf);
1637 head->write_buf = NULL;
1638 - tomoyo_free(head);
1639 + kfree(head);
1640 head = NULL;
1641 file->private_data = NULL;
1642 + if (is_write)
1643 + tomoyo_run_gc();
1644 return 0;
1645 }
1646
1647 /**
1648 - * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry.
1649 - *
1650 - * @acl_type: Type of ACL entry.
1651 - *
1652 - * Returns pointer to the ACL entry on success, NULL otherwise.
1653 - */
1654 -void *tomoyo_alloc_acl_element(const u8 acl_type)
1655 -{
1656 - int len;
1657 - struct tomoyo_acl_info *ptr;
1658 -
1659 - switch (acl_type) {
1660 - case TOMOYO_TYPE_SINGLE_PATH_ACL:
1661 - len = sizeof(struct tomoyo_single_path_acl_record);
1662 - break;
1663 - case TOMOYO_TYPE_DOUBLE_PATH_ACL:
1664 - len = sizeof(struct tomoyo_double_path_acl_record);
1665 - break;
1666 - default:
1667 - return NULL;
1668 - }
1669 - ptr = tomoyo_alloc_element(len);
1670 - if (!ptr)
1671 - return NULL;
1672 - ptr->type = acl_type;
1673 - return ptr;
1674 -}
1675 -
1676 -/**
1677 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
1678 *
1679 * @inode: Pointer to "struct inode".
1680 --- linux-2.6.32.28.orig/security/tomoyo/common.h
1681 +++ linux-2.6.32.28/security/tomoyo/common.h
1682 @@ -1,12 +1,9 @@
1683 /*
1684 * security/tomoyo/common.h
1685 *
1686 - * Common functions for TOMOYO.
1687 - *
1688 - * Copyright (C) 2005-2009 NTT DATA CORPORATION
1689 - *
1690 - * Version: 2.2.0 2009/04/01
1691 + * Header file for TOMOYO.
1692 *
1693 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
1694 */
1695
1696 #ifndef _SECURITY_TOMOYO_COMMON_H
1697 @@ -22,9 +19,120 @@
1698 #include <linux/namei.h>
1699 #include <linux/mount.h>
1700 #include <linux/list.h>
1701 +#include <linux/cred.h>
1702 +struct linux_binprm;
1703 +
1704 +/********** Constants definitions. **********/
1705 +
1706 +/*
1707 + * TOMOYO uses this hash only when appending a string into the string
1708 + * table. Frequency of appending strings is very low. So we don't need
1709 + * large (e.g. 64k) hash size. 256 will be sufficient.
1710 + */
1711 +#define TOMOYO_HASH_BITS 8
1712 +#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)
1713 +
1714 +/*
1715 + * This is the max length of a token.
1716 + *
1717 + * A token consists of only ASCII printable characters.
1718 + * Non printable characters in a token is represented in \ooo style
1719 + * octal string. Thus, \ itself is represented as \\.
1720 + */
1721 +#define TOMOYO_MAX_PATHNAME_LEN 4000
1722 +
1723 +/* Profile number is an integer between 0 and 255. */
1724 +#define TOMOYO_MAX_PROFILES 256
1725 +
1726 +/* Keywords for ACLs. */
1727 +#define TOMOYO_KEYWORD_ALIAS "alias "
1728 +#define TOMOYO_KEYWORD_ALLOW_READ "allow_read "
1729 +#define TOMOYO_KEYWORD_DELETE "delete "
1730 +#define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite "
1731 +#define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern "
1732 +#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain "
1733 +#define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain "
1734 +#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain "
1735 +#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain "
1736 +#define TOMOYO_KEYWORD_PATH_GROUP "path_group "
1737 +#define TOMOYO_KEYWORD_SELECT "select "
1738 +#define TOMOYO_KEYWORD_USE_PROFILE "use_profile "
1739 +#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read"
1740 +/* A domain definition starts with <kernel>. */
1741 +#define TOMOYO_ROOT_NAME "<kernel>"
1742 +#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1)
1743 +
1744 +/* Index numbers for Access Controls. */
1745 +enum tomoyo_mac_index {
1746 + TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */
1747 + TOMOYO_MAX_ACCEPT_ENTRY,
1748 + TOMOYO_VERBOSE,
1749 + TOMOYO_MAX_CONTROL_INDEX
1750 +};
1751 +
1752 +/* Index numbers for Access Controls. */
1753 +enum tomoyo_acl_entry_type_index {
1754 + TOMOYO_TYPE_PATH_ACL,
1755 + TOMOYO_TYPE_PATH2_ACL,
1756 +};
1757 +
1758 +/* Index numbers for File Controls. */
1759
1760 -struct dentry;
1761 -struct vfsmount;
1762 +/*
1763 + * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set
1764 + * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and
1765 + * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set.
1766 + * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or
1767 + * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are
1768 + * automatically cleared if TYPE_READ_WRITE_ACL is cleared.
1769 + */
1770 +
1771 +enum tomoyo_path_acl_index {
1772 + TOMOYO_TYPE_READ_WRITE,
1773 + TOMOYO_TYPE_EXECUTE,
1774 + TOMOYO_TYPE_READ,
1775 + TOMOYO_TYPE_WRITE,
1776 + TOMOYO_TYPE_CREATE,
1777 + TOMOYO_TYPE_UNLINK,
1778 + TOMOYO_TYPE_MKDIR,
1779 + TOMOYO_TYPE_RMDIR,
1780 + TOMOYO_TYPE_MKFIFO,
1781 + TOMOYO_TYPE_MKSOCK,
1782 + TOMOYO_TYPE_MKBLOCK,
1783 + TOMOYO_TYPE_MKCHAR,
1784 + TOMOYO_TYPE_TRUNCATE,
1785 + TOMOYO_TYPE_SYMLINK,
1786 + TOMOYO_TYPE_REWRITE,
1787 + TOMOYO_TYPE_IOCTL,
1788 + TOMOYO_TYPE_CHMOD,
1789 + TOMOYO_TYPE_CHOWN,
1790 + TOMOYO_TYPE_CHGRP,
1791 + TOMOYO_TYPE_CHROOT,
1792 + TOMOYO_TYPE_MOUNT,
1793 + TOMOYO_TYPE_UMOUNT,
1794 + TOMOYO_MAX_PATH_OPERATION
1795 +};
1796 +
1797 +enum tomoyo_path2_acl_index {
1798 + TOMOYO_TYPE_LINK,
1799 + TOMOYO_TYPE_RENAME,
1800 + TOMOYO_TYPE_PIVOT_ROOT,
1801 + TOMOYO_MAX_PATH2_OPERATION
1802 +};
1803 +
1804 +enum tomoyo_securityfs_interface_index {
1805 + TOMOYO_DOMAINPOLICY,
1806 + TOMOYO_EXCEPTIONPOLICY,
1807 + TOMOYO_DOMAIN_STATUS,
1808 + TOMOYO_PROCESS_STATUS,
1809 + TOMOYO_MEMINFO,
1810 + TOMOYO_SELFDOMAIN,
1811 + TOMOYO_VERSION,
1812 + TOMOYO_PROFILE,
1813 + TOMOYO_MANAGER
1814 +};
1815 +
1816 +/********** Structure definitions. **********/
1817
1818 /*
1819 * tomoyo_page_buffer is a structure which is used for holding a pathname
1820 @@ -56,9 +164,6 @@ struct tomoyo_page_buffer {
1821 * (5) "is_patterned" is a bool which is true if "name" contains wildcard
1822 * characters, false otherwise. This allows TOMOYO to use "hash" and
1823 * strcmp() for string comparison if "is_patterned" is false.
1824 - * (6) "depth" is calculated using the number of "/" characters in "name".
1825 - * This allows TOMOYO to avoid comparing two pathnames which never match
1826 - * (e.g. whether "/var/www/html/index.html" matches "/tmp/sh-thd-\$").
1827 */
1828 struct tomoyo_path_info {
1829 const char *name;
1830 @@ -66,17 +171,17 @@ struct tomoyo_path_info {
1831 u16 const_len; /* = tomoyo_const_part_length(name) */
1832 bool is_dir; /* = tomoyo_strendswith(name, "/") */
1833 bool is_patterned; /* = tomoyo_path_contains_pattern(name) */
1834 - u16 depth; /* = tomoyo_path_depth(name) */
1835 };
1836
1837 /*
1838 - * This is the max length of a token.
1839 - *
1840 - * A token consists of only ASCII printable characters.
1841 - * Non printable characters in a token is represented in \ooo style
1842 - * octal string. Thus, \ itself is represented as \\.
1843 + * tomoyo_name_entry is a structure which is used for linking
1844 + * "struct tomoyo_path_info" into tomoyo_name_list .
1845 */
1846 -#define TOMOYO_MAX_PATHNAME_LEN 4000
1847 +struct tomoyo_name_entry {
1848 + struct list_head list;
1849 + atomic_t users;
1850 + struct tomoyo_path_info entry;
1851 +};
1852
1853 /*
1854 * tomoyo_path_info_with_data is a structure which is used for holding a
1855 @@ -93,42 +198,52 @@ struct tomoyo_path_info {
1856 * "struct tomoyo_path_info_with_data".
1857 */
1858 struct tomoyo_path_info_with_data {
1859 - /* Keep "head" first, for this pointer is passed to tomoyo_free(). */
1860 + /* Keep "head" first, for this pointer is passed to kfree(). */
1861 struct tomoyo_path_info head;
1862 char barrier1[16]; /* Safeguard for overrun. */
1863 char body[TOMOYO_MAX_PATHNAME_LEN];
1864 char barrier2[16]; /* Safeguard for overrun. */
1865 };
1866
1867 +struct tomoyo_name_union {
1868 + const struct tomoyo_path_info *filename;
1869 + struct tomoyo_path_group *group;
1870 + u8 is_group;
1871 +};
1872 +
1873 +/* Structure for "path_group" directive. */
1874 +struct tomoyo_path_group {
1875 + struct list_head list;
1876 + const struct tomoyo_path_info *group_name;
1877 + struct list_head member_list;
1878 + atomic_t users;
1879 +};
1880 +
1881 +/* Structure for "path_group" directive. */
1882 +struct tomoyo_path_group_member {
1883 + struct list_head list;
1884 + bool is_deleted;
1885 + const struct tomoyo_path_info *member_name;
1886 +};
1887 +
1888 /*
1889 * tomoyo_acl_info is a structure which is used for holding
1890 *
1891 * (1) "list" which is linked to the ->acl_info_list of
1892 * "struct tomoyo_domain_info"
1893 - * (2) "type" which tells
1894 - * (a) type & 0x7F : type of the entry (either
1895 - * "struct tomoyo_single_path_acl_record" or
1896 - * "struct tomoyo_double_path_acl_record")
1897 - * (b) type & 0x80 : whether the entry is marked as "deleted".
1898 + * (2) "type" which tells type of the entry (either
1899 + * "struct tomoyo_path_acl" or "struct tomoyo_path2_acl").
1900 *
1901 * Packing "struct tomoyo_acl_info" allows
1902 - * "struct tomoyo_single_path_acl_record" to embed "u16" and
1903 - * "struct tomoyo_double_path_acl_record" to embed "u8"
1904 + * "struct tomoyo_path_acl" to embed "u8" + "u16" and
1905 + * "struct tomoyo_path2_acl" to embed "u8"
1906 * without enlarging their structure size.
1907 */
1908 struct tomoyo_acl_info {
1909 struct list_head list;
1910 - /*
1911 - * Type of this ACL entry.
1912 - *
1913 - * MSB is is_deleted flag.
1914 - */
1915 u8 type;
1916 } __packed;
1917
1918 -/* This ACL entry is deleted. */
1919 -#define TOMOYO_ACL_DELETED 0x80
1920 -
1921 /*
1922 * tomoyo_domain_info is a structure which is used for holding permissions
1923 * (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
1924 @@ -142,7 +257,17 @@ struct tomoyo_acl_info {
1925 * "deleted", false otherwise.
1926 * (6) "quota_warned" is a bool which is used for suppressing warning message
1927 * when learning mode learned too much entries.
1928 - * (7) "flags" which remembers this domain's attributes.
1929 + * (7) "ignore_global_allow_read" is a bool which is true if this domain
1930 + * should ignore "allow_read" directive in exception policy.
1931 + * (8) "transition_failed" is a bool which is set to true when this domain was
1932 + * unable to create a new domain at tomoyo_find_next_domain() because the
1933 + * name of the domain to be created was too long or it could not allocate
1934 + * memory. If set to true, more than one process continued execve()
1935 + * without domain transition.
1936 + * (9) "users" is an atomic_t that holds how many "struct cred"->security
1937 + * are referring this "struct tomoyo_domain_info". If is_deleted == true
1938 + * and users == 0, this struct will be kfree()d upon next garbage
1939 + * collection.
1940 *
1941 * A domain's lifecycle is an analogy of files on / directory.
1942 * Multiple domains with the same domainname cannot be created (as with
1943 @@ -159,88 +284,54 @@ struct tomoyo_domain_info {
1944 u8 profile; /* Profile number to use. */
1945 bool is_deleted; /* Delete flag. */
1946 bool quota_warned; /* Quota warnning flag. */
1947 - /* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */
1948 - u8 flags;
1949 + bool ignore_global_allow_read; /* Ignore "allow_read" flag. */
1950 + bool transition_failed; /* Domain transition failed flag. */
1951 + atomic_t users; /* Number of referring credentials. */
1952 };
1953
1954 -/* Profile number is an integer between 0 and 255. */
1955 -#define TOMOYO_MAX_PROFILES 256
1956 -
1957 -/* Ignore "allow_read" directive in exception policy. */
1958 -#define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1
1959 /*
1960 - * This domain was unable to create a new domain at tomoyo_find_next_domain()
1961 - * because the name of the domain to be created was too long or
1962 - * it could not allocate memory.
1963 - * More than one process continued execve() without domain transition.
1964 - */
1965 -#define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED 2
1966 -
1967 -/*
1968 - * tomoyo_single_path_acl_record is a structure which is used for holding an
1969 + * tomoyo_path_acl is a structure which is used for holding an
1970 * entry with one pathname operation (e.g. open(), mkdir()).
1971 * It has following fields.
1972 *
1973 * (1) "head" which is a "struct tomoyo_acl_info".
1974 * (2) "perm" which is a bitmask of permitted operations.
1975 - * (3) "filename" is the pathname.
1976 + * (3) "name" is the pathname.
1977 *
1978 * Directives held by this structure are "allow_read/write", "allow_execute",
1979 * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir",
1980 * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock",
1981 - * "allow_mkchar", "allow_truncate", "allow_symlink" and "allow_rewrite".
1982 - */
1983 -struct tomoyo_single_path_acl_record {
1984 - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_SINGLE_PATH_ACL */
1985 + * "allow_mkchar", "allow_truncate", "allow_symlink", "allow_rewrite",
1986 + * "allow_chmod", "allow_chown", "allow_chgrp", "allow_chroot", "allow_mount"
1987 + * and "allow_unmount".
1988 + */
1989 +struct tomoyo_path_acl {
1990 + struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */
1991 + u8 perm_high;
1992 u16 perm;
1993 - /* Pointer to single pathname. */
1994 - const struct tomoyo_path_info *filename;
1995 + struct tomoyo_name_union name;
1996 };
1997
1998 /*
1999 - * tomoyo_double_path_acl_record is a structure which is used for holding an
2000 - * entry with two pathnames operation (i.e. link() and rename()).
2001 + * tomoyo_path2_acl is a structure which is used for holding an
2002 + * entry with two pathnames operation (i.e. link(), rename() and pivot_root()).
2003 * It has following fields.
2004 *
2005 * (1) "head" which is a "struct tomoyo_acl_info".
2006 * (2) "perm" which is a bitmask of permitted operations.
2007 - * (3) "filename1" is the source/old pathname.
2008 - * (4) "filename2" is the destination/new pathname.
2009 + * (3) "name1" is the source/old pathname.
2010 + * (4) "name2" is the destination/new pathname.
2011 *
2012 - * Directives held by this structure are "allow_rename" and "allow_link".
2013 + * Directives held by this structure are "allow_rename", "allow_link" and
2014 + * "allow_pivot_root".
2015 */
2016 -struct tomoyo_double_path_acl_record {
2017 - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_DOUBLE_PATH_ACL */
2018 +struct tomoyo_path2_acl {
2019 + struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */
2020 u8 perm;
2021 - /* Pointer to single pathname. */
2022 - const struct tomoyo_path_info *filename1;
2023 - /* Pointer to single pathname. */
2024 - const struct tomoyo_path_info *filename2;
2025 + struct tomoyo_name_union name1;
2026 + struct tomoyo_name_union name2;
2027 };
2028
2029 -/* Keywords for ACLs. */
2030 -#define TOMOYO_KEYWORD_ALIAS "alias "
2031 -#define TOMOYO_KEYWORD_ALLOW_READ "allow_read "
2032 -#define TOMOYO_KEYWORD_DELETE "delete "
2033 -#define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite "
2034 -#define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern "
2035 -#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain "
2036 -#define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain "
2037 -#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain "
2038 -#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain "
2039 -#define TOMOYO_KEYWORD_SELECT "select "
2040 -#define TOMOYO_KEYWORD_USE_PROFILE "use_profile "
2041 -#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read"
2042 -/* A domain definition starts with <kernel>. */
2043 -#define TOMOYO_ROOT_NAME "<kernel>"
2044 -#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1)
2045 -
2046 -/* Index numbers for Access Controls. */
2047 -#define TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */
2048 -#define TOMOYO_MAX_ACCEPT_ENTRY 1
2049 -#define TOMOYO_VERBOSE 2
2050 -#define TOMOYO_MAX_CONTROL_INDEX 3
2051 -
2052 /*
2053 * tomoyo_io_buffer is a structure which is used for reading and modifying
2054 * configuration via /sys/kernel/security/tomoyo/ interface.
2055 @@ -269,6 +360,8 @@ struct tomoyo_io_buffer {
2056 int (*write) (struct tomoyo_io_buffer *);
2057 /* Exclusive lock for this structure. */
2058 struct mutex io_sem;
2059 + /* Index returned by tomoyo_read_lock(). */
2060 + int reader_idx;
2061 /* The position currently reading from. */
2062 struct list_head *read_var1;
2063 /* Extra variables for reading. */
2064 @@ -297,20 +390,170 @@ struct tomoyo_io_buffer {
2065 int writebuf_size;
2066 };
2067
2068 +/*
2069 + * tomoyo_globally_readable_file_entry is a structure which is used for holding
2070 + * "allow_read" entries.
2071 + * It has following fields.
2072 + *
2073 + * (1) "list" which is linked to tomoyo_globally_readable_list .
2074 + * (2) "filename" is a pathname which is allowed to open(O_RDONLY).
2075 + * (3) "is_deleted" is a bool which is true if marked as deleted, false
2076 + * otherwise.
2077 + */
2078 +struct tomoyo_globally_readable_file_entry {
2079 + struct list_head list;
2080 + const struct tomoyo_path_info *filename;
2081 + bool is_deleted;
2082 +};
2083 +
2084 +/*
2085 + * tomoyo_pattern_entry is a structure which is used for holding
2086 + * "tomoyo_pattern_list" entries.
2087 + * It has following fields.
2088 + *
2089 + * (1) "list" which is linked to tomoyo_pattern_list .
2090 + * (2) "pattern" is a pathname pattern which is used for converting pathnames
2091 + * to pathname patterns during learning mode.
2092 + * (3) "is_deleted" is a bool which is true if marked as deleted, false
2093 + * otherwise.
2094 + */
2095 +struct tomoyo_pattern_entry {
2096 + struct list_head list;
2097 + const struct tomoyo_path_info *pattern;
2098 + bool is_deleted;
2099 +};
2100 +
2101 +/*
2102 + * tomoyo_no_rewrite_entry is a structure which is used for holding
2103 + * "deny_rewrite" entries.
2104 + * It has following fields.
2105 + *
2106 + * (1) "list" which is linked to tomoyo_no_rewrite_list .
2107 + * (2) "pattern" is a pathname which is by default not permitted to modify
2108 + * already existing content.
2109 + * (3) "is_deleted" is a bool which is true if marked as deleted, false
2110 + * otherwise.
2111 + */
2112 +struct tomoyo_no_rewrite_entry {
2113 + struct list_head list;
2114 + const struct tomoyo_path_info *pattern;
2115 + bool is_deleted;
2116 +};
2117 +
2118 +/*
2119 + * tomoyo_domain_initializer_entry is a structure which is used for holding
2120 + * "initialize_domain" and "no_initialize_domain" entries.
2121 + * It has following fields.
2122 + *
2123 + * (1) "list" which is linked to tomoyo_domain_initializer_list .
2124 + * (2) "domainname" which is "a domainname" or "the last component of a
2125 + * domainname". This field is NULL if "from" clause is not specified.
2126 + * (3) "program" which is a program's pathname.
2127 + * (4) "is_deleted" is a bool which is true if marked as deleted, false
2128 + * otherwise.
2129 + * (5) "is_not" is a bool which is true if "no_initialize_domain", false
2130 + * otherwise.
2131 + * (6) "is_last_name" is a bool which is true if "domainname" is "the last
2132 + * component of a domainname", false otherwise.
2133 + */
2134 +struct tomoyo_domain_initializer_entry {
2135 + struct list_head list;
2136 + const struct tomoyo_path_info *domainname; /* This may be NULL */
2137 + const struct tomoyo_path_info *program;
2138 + bool is_deleted;
2139 + bool is_not; /* True if this entry is "no_initialize_domain". */
2140 + /* True if the domainname is tomoyo_get_last_name(). */
2141 + bool is_last_name;
2142 +};
2143 +
2144 +/*
2145 + * tomoyo_domain_keeper_entry is a structure which is used for holding
2146 + * "keep_domain" and "no_keep_domain" entries.
2147 + * It has following fields.
2148 + *
2149 + * (1) "list" which is linked to tomoyo_domain_keeper_list .
2150 + * (2) "domainname" which is "a domainname" or "the last component of a
2151 + * domainname".
2152 + * (3) "program" which is a program's pathname.
2153 + * This field is NULL if "from" clause is not specified.
2154 + * (4) "is_deleted" is a bool which is true if marked as deleted, false
2155 + * otherwise.
2156 + * (5) "is_not" is a bool which is true if "no_initialize_domain", false
2157 + * otherwise.
2158 + * (6) "is_last_name" is a bool which is true if "domainname" is "the last
2159 + * component of a domainname", false otherwise.
2160 + */
2161 +struct tomoyo_domain_keeper_entry {
2162 + struct list_head list;
2163 + const struct tomoyo_path_info *domainname;
2164 + const struct tomoyo_path_info *program; /* This may be NULL */
2165 + bool is_deleted;
2166 + bool is_not; /* True if this entry is "no_keep_domain". */
2167 + /* True if the domainname is tomoyo_get_last_name(). */
2168 + bool is_last_name;
2169 +};
2170 +
2171 +/*
2172 + * tomoyo_alias_entry is a structure which is used for holding "alias" entries.
2173 + * It has following fields.
2174 + *
2175 + * (1) "list" which is linked to tomoyo_alias_list .
2176 + * (2) "original_name" which is a dereferenced pathname.
2177 + * (3) "aliased_name" which is a symlink's pathname.
2178 + * (4) "is_deleted" is a bool which is true if marked as deleted, false
2179 + * otherwise.
2180 + */
2181 +struct tomoyo_alias_entry {
2182 + struct list_head list;
2183 + const struct tomoyo_path_info *original_name;
2184 + const struct tomoyo_path_info *aliased_name;
2185 + bool is_deleted;
2186 +};
2187 +
2188 +/*
2189 + * tomoyo_policy_manager_entry is a structure which is used for holding list of
2190 + * domainnames or programs which are permitted to modify configuration via
2191 + * /sys/kernel/security/tomoyo/ interface.
2192 + * It has following fields.
2193 + *
2194 + * (1) "list" which is linked to tomoyo_policy_manager_list .
2195 + * (2) "manager" is a domainname or a program's pathname.
2196 + * (3) "is_domain" is a bool which is true if "manager" is a domainname, false
2197 + * otherwise.
2198 + * (4) "is_deleted" is a bool which is true if marked as deleted, false
2199 + * otherwise.
2200 + */
2201 +struct tomoyo_policy_manager_entry {
2202 + struct list_head list;
2203 + /* A path to program or a domainname. */
2204 + const struct tomoyo_path_info *manager;
2205 + bool is_domain; /* True if manager is a domainname. */
2206 + bool is_deleted; /* True if this entry is deleted. */
2207 +};
2208 +
2209 +/********** Function prototypes. **********/
2210 +
2211 +/* Check whether the given name matches the given name_union. */
2212 +bool tomoyo_compare_name_union(const struct tomoyo_path_info *name,
2213 + const struct tomoyo_name_union *ptr);
2214 /* Check whether the domain has too many ACL entries to hold. */
2215 bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain);
2216 /* Transactional sprintf() for policy dump. */
2217 bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
2218 __attribute__ ((format(printf, 2, 3)));
2219 /* Check whether the domainname is correct. */
2220 -bool tomoyo_is_correct_domain(const unsigned char *domainname,
2221 - const char *function);
2222 +bool tomoyo_is_correct_domain(const unsigned char *domainname);
2223 /* Check whether the token is correct. */
2224 bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
2225 - const s8 pattern_type, const s8 end_type,
2226 - const char *function);
2227 + const s8 pattern_type, const s8 end_type);
2228 /* Check whether the token can be a domainname. */
2229 bool tomoyo_is_domain_def(const unsigned char *buffer);
2230 +bool tomoyo_parse_name_union(const char *filename,
2231 + struct tomoyo_name_union *ptr);
2232 +/* Check whether the given filename matches the given path_group. */
2233 +bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
2234 + const struct tomoyo_path_group *group,
2235 + const bool may_use_pattern);
2236 /* Check whether the given filename matches the given pattern. */
2237 bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
2238 const struct tomoyo_path_info *pattern);
2239 @@ -325,20 +568,24 @@ bool tomoyo_read_domain_initializer_poli
2240 bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head);
2241 /* Read "file_pattern" entry in exception policy. */
2242 bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head);
2243 +/* Read "path_group" entry in exception policy. */
2244 +bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head);
2245 /* Read "allow_read" entry in exception policy. */
2246 bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head);
2247 /* Read "deny_rewrite" entry in exception policy. */
2248 bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head);
2249 +/* Tokenize a line. */
2250 +bool tomoyo_tokenize(char *buffer, char *w[], size_t size);
2251 /* Write domain policy violation warning message to console? */
2252 bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain);
2253 /* Convert double path operation to operation name. */
2254 -const char *tomoyo_dp2keyword(const u8 operation);
2255 +const char *tomoyo_path22keyword(const u8 operation);
2256 /* Get the last component of the given domainname. */
2257 const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain);
2258 /* Get warning message. */
2259 const char *tomoyo_get_msg(const bool is_enforce);
2260 /* Convert single path operation to operation name. */
2261 -const char *tomoyo_sp2keyword(const u8 operation);
2262 +const char *tomoyo_path2keyword(const u8 operation);
2263 /* Create "alias" entry in exception policy. */
2264 int tomoyo_write_alias_policy(char *data, const bool is_delete);
2265 /*
2266 @@ -365,42 +612,128 @@ int tomoyo_write_globally_readable_polic
2267 int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete);
2268 /* Create "file_pattern" entry in exception policy. */
2269 int tomoyo_write_pattern_policy(char *data, const bool is_delete);
2270 +/* Create "path_group" entry in exception policy. */
2271 +int tomoyo_write_path_group_policy(char *data, const bool is_delete);
2272 /* Find a domain by the given name. */
2273 struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
2274 /* Find or create a domain by the given name. */
2275 struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
2276 domainname,
2277 const u8 profile);
2278 +
2279 +/* Allocate memory for "struct tomoyo_path_group". */
2280 +struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name);
2281 +
2282 /* Check mode for specified functionality. */
2283 unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
2284 const u8 index);
2285 -/* Allocate memory for structures. */
2286 -void *tomoyo_alloc_acl_element(const u8 acl_type);
2287 /* Fill in "struct tomoyo_path_info" members. */
2288 void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
2289 /* Run policy loader when /sbin/init starts. */
2290 void tomoyo_load_policy(const char *filename);
2291 -/* Change "struct tomoyo_domain_info"->flags. */
2292 -void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
2293 - const bool is_delete, const u8 flags);
2294
2295 -/* strcmp() for "struct tomoyo_path_info" structure. */
2296 -static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
2297 - const struct tomoyo_path_info *b)
2298 +/* Convert binary string to ascii string. */
2299 +int tomoyo_encode(char *buffer, int buflen, const char *str);
2300 +
2301 +/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
2302 +int tomoyo_realpath_from_path2(struct path *path, char *newname,
2303 + int newname_len);
2304 +
2305 +/*
2306 + * Returns realpath(3) of the given pathname but ignores chroot'ed root.
2307 + * These functions use kzalloc(), so the caller must call kfree()
2308 + * if these functions didn't return NULL.
2309 + */
2310 +char *tomoyo_realpath(const char *pathname);
2311 +/*
2312 + * Same with tomoyo_realpath() except that it doesn't follow the final symlink.
2313 + */
2314 +char *tomoyo_realpath_nofollow(const char *pathname);
2315 +/* Same with tomoyo_realpath() except that the pathname is already solved. */
2316 +char *tomoyo_realpath_from_path(struct path *path);
2317 +
2318 +/* Check memory quota. */
2319 +bool tomoyo_memory_ok(void *ptr);
2320 +void *tomoyo_commit_ok(void *data, const unsigned int size);
2321 +
2322 +/*
2323 + * Keep the given name on the RAM.
2324 + * The RAM is shared, so NEVER try to modify or kfree() the returned name.
2325 + */
2326 +const struct tomoyo_path_info *tomoyo_get_name(const char *name);
2327 +
2328 +/* Check for memory usage. */
2329 +int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head);
2330 +
2331 +/* Set memory quota. */
2332 +int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
2333 +
2334 +/* Initialize realpath related code. */
2335 +void __init tomoyo_realpath_init(void);
2336 +int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
2337 + const struct tomoyo_path_info *filename);
2338 +int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
2339 + struct path *path, const int flag);
2340 +int tomoyo_path_perm(const u8 operation, struct path *path);
2341 +int tomoyo_path2_perm(const u8 operation, struct path *path1,
2342 + struct path *path2);
2343 +int tomoyo_check_rewrite_permission(struct file *filp);
2344 +int tomoyo_find_next_domain(struct linux_binprm *bprm);
2345 +
2346 +/* Drop refcount on tomoyo_name_union. */
2347 +void tomoyo_put_name_union(struct tomoyo_name_union *ptr);
2348 +
2349 +/* Run garbage collector. */
2350 +void tomoyo_run_gc(void);
2351 +
2352 +void tomoyo_memory_free(void *ptr);
2353 +
2354 +int tomoyo_check_file_perm(const char *filename, const u8 perm);
2355 +
2356 +/********** External variable definitions. **********/
2357 +
2358 +/* Lock for GC. */
2359 +extern struct srcu_struct tomoyo_ss;
2360 +
2361 +/* The list for "struct tomoyo_domain_info". */
2362 +extern struct list_head tomoyo_domain_list;
2363 +
2364 +extern struct list_head tomoyo_path_group_list;
2365 +extern struct list_head tomoyo_domain_initializer_list;
2366 +extern struct list_head tomoyo_domain_keeper_list;
2367 +extern struct list_head tomoyo_alias_list;
2368 +extern struct list_head tomoyo_globally_readable_list;
2369 +extern struct list_head tomoyo_pattern_list;
2370 +extern struct list_head tomoyo_no_rewrite_list;
2371 +extern struct list_head tomoyo_policy_manager_list;
2372 +extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
2373 +
2374 +/* Lock for protecting policy. */
2375 +extern struct mutex tomoyo_policy_lock;
2376 +
2377 +/* Has /sbin/init started? */
2378 +extern bool tomoyo_policy_loaded;
2379 +
2380 +/* The kernel's domain. */
2381 +extern struct tomoyo_domain_info tomoyo_kernel_domain;
2382 +
2383 +/********** Inlined functions. **********/
2384 +
2385 +static inline int tomoyo_read_lock(void)
2386 {
2387 - return a->hash != b->hash || strcmp(a->name, b->name);
2388 + return srcu_read_lock(&tomoyo_ss);
2389 }
2390
2391 -/* Get type of an ACL entry. */
2392 -static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr)
2393 +static inline void tomoyo_read_unlock(int idx)
2394 {
2395 - return ptr->type & ~TOMOYO_ACL_DELETED;
2396 + srcu_read_unlock(&tomoyo_ss, idx);
2397 }
2398
2399 -/* Get type of an ACL entry. */
2400 -static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr)
2401 +/* strcmp() for "struct tomoyo_path_info" structure. */
2402 +static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
2403 + const struct tomoyo_path_info *b)
2404 {
2405 - return ptr->type;
2406 + return a->hash != b->hash || strcmp(a->name, b->name);
2407 }
2408
2409 /**
2410 @@ -427,18 +760,84 @@ static inline bool tomoyo_is_invalid(con
2411 return c && (c <= ' ' || c >= 127);
2412 }
2413
2414 -/* The list for "struct tomoyo_domain_info". */
2415 -extern struct list_head tomoyo_domain_list;
2416 -extern struct rw_semaphore tomoyo_domain_list_lock;
2417 +static inline void tomoyo_put_name(const struct tomoyo_path_info *name)
2418 +{
2419 + if (name) {
2420 + struct tomoyo_name_entry *ptr =
2421 + container_of(name, struct tomoyo_name_entry, entry);
2422 + atomic_dec(&ptr->users);
2423 + }
2424 +}
2425
2426 -/* Lock for domain->acl_info_list. */
2427 -extern struct rw_semaphore tomoyo_domain_acl_info_list_lock;
2428 +static inline void tomoyo_put_path_group(struct tomoyo_path_group *group)
2429 +{
2430 + if (group)
2431 + atomic_dec(&group->users);
2432 +}
2433
2434 -/* Has /sbin/init started? */
2435 -extern bool tomoyo_policy_loaded;
2436 +static inline struct tomoyo_domain_info *tomoyo_domain(void)
2437 +{
2438 + return current_cred()->security;
2439 +}
2440
2441 -/* The kernel's domain. */
2442 -extern struct tomoyo_domain_info tomoyo_kernel_domain;
2443 +static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
2444 + *task)
2445 +{
2446 + return task_cred_xxx(task, security);
2447 +}
2448 +
2449 +static inline bool tomoyo_is_same_acl_head(const struct tomoyo_acl_info *p1,
2450 + const struct tomoyo_acl_info *p2)
2451 +{
2452 + return p1->type == p2->type;
2453 +}
2454 +
2455 +static inline bool tomoyo_is_same_name_union
2456 +(const struct tomoyo_name_union *p1, const struct tomoyo_name_union *p2)
2457 +{
2458 + return p1->filename == p2->filename && p1->group == p2->group &&
2459 + p1->is_group == p2->is_group;
2460 +}
2461 +
2462 +static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1,
2463 + const struct tomoyo_path_acl *p2)
2464 +{
2465 + return tomoyo_is_same_acl_head(&p1->head, &p2->head) &&
2466 + tomoyo_is_same_name_union(&p1->name, &p2->name);
2467 +}
2468 +
2469 +static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1,
2470 + const struct tomoyo_path2_acl *p2)
2471 +{
2472 + return tomoyo_is_same_acl_head(&p1->head, &p2->head) &&
2473 + tomoyo_is_same_name_union(&p1->name1, &p2->name1) &&
2474 + tomoyo_is_same_name_union(&p1->name2, &p2->name2);
2475 +}
2476 +
2477 +static inline bool tomoyo_is_same_domain_initializer_entry
2478 +(const struct tomoyo_domain_initializer_entry *p1,
2479 + const struct tomoyo_domain_initializer_entry *p2)
2480 +{
2481 + return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
2482 + && p1->domainname == p2->domainname
2483 + && p1->program == p2->program;
2484 +}
2485 +
2486 +static inline bool tomoyo_is_same_domain_keeper_entry
2487 +(const struct tomoyo_domain_keeper_entry *p1,
2488 + const struct tomoyo_domain_keeper_entry *p2)
2489 +{
2490 + return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
2491 + && p1->domainname == p2->domainname
2492 + && p1->program == p2->program;
2493 +}
2494 +
2495 +static inline bool tomoyo_is_same_alias_entry
2496 +(const struct tomoyo_alias_entry *p1, const struct tomoyo_alias_entry *p2)
2497 +{
2498 + return p1->original_name == p2->original_name &&
2499 + p1->aliased_name == p2->aliased_name;
2500 +}
2501
2502 /**
2503 * list_for_each_cookie - iterate over a list with cookie.
2504 @@ -446,16 +845,16 @@ extern struct tomoyo_domain_info tomoyo_
2505 * @cookie: the &struct list_head to use as a cookie.
2506 * @head: the head for your list.
2507 *
2508 - * Same with list_for_each() except that this primitive uses @cookie
2509 + * Same with list_for_each_rcu() except that this primitive uses @cookie
2510 * so that we can continue iteration.
2511 * @cookie must be NULL when iteration starts, and @cookie will become
2512 * NULL when iteration finishes.
2513 */
2514 -#define list_for_each_cookie(pos, cookie, head) \
2515 - for (({ if (!cookie) \
2516 - cookie = head; }), \
2517 - pos = (cookie)->next; \
2518 - prefetch(pos->next), pos != (head) || ((cookie) = NULL); \
2519 - (cookie) = pos, pos = pos->next)
2520 +#define list_for_each_cookie(pos, cookie, head) \
2521 + for (({ if (!cookie) \
2522 + cookie = head; }), \
2523 + pos = rcu_dereference((cookie)->next); \
2524 + prefetch(pos->next), pos != (head) || ((cookie) = NULL); \
2525 + (cookie) = pos, pos = rcu_dereference(pos->next))
2526
2527 #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */
2528 --- linux-2.6.32.28.orig/security/tomoyo/domain.c
2529 +++ linux-2.6.32.28/security/tomoyo/domain.c
2530 @@ -10,9 +10,8 @@
2531 */
2532
2533 #include "common.h"
2534 -#include "tomoyo.h"
2535 -#include "realpath.h"
2536 #include <linux/binfmts.h>
2537 +#include <linux/slab.h>
2538
2539 /* Variables definitions.*/
2540
2541 @@ -58,99 +57,6 @@ struct tomoyo_domain_info tomoyo_kernel_
2542 * exceptions.
2543 */
2544 LIST_HEAD(tomoyo_domain_list);
2545 -DECLARE_RWSEM(tomoyo_domain_list_lock);
2546 -
2547 -/*
2548 - * tomoyo_domain_initializer_entry is a structure which is used for holding
2549 - * "initialize_domain" and "no_initialize_domain" entries.
2550 - * It has following fields.
2551 - *
2552 - * (1) "list" which is linked to tomoyo_domain_initializer_list .
2553 - * (2) "domainname" which is "a domainname" or "the last component of a
2554 - * domainname". This field is NULL if "from" clause is not specified.
2555 - * (3) "program" which is a program's pathname.
2556 - * (4) "is_deleted" is a bool which is true if marked as deleted, false
2557 - * otherwise.
2558 - * (5) "is_not" is a bool which is true if "no_initialize_domain", false
2559 - * otherwise.
2560 - * (6) "is_last_name" is a bool which is true if "domainname" is "the last
2561 - * component of a domainname", false otherwise.
2562 - */
2563 -struct tomoyo_domain_initializer_entry {
2564 - struct list_head list;
2565 - const struct tomoyo_path_info *domainname; /* This may be NULL */
2566 - const struct tomoyo_path_info *program;
2567 - bool is_deleted;
2568 - bool is_not; /* True if this entry is "no_initialize_domain". */
2569 - /* True if the domainname is tomoyo_get_last_name(). */
2570 - bool is_last_name;
2571 -};
2572 -
2573 -/*
2574 - * tomoyo_domain_keeper_entry is a structure which is used for holding
2575 - * "keep_domain" and "no_keep_domain" entries.
2576 - * It has following fields.
2577 - *
2578 - * (1) "list" which is linked to tomoyo_domain_keeper_list .
2579 - * (2) "domainname" which is "a domainname" or "the last component of a
2580 - * domainname".
2581 - * (3) "program" which is a program's pathname.
2582 - * This field is NULL if "from" clause is not specified.
2583 - * (4) "is_deleted" is a bool which is true if marked as deleted, false
2584 - * otherwise.
2585 - * (5) "is_not" is a bool which is true if "no_initialize_domain", false
2586 - * otherwise.
2587 - * (6) "is_last_name" is a bool which is true if "domainname" is "the last
2588 - * component of a domainname", false otherwise.
2589 - */
2590 -struct tomoyo_domain_keeper_entry {
2591 - struct list_head list;
2592 - const struct tomoyo_path_info *domainname;
2593 - const struct tomoyo_path_info *program; /* This may be NULL */
2594 - bool is_deleted;
2595 - bool is_not; /* True if this entry is "no_keep_domain". */
2596 - /* True if the domainname is tomoyo_get_last_name(). */
2597 - bool is_last_name;
2598 -};
2599 -
2600 -/*
2601 - * tomoyo_alias_entry is a structure which is used for holding "alias" entries.
2602 - * It has following fields.
2603 - *
2604 - * (1) "list" which is linked to tomoyo_alias_list .
2605 - * (2) "original_name" which is a dereferenced pathname.
2606 - * (3) "aliased_name" which is a symlink's pathname.
2607 - * (4) "is_deleted" is a bool which is true if marked as deleted, false
2608 - * otherwise.
2609 - */
2610 -struct tomoyo_alias_entry {
2611 - struct list_head list;
2612 - const struct tomoyo_path_info *original_name;
2613 - const struct tomoyo_path_info *aliased_name;
2614 - bool is_deleted;
2615 -};
2616 -
2617 -/**
2618 - * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
2619 - *
2620 - * @domain: Pointer to "struct tomoyo_domain_info".
2621 - * @is_delete: True if it is a delete request.
2622 - * @flags: Flags to set or clear.
2623 - *
2624 - * Returns nothing.
2625 - */
2626 -void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
2627 - const bool is_delete, const u8 flags)
2628 -{
2629 - /* We need to serialize because this is bitfield operation. */
2630 - static DEFINE_SPINLOCK(lock);
2631 - spin_lock(&lock);
2632 - if (!is_delete)
2633 - domain->flags |= flags;
2634 - else
2635 - domain->flags &= ~flags;
2636 - spin_unlock(&lock);
2637 -}
2638
2639 /**
2640 * tomoyo_get_last_name - Get last component of a domainname.
2641 @@ -205,8 +111,7 @@ const char *tomoyo_get_last_name(const s
2642 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
2643 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
2644 */
2645 -static LIST_HEAD(tomoyo_domain_initializer_list);
2646 -static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
2647 +LIST_HEAD(tomoyo_domain_initializer_list);
2648
2649 /**
2650 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
2651 @@ -217,59 +122,55 @@ static DECLARE_RWSEM(tomoyo_domain_initi
2652 * @is_delete: True if it is a delete request.
2653 *
2654 * Returns 0 on success, negative value otherwise.
2655 + *
2656 + * Caller holds tomoyo_read_lock().
2657 */
2658 static int tomoyo_update_domain_initializer_entry(const char *domainname,
2659 const char *program,
2660 const bool is_not,
2661 const bool is_delete)
2662 {
2663 - struct tomoyo_domain_initializer_entry *new_entry;
2664 struct tomoyo_domain_initializer_entry *ptr;
2665 - const struct tomoyo_path_info *saved_program;
2666 - const struct tomoyo_path_info *saved_domainname = NULL;
2667 - int error = -ENOMEM;
2668 - bool is_last_name = false;
2669 + struct tomoyo_domain_initializer_entry e = { .is_not = is_not };
2670 + int error = is_delete ? -ENOENT : -ENOMEM;
2671
2672 - if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
2673 + if (!tomoyo_is_correct_path(program, 1, -1, -1))
2674 return -EINVAL; /* No patterns allowed. */
2675 if (domainname) {
2676 if (!tomoyo_is_domain_def(domainname) &&
2677 - tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
2678 - is_last_name = true;
2679 - else if (!tomoyo_is_correct_domain(domainname, __func__))
2680 + tomoyo_is_correct_path(domainname, 1, -1, -1))
2681 + e.is_last_name = true;
2682 + else if (!tomoyo_is_correct_domain(domainname))
2683 return -EINVAL;
2684 - saved_domainname = tomoyo_save_name(domainname);
2685 - if (!saved_domainname)
2686 - return -ENOMEM;
2687 - }
2688 - saved_program = tomoyo_save_name(program);
2689 - if (!saved_program)
2690 - return -ENOMEM;
2691 - down_write(&tomoyo_domain_initializer_list_lock);
2692 - list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
2693 - if (ptr->is_not != is_not ||
2694 - ptr->domainname != saved_domainname ||
2695 - ptr->program != saved_program)
2696 + e.domainname = tomoyo_get_name(domainname);
2697 + if (!e.domainname)
2698 + goto out;
2699 + }
2700 + e.program = tomoyo_get_name(program);
2701 + if (!e.program)
2702 + goto out;
2703 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
2704 + goto out;
2705 + list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
2706 + if (!tomoyo_is_same_domain_initializer_entry(ptr, &e))
2707 continue;
2708 ptr->is_deleted = is_delete;
2709 error = 0;
2710 - goto out;
2711 + break;
2712 }
2713 - if (is_delete) {
2714 - error = -ENOENT;
2715 - goto out;
2716 + if (!is_delete && error) {
2717 + struct tomoyo_domain_initializer_entry *entry =
2718 + tomoyo_commit_ok(&e, sizeof(e));
2719 + if (entry) {
2720 + list_add_tail_rcu(&entry->list,
2721 + &tomoyo_domain_initializer_list);
2722 + error = 0;
2723 + }
2724 }
2725 - new_entry = tomoyo_alloc_element(sizeof(*new_entry));
2726 - if (!new_entry)
2727 - goto out;
2728 - new_entry->domainname = saved_domainname;
2729 - new_entry->program = saved_program;
2730 - new_entry->is_not = is_not;
2731 - new_entry->is_last_name = is_last_name;
2732 - list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list);
2733 - error = 0;
2734 + mutex_unlock(&tomoyo_policy_lock);
2735 out:
2736 - up_write(&tomoyo_domain_initializer_list_lock);
2737 + tomoyo_put_name(e.domainname);
2738 + tomoyo_put_name(e.program);
2739 return error;
2740 }
2741
2742 @@ -279,13 +180,14 @@ static int tomoyo_update_domain_initiali
2743 * @head: Pointer to "struct tomoyo_io_buffer".
2744 *
2745 * Returns true on success, false otherwise.
2746 + *
2747 + * Caller holds tomoyo_read_lock().
2748 */
2749 bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
2750 {
2751 struct list_head *pos;
2752 bool done = true;
2753
2754 - down_read(&tomoyo_domain_initializer_list_lock);
2755 list_for_each_cookie(pos, head->read_var2,
2756 &tomoyo_domain_initializer_list) {
2757 const char *no;
2758 @@ -308,7 +210,6 @@ bool tomoyo_read_domain_initializer_poli
2759 if (!done)
2760 break;
2761 }
2762 - up_read(&tomoyo_domain_initializer_list_lock);
2763 return done;
2764 }
2765
2766 @@ -320,6 +221,8 @@ bool tomoyo_read_domain_initializer_poli
2767 * @is_delete: True if it is a delete request.
2768 *
2769 * Returns 0 on success, negative value otherwise.
2770 + *
2771 + * Caller holds tomoyo_read_lock().
2772 */
2773 int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
2774 const bool is_delete)
2775 @@ -345,6 +248,8 @@ int tomoyo_write_domain_initializer_poli
2776 *
2777 * Returns true if executing @program reinitializes domain transition,
2778 * false otherwise.
2779 + *
2780 + * Caller holds tomoyo_read_lock().
2781 */
2782 static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
2783 domainname,
2784 @@ -355,8 +260,7 @@ static bool tomoyo_is_domain_initializer
2785 struct tomoyo_domain_initializer_entry *ptr;
2786 bool flag = false;
2787
2788 - down_read(&tomoyo_domain_initializer_list_lock);
2789 - list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
2790 + list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
2791 if (ptr->is_deleted)
2792 continue;
2793 if (ptr->domainname) {
2794 @@ -376,7 +280,6 @@ static bool tomoyo_is_domain_initializer
2795 }
2796 flag = true;
2797 }
2798 - up_read(&tomoyo_domain_initializer_list_lock);
2799 return flag;
2800 }
2801
2802 @@ -418,8 +321,7 @@ static bool tomoyo_is_domain_initializer
2803 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
2804 * explicitly specified by "initialize_domain".
2805 */
2806 -static LIST_HEAD(tomoyo_domain_keeper_list);
2807 -static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
2808 +LIST_HEAD(tomoyo_domain_keeper_list);
2809
2810 /**
2811 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
2812 @@ -430,59 +332,55 @@ static DECLARE_RWSEM(tomoyo_domain_keepe
2813 * @is_delete: True if it is a delete request.
2814 *
2815 * Returns 0 on success, negative value otherwise.
2816 + *
2817 + * Caller holds tomoyo_read_lock().
2818 */
2819 static int tomoyo_update_domain_keeper_entry(const char *domainname,
2820 const char *program,
2821 const bool is_not,
2822 const bool is_delete)
2823 {
2824 - struct tomoyo_domain_keeper_entry *new_entry;
2825 struct tomoyo_domain_keeper_entry *ptr;
2826 - const struct tomoyo_path_info *saved_domainname;
2827 - const struct tomoyo_path_info *saved_program = NULL;
2828 - int error = -ENOMEM;
2829 - bool is_last_name = false;
2830 + struct tomoyo_domain_keeper_entry e = { .is_not = is_not };
2831 + int error = is_delete ? -ENOENT : -ENOMEM;
2832
2833 if (!tomoyo_is_domain_def(domainname) &&
2834 - tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
2835 - is_last_name = true;
2836 - else if (!tomoyo_is_correct_domain(domainname, __func__))
2837 + tomoyo_is_correct_path(domainname, 1, -1, -1))
2838 + e.is_last_name = true;
2839 + else if (!tomoyo_is_correct_domain(domainname))
2840 return -EINVAL;
2841 if (program) {
2842 - if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
2843 + if (!tomoyo_is_correct_path(program, 1, -1, -1))
2844 return -EINVAL;
2845 - saved_program = tomoyo_save_name(program);
2846 - if (!saved_program)
2847 - return -ENOMEM;
2848 + e.program = tomoyo_get_name(program);
2849 + if (!e.program)
2850 + goto out;
2851 }
2852 - saved_domainname = tomoyo_save_name(domainname);
2853 - if (!saved_domainname)
2854 - return -ENOMEM;
2855 - down_write(&tomoyo_domain_keeper_list_lock);
2856 - list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
2857 - if (ptr->is_not != is_not ||
2858 - ptr->domainname != saved_domainname ||
2859 - ptr->program != saved_program)
2860 + e.domainname = tomoyo_get_name(domainname);
2861 + if (!e.domainname)
2862 + goto out;
2863 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
2864 + goto out;
2865 + list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
2866 + if (!tomoyo_is_same_domain_keeper_entry(ptr, &e))
2867 continue;
2868 ptr->is_deleted = is_delete;
2869 error = 0;
2870 - goto out;
2871 + break;
2872 }
2873 - if (is_delete) {
2874 - error = -ENOENT;
2875 - goto out;
2876 + if (!is_delete && error) {
2877 + struct tomoyo_domain_keeper_entry *entry =
2878 + tomoyo_commit_ok(&e, sizeof(e));
2879 + if (entry) {
2880 + list_add_tail_rcu(&entry->list,
2881 + &tomoyo_domain_keeper_list);
2882 + error = 0;
2883 + }
2884 }
2885 - new_entry = tomoyo_alloc_element(sizeof(*new_entry));
2886 - if (!new_entry)
2887 - goto out;
2888 - new_entry->domainname = saved_domainname;
2889 - new_entry->program = saved_program;
2890 - new_entry->is_not = is_not;
2891 - new_entry->is_last_name = is_last_name;
2892 - list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list);
2893 - error = 0;
2894 + mutex_unlock(&tomoyo_policy_lock);
2895 out:
2896 - up_write(&tomoyo_domain_keeper_list_lock);
2897 + tomoyo_put_name(e.domainname);
2898 + tomoyo_put_name(e.program);
2899 return error;
2900 }
2901
2902 @@ -493,6 +391,7 @@ static int tomoyo_update_domain_keeper_e
2903 * @is_not: True if it is "no_keep_domain" entry.
2904 * @is_delete: True if it is a delete request.
2905 *
2906 + * Caller holds tomoyo_read_lock().
2907 */
2908 int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
2909 const bool is_delete)
2910 @@ -513,13 +412,14 @@ int tomoyo_write_domain_keeper_policy(ch
2911 * @head: Pointer to "struct tomoyo_io_buffer".
2912 *
2913 * Returns true on success, false otherwise.
2914 + *
2915 + * Caller holds tomoyo_read_lock().
2916 */
2917 bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
2918 {
2919 struct list_head *pos;
2920 bool done = true;
2921
2922 - down_read(&tomoyo_domain_keeper_list_lock);
2923 list_for_each_cookie(pos, head->read_var2,
2924 &tomoyo_domain_keeper_list) {
2925 struct tomoyo_domain_keeper_entry *ptr;
2926 @@ -542,7 +442,6 @@ bool tomoyo_read_domain_keeper_policy(st
2927 if (!done)
2928 break;
2929 }
2930 - up_read(&tomoyo_domain_keeper_list_lock);
2931 return done;
2932 }
2933
2934 @@ -555,6 +454,8 @@ bool tomoyo_read_domain_keeper_policy(st
2935 *
2936 * Returns true if executing @program supresses domain transition,
2937 * false otherwise.
2938 + *
2939 + * Caller holds tomoyo_read_lock().
2940 */
2941 static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
2942 const struct tomoyo_path_info *program,
2943 @@ -563,8 +464,7 @@ static bool tomoyo_is_domain_keeper(cons
2944 struct tomoyo_domain_keeper_entry *ptr;
2945 bool flag = false;
2946
2947 - down_read(&tomoyo_domain_keeper_list_lock);
2948 - list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
2949 + list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
2950 if (ptr->is_deleted)
2951 continue;
2952 if (!ptr->is_last_name) {
2953 @@ -582,7 +482,6 @@ static bool tomoyo_is_domain_keeper(cons
2954 }
2955 flag = true;
2956 }
2957 - up_read(&tomoyo_domain_keeper_list_lock);
2958 return flag;
2959 }
2960
2961 @@ -616,8 +515,7 @@ static bool tomoyo_is_domain_keeper(cons
2962 * /bin/busybox and domainname which the current process will belong to after
2963 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
2964 */
2965 -static LIST_HEAD(tomoyo_alias_list);
2966 -static DECLARE_RWSEM(tomoyo_alias_list_lock);
2967 +LIST_HEAD(tomoyo_alias_list);
2968
2969 /**
2970 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
2971 @@ -627,46 +525,45 @@ static DECLARE_RWSEM(tomoyo_alias_list_l
2972 * @is_delete: True if it is a delete request.
2973 *
2974 * Returns 0 on success, negative value otherwise.
2975 + *
2976 + * Caller holds tomoyo_read_lock().
2977 */
2978 static int tomoyo_update_alias_entry(const char *original_name,
2979 const char *aliased_name,
2980 const bool is_delete)
2981 {
2982 - struct tomoyo_alias_entry *new_entry;
2983 struct tomoyo_alias_entry *ptr;
2984 - const struct tomoyo_path_info *saved_original_name;
2985 - const struct tomoyo_path_info *saved_aliased_name;
2986 - int error = -ENOMEM;
2987 + struct tomoyo_alias_entry e = { };
2988 + int error = is_delete ? -ENOENT : -ENOMEM;
2989
2990 - if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) ||
2991 - !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__))
2992 + if (!tomoyo_is_correct_path(original_name, 1, -1, -1) ||
2993 + !tomoyo_is_correct_path(aliased_name, 1, -1, -1))
2994 return -EINVAL; /* No patterns allowed. */
2995 - saved_original_name = tomoyo_save_name(original_name);
2996 - saved_aliased_name = tomoyo_save_name(aliased_name);
2997 - if (!saved_original_name || !saved_aliased_name)
2998 - return -ENOMEM;
2999 - down_write(&tomoyo_alias_list_lock);
3000 - list_for_each_entry(ptr, &tomoyo_alias_list, list) {
3001 - if (ptr->original_name != saved_original_name ||
3002 - ptr->aliased_name != saved_aliased_name)
3003 + e.original_name = tomoyo_get_name(original_name);
3004 + e.aliased_name = tomoyo_get_name(aliased_name);
3005 + if (!e.original_name || !e.aliased_name)
3006 + goto out;
3007 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
3008 + goto out;
3009 + list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
3010 + if (!tomoyo_is_same_alias_entry(ptr, &e))
3011 continue;
3012 ptr->is_deleted = is_delete;
3013 error = 0;
3014 - goto out;
3015 + break;
3016 }
3017 - if (is_delete) {
3018 - error = -ENOENT;
3019 - goto out;
3020 + if (!is_delete && error) {
3021 + struct tomoyo_alias_entry *entry =
3022 + tomoyo_commit_ok(&e, sizeof(e));
3023 + if (entry) {
3024 + list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
3025 + error = 0;
3026 + }
3027 }
3028 - new_entry = tomoyo_alloc_element(sizeof(*new_entry));
3029 - if (!new_entry)
3030 - goto out;
3031 - new_entry->original_name = saved_original_name;
3032 - new_entry->aliased_name = saved_aliased_name;
3033 - list_add_tail(&new_entry->list, &tomoyo_alias_list);
3034 - error = 0;
3035 + mutex_unlock(&tomoyo_policy_lock);
3036 out:
3037 - up_write(&tomoyo_alias_list_lock);
3038 + tomoyo_put_name(e.original_name);
3039 + tomoyo_put_name(e.aliased_name);
3040 return error;
3041 }
3042
3043 @@ -676,13 +573,14 @@ static int tomoyo_update_alias_entry(con
3044 * @head: Pointer to "struct tomoyo_io_buffer".
3045 *
3046 * Returns true on success, false otherwise.
3047 + *
3048 + * Caller holds tomoyo_read_lock().
3049 */
3050 bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
3051 {
3052 struct list_head *pos;
3053 bool done = true;
3054
3055 - down_read(&tomoyo_alias_list_lock);
3056 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
3057 struct tomoyo_alias_entry *ptr;
3058
3059 @@ -695,7 +593,6 @@ bool tomoyo_read_alias_policy(struct tom
3060 if (!done)
3061 break;
3062 }
3063 - up_read(&tomoyo_alias_list_lock);
3064 return done;
3065 }
3066
3067 @@ -706,6 +603,8 @@ bool tomoyo_read_alias_policy(struct tom
3068 * @is_delete: True if it is a delete request.
3069 *
3070 * Returns 0 on success, negative value otherwise.
3071 + *
3072 + * Caller holds tomoyo_read_lock().
3073 */
3074 int tomoyo_write_alias_policy(char *data, const bool is_delete)
3075 {
3076 @@ -724,63 +623,48 @@ int tomoyo_write_alias_policy(char *data
3077 * @profile: Profile number to assign if the domain was newly created.
3078 *
3079 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
3080 + *
3081 + * Caller holds tomoyo_read_lock().
3082 */
3083 struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
3084 domainname,
3085 const u8 profile)
3086 {
3087 + struct tomoyo_domain_info *entry;
3088 struct tomoyo_domain_info *domain = NULL;
3089 const struct tomoyo_path_info *saved_domainname;
3090 + bool found = false;
3091
3092 - down_write(&tomoyo_domain_list_lock);
3093 - domain = tomoyo_find_domain(domainname);
3094 - if (domain)
3095 - goto out;
3096 - if (!tomoyo_is_correct_domain(domainname, __func__))
3097 - goto out;
3098 - saved_domainname = tomoyo_save_name(domainname);
3099 + if (!tomoyo_is_correct_domain(domainname))
3100 + return NULL;
3101 + saved_domainname = tomoyo_get_name(domainname);
3102 if (!saved_domainname)
3103 - goto out;
3104 - /* Can I reuse memory of deleted domain? */
3105 - list_for_each_entry(domain, &tomoyo_domain_list, list) {
3106 - struct task_struct *p;
3107 - struct tomoyo_acl_info *ptr;
3108 - bool flag;
3109 - if (!domain->is_deleted ||
3110 - domain->domainname != saved_domainname)
3111 - continue;
3112 - flag = false;
3113 - read_lock(&tasklist_lock);
3114 - for_each_process(p) {
3115 - if (tomoyo_real_domain(p) != domain)
3116 - continue;
3117 - flag = true;
3118 - break;
3119 - }
3120 - read_unlock(&tasklist_lock);
3121 - if (flag)
3122 - continue;
3123 - list_for_each_entry(ptr, &domain->acl_info_list, list) {
3124 - ptr->type |= TOMOYO_ACL_DELETED;
3125 - }
3126 - tomoyo_set_domain_flag(domain, true, domain->flags);
3127 - domain->profile = profile;
3128 - domain->quota_warned = false;
3129 - mb(); /* Avoid out-of-order execution. */
3130 - domain->is_deleted = false;
3131 - goto out;
3132 - }
3133 - /* No memory reusable. Create using new memory. */
3134 - domain = tomoyo_alloc_element(sizeof(*domain));
3135 - if (domain) {
3136 - INIT_LIST_HEAD(&domain->acl_info_list);
3137 - domain->domainname = saved_domainname;
3138 - domain->profile = profile;
3139 - list_add_tail(&domain->list, &tomoyo_domain_list);
3140 + return NULL;
3141 + entry = kzalloc(sizeof(*entry), GFP_NOFS);
3142 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
3143 + goto out;
3144 + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
3145 + if (domain->is_deleted ||
3146 + tomoyo_pathcmp(saved_domainname, domain->domainname))
3147 + continue;
3148 + found = true;
3149 + break;
3150 + }
3151 + if (!found && tomoyo_memory_ok(entry)) {
3152 + INIT_LIST_HEAD(&entry->acl_info_list);
3153 + entry->domainname = saved_domainname;
3154 + saved_domainname = NULL;
3155 + entry->profile = profile;
3156 + list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
3157 + domain = entry;
3158 + entry = NULL;
3159 + found = true;
3160 }
3161 + mutex_unlock(&tomoyo_policy_lock);
3162 out:
3163 - up_write(&tomoyo_domain_list_lock);
3164 - return domain;
3165 + tomoyo_put_name(saved_domainname);
3166 + kfree(entry);
3167 + return found ? domain : NULL;
3168 }
3169
3170 /**
3171 @@ -789,6 +673,8 @@ struct tomoyo_domain_info *tomoyo_find_o
3172 * @bprm: Pointer to "struct linux_binprm".
3173 *
3174 * Returns 0 on success, negative value otherwise.
3175 + *
3176 + * Caller holds tomoyo_read_lock().
3177 */
3178 int tomoyo_find_next_domain(struct linux_binprm *bprm)
3179 {
3180 @@ -796,7 +682,7 @@ int tomoyo_find_next_domain(struct linux
3181 * This function assumes that the size of buffer returned by
3182 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
3183 */
3184 - struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp));
3185 + struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_NOFS);
3186 struct tomoyo_domain_info *old_domain = tomoyo_domain();
3187 struct tomoyo_domain_info *domain = NULL;
3188 const char *old_domain_name = old_domain->domainname->name;
3189 @@ -849,8 +735,7 @@ int tomoyo_find_next_domain(struct linux
3190 if (tomoyo_pathcmp(&r, &s)) {
3191 struct tomoyo_alias_entry *ptr;
3192 /* Is this program allowed to be called via symbolic links? */
3193 - down_read(&tomoyo_alias_list_lock);
3194 - list_for_each_entry(ptr, &tomoyo_alias_list, list) {
3195 + list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
3196 if (ptr->is_deleted ||
3197 tomoyo_pathcmp(&r, ptr->original_name) ||
3198 tomoyo_pathcmp(&s, ptr->aliased_name))
3199 @@ -861,7 +746,6 @@ int tomoyo_find_next_domain(struct linux
3200 tomoyo_fill_path_info(&r);
3201 break;
3202 }
3203 - up_read(&tomoyo_alias_list_lock);
3204 }
3205
3206 /* Check execute permission. */
3207 @@ -892,9 +776,7 @@ int tomoyo_find_next_domain(struct linux
3208 }
3209 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
3210 goto done;
3211 - down_read(&tomoyo_domain_list_lock);
3212 domain = tomoyo_find_domain(new_domain_name);
3213 - up_read(&tomoyo_domain_list_lock);
3214 if (domain)
3215 goto done;
3216 if (is_enforce)
3217 @@ -909,14 +791,15 @@ int tomoyo_find_next_domain(struct linux
3218 if (is_enforce)
3219 retval = -EPERM;
3220 else
3221 - tomoyo_set_domain_flag(old_domain, false,
3222 - TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
3223 + old_domain->transition_failed = true;
3224 out:
3225 if (!domain)
3226 domain = old_domain;
3227 + /* Update reference count on "struct tomoyo_domain_info". */
3228 + atomic_inc(&domain->users);
3229 bprm->cred->security = domain;
3230 - tomoyo_free(real_program_name);
3231 - tomoyo_free(symlink_program_name);
3232 - tomoyo_free(tmp);
3233 + kfree(real_program_name);
3234 + kfree(symlink_program_name);
3235 + kfree(tmp);
3236 return retval;
3237 }
3238 --- linux-2.6.32.28.orig/security/tomoyo/file.c
3239 +++ linux-2.6.32.28/security/tomoyo/file.c
3240 @@ -10,109 +10,97 @@
3241 */
3242
3243 #include "common.h"
3244 -#include "tomoyo.h"
3245 -#include "realpath.h"
3246 +#include <linux/slab.h>
3247 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
3248
3249 -/*
3250 - * tomoyo_globally_readable_file_entry is a structure which is used for holding
3251 - * "allow_read" entries.
3252 - * It has following fields.
3253 - *
3254 - * (1) "list" which is linked to tomoyo_globally_readable_list .
3255 - * (2) "filename" is a pathname which is allowed to open(O_RDONLY).
3256 - * (3) "is_deleted" is a bool which is true if marked as deleted, false
3257 - * otherwise.
3258 - */
3259 -struct tomoyo_globally_readable_file_entry {
3260 - struct list_head list;
3261 - const struct tomoyo_path_info *filename;
3262 - bool is_deleted;
3263 +/* Keyword array for single path operations. */
3264 +static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = {
3265 + [TOMOYO_TYPE_READ_WRITE] = "read/write",
3266 + [TOMOYO_TYPE_EXECUTE] = "execute",
3267 + [TOMOYO_TYPE_READ] = "read",
3268 + [TOMOYO_TYPE_WRITE] = "write",
3269 + [TOMOYO_TYPE_CREATE] = "create",
3270 + [TOMOYO_TYPE_UNLINK] = "unlink",
3271 + [TOMOYO_TYPE_MKDIR] = "mkdir",
3272 + [TOMOYO_TYPE_RMDIR] = "rmdir",
3273 + [TOMOYO_TYPE_MKFIFO] = "mkfifo",
3274 + [TOMOYO_TYPE_MKSOCK] = "mksock",
3275 + [TOMOYO_TYPE_MKBLOCK] = "mkblock",
3276 + [TOMOYO_TYPE_MKCHAR] = "mkchar",
3277 + [TOMOYO_TYPE_TRUNCATE] = "truncate",
3278 + [TOMOYO_TYPE_SYMLINK] = "symlink",
3279 + [TOMOYO_TYPE_REWRITE] = "rewrite",
3280 + [TOMOYO_TYPE_IOCTL] = "ioctl",
3281 + [TOMOYO_TYPE_CHMOD] = "chmod",
3282 + [TOMOYO_TYPE_CHOWN] = "chown",
3283 + [TOMOYO_TYPE_CHGRP] = "chgrp",
3284 + [TOMOYO_TYPE_CHROOT] = "chroot",
3285 + [TOMOYO_TYPE_MOUNT] = "mount",
3286 + [TOMOYO_TYPE_UMOUNT] = "unmount",
3287 };
3288
3289 -/*
3290 - * tomoyo_pattern_entry is a structure which is used for holding
3291 - * "tomoyo_pattern_list" entries.
3292 - * It has following fields.
3293 - *
3294 - * (1) "list" which is linked to tomoyo_pattern_list .
3295 - * (2) "pattern" is a pathname pattern which is used for converting pathnames
3296 - * to pathname patterns during learning mode.
3297 - * (3) "is_deleted" is a bool which is true if marked as deleted, false
3298 - * otherwise.
3299 - */
3300 -struct tomoyo_pattern_entry {
3301 - struct list_head list;
3302 - const struct tomoyo_path_info *pattern;
3303 - bool is_deleted;
3304 +/* Keyword array for double path operations. */
3305 +static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = {
3306 + [TOMOYO_TYPE_LINK] = "link",
3307 + [TOMOYO_TYPE_RENAME] = "rename",
3308 + [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root",
3309 };
3310
3311 -/*
3312 - * tomoyo_no_rewrite_entry is a structure which is used for holding
3313 - * "deny_rewrite" entries.
3314 - * It has following fields.
3315 - *
3316 - * (1) "list" which is linked to tomoyo_no_rewrite_list .
3317 - * (2) "pattern" is a pathname which is by default not permitted to modify
3318 - * already existing content.
3319 - * (3) "is_deleted" is a bool which is true if marked as deleted, false
3320 - * otherwise.
3321 - */
3322 -struct tomoyo_no_rewrite_entry {
3323 - struct list_head list;
3324 - const struct tomoyo_path_info *pattern;
3325 - bool is_deleted;
3326 -};
3327 +void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
3328 +{
3329 + if (!ptr)
3330 + return;
3331 + if (ptr->is_group)
3332 + tomoyo_put_path_group(ptr->group);
3333 + else
3334 + tomoyo_put_name(ptr->filename);
3335 +}
3336
3337 -/* Keyword array for single path operations. */
3338 -static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
3339 - [TOMOYO_TYPE_READ_WRITE_ACL] = "read/write",
3340 - [TOMOYO_TYPE_EXECUTE_ACL] = "execute",
3341 - [TOMOYO_TYPE_READ_ACL] = "read",
3342 - [TOMOYO_TYPE_WRITE_ACL] = "write",
3343 - [TOMOYO_TYPE_CREATE_ACL] = "create",
3344 - [TOMOYO_TYPE_UNLINK_ACL] = "unlink",
3345 - [TOMOYO_TYPE_MKDIR_ACL] = "mkdir",
3346 - [TOMOYO_TYPE_RMDIR_ACL] = "rmdir",
3347 - [TOMOYO_TYPE_MKFIFO_ACL] = "mkfifo",
3348 - [TOMOYO_TYPE_MKSOCK_ACL] = "mksock",
3349 - [TOMOYO_TYPE_MKBLOCK_ACL] = "mkblock",
3350 - [TOMOYO_TYPE_MKCHAR_ACL] = "mkchar",
3351 - [TOMOYO_TYPE_TRUNCATE_ACL] = "truncate",
3352 - [TOMOYO_TYPE_SYMLINK_ACL] = "symlink",
3353 - [TOMOYO_TYPE_REWRITE_ACL] = "rewrite",
3354 -};
3355 +bool tomoyo_compare_name_union(const struct tomoyo_path_info *name,
3356 + const struct tomoyo_name_union *ptr)
3357 +{
3358 + if (ptr->is_group)
3359 + return tomoyo_path_matches_group(name, ptr->group, 1);
3360 + return tomoyo_path_matches_pattern(name, ptr->filename);
3361 +}
3362
3363 -/* Keyword array for double path operations. */
3364 -static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
3365 - [TOMOYO_TYPE_LINK_ACL] = "link",
3366 - [TOMOYO_TYPE_RENAME_ACL] = "rename",
3367 -};
3368 +static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info
3369 + *name,
3370 + const struct tomoyo_name_union
3371 + *ptr, const bool may_use_pattern)
3372 +{
3373 + if (ptr->is_group)
3374 + return tomoyo_path_matches_group(name, ptr->group,
3375 + may_use_pattern);
3376 + if (may_use_pattern || !ptr->filename->is_patterned)
3377 + return tomoyo_path_matches_pattern(name, ptr->filename);
3378 + return false;
3379 +}
3380
3381 /**
3382 - * tomoyo_sp2keyword - Get the name of single path operation.
3383 + * tomoyo_path2keyword - Get the name of single path operation.
3384 *
3385 * @operation: Type of operation.
3386 *
3387 * Returns the name of single path operation.
3388 */
3389 -const char *tomoyo_sp2keyword(const u8 operation)
3390 +const char *tomoyo_path2keyword(const u8 operation)
3391 {
3392 - return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION)
3393 - ? tomoyo_sp_keyword[operation] : NULL;
3394 + return (operation < TOMOYO_MAX_PATH_OPERATION)
3395 + ? tomoyo_path_keyword[operation] : NULL;
3396 }
3397
3398 /**
3399 - * tomoyo_dp2keyword - Get the name of double path operation.
3400 + * tomoyo_path22keyword - Get the name of double path operation.
3401 *
3402 * @operation: Type of operation.
3403 *
3404 * Returns the name of double path operation.
3405 */
3406 -const char *tomoyo_dp2keyword(const u8 operation)
3407 +const char *tomoyo_path22keyword(const u8 operation)
3408 {
3409 - return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION)
3410 - ? tomoyo_dp_keyword[operation] : NULL;
3411 + return (operation < TOMOYO_MAX_PATH2_OPERATION)
3412 + ? tomoyo_path2_keyword[operation] : NULL;
3413 }
3414
3415 /**
3416 @@ -143,7 +131,8 @@ static bool tomoyo_strendswith(const cha
3417 static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
3418 {
3419 int error;
3420 - struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf));
3421 + struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf),
3422 + GFP_NOFS);
3423
3424 if (!buf)
3425 return NULL;
3426 @@ -155,20 +144,17 @@ static struct tomoyo_path_info *tomoyo_g
3427 tomoyo_fill_path_info(&buf->head);
3428 return &buf->head;
3429 }
3430 - tomoyo_free(buf);
3431 + kfree(buf);
3432 return NULL;
3433 }
3434
3435 -/* Lock for domain->acl_info_list. */
3436 -DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
3437 -
3438 -static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
3439 - const char *filename2,
3440 - struct tomoyo_domain_info *
3441 - const domain, const bool is_delete);
3442 -static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
3443 - struct tomoyo_domain_info *
3444 - const domain, const bool is_delete);
3445 +static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
3446 + const char *filename2,
3447 + struct tomoyo_domain_info *const domain,
3448 + const bool is_delete);
3449 +static int tomoyo_update_path_acl(const u8 type, const char *filename,
3450 + struct tomoyo_domain_info *const domain,
3451 + const bool is_delete);
3452
3453 /*
3454 * tomoyo_globally_readable_list is used for holding list of pathnames which
3455 @@ -195,8 +181,7 @@ static int tomoyo_update_single_path_acl
3456 * given "allow_read /lib/libc-2.5.so" to the domain which current process
3457 * belongs to.
3458 */
3459 -static LIST_HEAD(tomoyo_globally_readable_list);
3460 -static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
3461 +LIST_HEAD(tomoyo_globally_readable_list);
3462
3463 /**
3464 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
3465 @@ -205,40 +190,42 @@ static DECLARE_RWSEM(tomoyo_globally_rea
3466 * @is_delete: True if it is a delete request.
3467 *
3468 * Returns 0 on success, negative value otherwise.
3469 + *
3470 + * Caller holds tomoyo_read_lock().
3471 */
3472 static int tomoyo_update_globally_readable_entry(const char *filename,
3473 const bool is_delete)
3474 {
3475 - struct tomoyo_globally_readable_file_entry *new_entry;
3476 struct tomoyo_globally_readable_file_entry *ptr;
3477 - const struct tomoyo_path_info *saved_filename;
3478 - int error = -ENOMEM;
3479 + struct tomoyo_globally_readable_file_entry e = { };
3480 + int error = is_delete ? -ENOENT : -ENOMEM;
3481
3482 - if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
3483 + if (!tomoyo_is_correct_path(filename, 1, 0, -1))
3484 return -EINVAL;
3485 - saved_filename = tomoyo_save_name(filename);
3486 - if (!saved_filename)
3487 + e.filename = tomoyo_get_name(filename);
3488 + if (!e.filename)
3489 return -ENOMEM;
3490 - down_write(&tomoyo_globally_readable_list_lock);
3491 - list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
3492 - if (ptr->filename != saved_filename)
3493 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
3494 + goto out;
3495 + list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
3496 + if (ptr->filename != e.filename)
3497 continue;
3498 ptr->is_deleted = is_delete;
3499 error = 0;
3500 - goto out;
3501 + break;
3502 }
3503 - if (is_delete) {
3504 - error = -ENOENT;
3505 - goto out;
3506 + if (!is_delete && error) {
3507 + struct tomoyo_globally_readable_file_entry *entry =
3508 + tomoyo_commit_ok(&e, sizeof(e));
3509 + if (entry) {
3510 + list_add_tail_rcu(&entry->list,
3511 + &tomoyo_globally_readable_list);
3512 + error = 0;
3513 + }
3514 }
3515 - new_entry = tomoyo_alloc_element(sizeof(*new_entry));
3516 - if (!new_entry)
3517 - goto out;
3518 - new_entry->filename = saved_filename;
3519 - list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
3520 - error = 0;
3521 + mutex_unlock(&tomoyo_policy_lock);
3522 out:
3523 - up_write(&tomoyo_globally_readable_list_lock);
3524 + tomoyo_put_name(e.filename);
3525 return error;
3526 }
3527
3528 @@ -248,21 +235,22 @@ static int tomoyo_update_globally_readab
3529 * @filename: The filename to check.
3530 *
3531 * Returns true if any domain can open @filename for reading, false otherwise.
3532 + *
3533 + * Caller holds tomoyo_read_lock().
3534 */
3535 static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
3536 filename)
3537 {
3538 struct tomoyo_globally_readable_file_entry *ptr;
3539 bool found = false;
3540 - down_read(&tomoyo_globally_readable_list_lock);
3541 - list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
3542 +
3543 + list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
3544 if (!ptr->is_deleted &&
3545 tomoyo_path_matches_pattern(filename, ptr->filename)) {
3546 found = true;
3547 break;
3548 }
3549 }
3550 - up_read(&tomoyo_globally_readable_list_lock);
3551 return found;
3552 }
3553
3554 @@ -273,6 +261,8 @@ static bool tomoyo_is_globally_readable_
3555 * @is_delete: True if it is a delete request.
3556 *
3557 * Returns 0 on success, negative value otherwise.
3558 + *
3559 + * Caller holds tomoyo_read_lock().
3560 */
3561 int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
3562 {
3563 @@ -285,13 +275,14 @@ int tomoyo_write_globally_readable_polic
3564 * @head: Pointer to "struct tomoyo_io_buffer".
3565 *
3566 * Returns true on success, false otherwise.
3567 + *
3568 + * Caller holds tomoyo_read_lock().
3569 */
3570 bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
3571 {
3572 struct list_head *pos;
3573 bool done = true;
3574
3575 - down_read(&tomoyo_globally_readable_list_lock);
3576 list_for_each_cookie(pos, head->read_var2,
3577 &tomoyo_globally_readable_list) {
3578 struct tomoyo_globally_readable_file_entry *ptr;
3579 @@ -305,7 +296,6 @@ bool tomoyo_read_globally_readable_polic
3580 if (!done)
3581 break;
3582 }
3583 - up_read(&tomoyo_globally_readable_list_lock);
3584 return done;
3585 }
3586
3587 @@ -338,8 +328,7 @@ bool tomoyo_read_globally_readable_polic
3588 * which pretends as if /proc/self/ is not a symlink; so that we can forbid
3589 * current process from accessing other process's information.
3590 */
3591 -static LIST_HEAD(tomoyo_pattern_list);
3592 -static DECLARE_RWSEM(tomoyo_pattern_list_lock);
3593 +LIST_HEAD(tomoyo_pattern_list);
3594
3595 /**
3596 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
3597 @@ -348,40 +337,40 @@ static DECLARE_RWSEM(tomoyo_pattern_list
3598 * @is_delete: True if it is a delete request.
3599 *
3600 * Returns 0 on success, negative value otherwise.
3601 + *
3602 + * Caller holds tomoyo_read_lock().
3603 */
3604 static int tomoyo_update_file_pattern_entry(const char *pattern,
3605 const bool is_delete)
3606 {
3607 - struct tomoyo_pattern_entry *new_entry;
3608 struct tomoyo_pattern_entry *ptr;
3609 - const struct tomoyo_path_info *saved_pattern;
3610 - int error = -ENOMEM;
3611 + struct tomoyo_pattern_entry e = { .pattern = tomoyo_get_name(pattern) };
3612 + int error = is_delete ? -ENOENT : -ENOMEM;
3613
3614 - if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
3615 - return -EINVAL;
3616 - saved_pattern = tomoyo_save_name(pattern);
3617 - if (!saved_pattern)
3618 - return -ENOMEM;
3619 - down_write(&tomoyo_pattern_list_lock);
3620 - list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
3621 - if (saved_pattern != ptr->pattern)
3622 + if (!e.pattern)
3623 + return error;
3624 + if (!e.pattern->is_patterned)
3625 + goto out;
3626 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
3627 + goto out;
3628 + list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
3629 + if (e.pattern != ptr->pattern)
3630 continue;
3631 ptr->is_deleted = is_delete;
3632 error = 0;
3633 - goto out;
3634 + break;
3635 }
3636 - if (is_delete) {
3637 - error = -ENOENT;
3638 - goto out;
3639 + if (!is_delete && error) {
3640 + struct tomoyo_pattern_entry *entry =
3641 + tomoyo_commit_ok(&e, sizeof(e));
3642 + if (entry) {
3643 + list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
3644 + error = 0;
3645 + }
3646 }
3647 - new_entry = tomoyo_alloc_element(sizeof(*new_entry));
3648 - if (!new_entry)
3649 - goto out;
3650 - new_entry->pattern = saved_pattern;
3651 - list_add_tail(&new_entry->list, &tomoyo_pattern_list);
3652 - error = 0;
3653 + mutex_unlock(&tomoyo_policy_lock);
3654 out:
3655 - up_write(&tomoyo_pattern_list_lock);
3656 + tomoyo_put_name(e.pattern);
3657 return error;
3658 }
3659
3660 @@ -391,6 +380,8 @@ static int tomoyo_update_file_pattern_en
3661 * @filename: The filename to find patterned pathname.
3662 *
3663 * Returns pointer to pathname pattern if matched, @filename otherwise.
3664 + *
3665 + * Caller holds tomoyo_read_lock().
3666 */
3667 static const struct tomoyo_path_info *
3668 tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
3669 @@ -398,8 +389,7 @@ tomoyo_get_file_pattern(const struct tom
3670 struct tomoyo_pattern_entry *ptr;
3671 const struct tomoyo_path_info *pattern = NULL;
3672
3673 - down_read(&tomoyo_pattern_list_lock);
3674 - list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
3675 + list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
3676 if (ptr->is_deleted)
3677 continue;
3678 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
3679 @@ -412,7 +402,6 @@ tomoyo_get_file_pattern(const struct tom
3680 break;
3681 }
3682 }
3683 - up_read(&tomoyo_pattern_list_lock);
3684 if (pattern)
3685 filename = pattern;
3686 return filename;
3687 @@ -425,6 +414,8 @@ tomoyo_get_file_pattern(const struct tom
3688 * @is_delete: True if it is a delete request.
3689 *
3690 * Returns 0 on success, negative value otherwise.
3691 + *
3692 + * Caller holds tomoyo_read_lock().
3693 */
3694 int tomoyo_write_pattern_policy(char *data, const bool is_delete)
3695 {
3696 @@ -437,13 +428,14 @@ int tomoyo_write_pattern_policy(char *da
3697 * @head: Pointer to "struct tomoyo_io_buffer".
3698 *
3699 * Returns true on success, false otherwise.
3700 + *
3701 + * Caller holds tomoyo_read_lock().
3702 */
3703 bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
3704 {
3705 struct list_head *pos;
3706 bool done = true;
3707
3708 - down_read(&tomoyo_pattern_list_lock);
3709 list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
3710 struct tomoyo_pattern_entry *ptr;
3711 ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
3712 @@ -454,7 +446,6 @@ bool tomoyo_read_file_pattern(struct tom
3713 if (!done)
3714 break;
3715 }
3716 - up_read(&tomoyo_pattern_list_lock);
3717 return done;
3718 }
3719
3720 @@ -487,8 +478,7 @@ bool tomoyo_read_file_pattern(struct tom
3721 * " (deleted)" suffix if the file is already unlink()ed; so that we don't
3722 * need to worry whether the file is already unlink()ed or not.
3723 */
3724 -static LIST_HEAD(tomoyo_no_rewrite_list);
3725 -static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
3726 +LIST_HEAD(tomoyo_no_rewrite_list);
3727
3728 /**
3729 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
3730 @@ -497,39 +487,42 @@ static DECLARE_RWSEM(tomoyo_no_rewrite_l
3731 * @is_delete: True if it is a delete request.
3732 *
3733 * Returns 0 on success, negative value otherwise.
3734 + *
3735 + * Caller holds tomoyo_read_lock().
3736 */
3737 static int tomoyo_update_no_rewrite_entry(const char *pattern,
3738 const bool is_delete)
3739 {
3740 - struct tomoyo_no_rewrite_entry *new_entry, *ptr;
3741 - const struct tomoyo_path_info *saved_pattern;
3742 - int error = -ENOMEM;
3743 + struct tomoyo_no_rewrite_entry *ptr;
3744 + struct tomoyo_no_rewrite_entry e = { };
3745 + int error = is_delete ? -ENOENT : -ENOMEM;
3746
3747 - if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
3748 + if (!tomoyo_is_correct_path(pattern, 0, 0, 0))
3749 return -EINVAL;
3750 - saved_pattern = tomoyo_save_name(pattern);
3751 - if (!saved_pattern)
3752 - return -ENOMEM;
3753 - down_write(&tomoyo_no_rewrite_list_lock);
3754 - list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
3755 - if (ptr->pattern != saved_pattern)
3756 + e.pattern = tomoyo_get_name(pattern);
3757 + if (!e.pattern)
3758 + return error;
3759 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
3760 + goto out;
3761 + list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
3762 + if (ptr->pattern != e.pattern)
3763 continue;
3764 ptr->is_deleted = is_delete;
3765 error = 0;
3766 - goto out;
3767 + break;
3768 }
3769 - if (is_delete) {
3770 - error = -ENOENT;
3771 - goto out;
3772 + if (!is_delete && error) {
3773 + struct tomoyo_no_rewrite_entry *entry =
3774 + tomoyo_commit_ok(&e, sizeof(e));
3775 + if (entry) {
3776 + list_add_tail_rcu(&entry->list,
3777 + &tomoyo_no_rewrite_list);
3778 + error = 0;
3779 + }
3780 }
3781 - new_entry = tomoyo_alloc_element(sizeof(*new_entry));
3782 - if (!new_entry)
3783 - goto out;
3784 - new_entry->pattern = saved_pattern;
3785 - list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
3786 - error = 0;
3787 + mutex_unlock(&tomoyo_policy_lock);
3788 out:
3789 - up_write(&tomoyo_no_rewrite_list_lock);
3790 + tomoyo_put_name(e.pattern);
3791 return error;
3792 }
3793
3794 @@ -540,14 +533,15 @@ static int tomoyo_update_no_rewrite_entr
3795 *
3796 * Returns true if @filename is specified by "deny_rewrite" directive,
3797 * false otherwise.
3798 + *
3799 + * Caller holds tomoyo_read_lock().
3800 */
3801 static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
3802 {
3803 struct tomoyo_no_rewrite_entry *ptr;
3804 bool found = false;
3805
3806 - down_read(&tomoyo_no_rewrite_list_lock);
3807 - list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
3808 + list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
3809 if (ptr->is_deleted)
3810 continue;
3811 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
3812 @@ -555,7 +549,6 @@ static bool tomoyo_is_no_rewrite_file(co
3813 found = true;
3814 break;
3815 }
3816 - up_read(&tomoyo_no_rewrite_list_lock);
3817 return found;
3818 }
3819
3820 @@ -566,6 +559,8 @@ static bool tomoyo_is_no_rewrite_file(co
3821 * @is_delete: True if it is a delete request.
3822 *
3823 * Returns 0 on success, negative value otherwise.
3824 + *
3825 + * Caller holds tomoyo_read_lock().
3826 */
3827 int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
3828 {
3829 @@ -578,13 +573,14 @@ int tomoyo_write_no_rewrite_policy(char
3830 * @head: Pointer to "struct tomoyo_io_buffer".
3831 *
3832 * Returns true on success, false otherwise.
3833 + *
3834 + * Caller holds tomoyo_read_lock().
3835 */
3836 bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
3837 {
3838 struct list_head *pos;
3839 bool done = true;
3840
3841 - down_read(&tomoyo_no_rewrite_list_lock);
3842 list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
3843 struct tomoyo_no_rewrite_entry *ptr;
3844 ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
3845 @@ -595,7 +591,6 @@ bool tomoyo_read_no_rewrite_policy(struc
3846 if (!done)
3847 break;
3848 }
3849 - up_read(&tomoyo_no_rewrite_list_lock);
3850 return done;
3851 }
3852
3853 @@ -613,6 +608,8 @@ bool tomoyo_read_no_rewrite_policy(struc
3854 * Current policy syntax uses "allow_read/write" instead of "6",
3855 * "allow_read" instead of "4", "allow_write" instead of "2",
3856 * "allow_execute" instead of "1".
3857 + *
3858 + * Caller holds tomoyo_read_lock().
3859 */
3860 static int tomoyo_update_file_acl(const char *filename, u8 perm,
3861 struct tomoyo_domain_info * const domain,
3862 @@ -630,19 +627,19 @@ static int tomoyo_update_file_acl(const
3863 */
3864 return 0;
3865 if (perm & 4)
3866 - tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename,
3867 - domain, is_delete);
3868 + tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain,
3869 + is_delete);
3870 if (perm & 2)
3871 - tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename,
3872 - domain, is_delete);
3873 + tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain,
3874 + is_delete);
3875 if (perm & 1)
3876 - tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL,
3877 - filename, domain, is_delete);
3878 + tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain,
3879 + is_delete);
3880 return 0;
3881 }
3882
3883 /**
3884 - * tomoyo_check_single_path_acl2 - Check permission for single path operation.
3885 + * tomoyo_path_acl2 - Check permission for single path operation.
3886 *
3887 * @domain: Pointer to "struct tomoyo_domain_info".
3888 * @filename: Filename to check.
3889 @@ -650,37 +647,34 @@ static int tomoyo_update_file_acl(const
3890 * @may_use_pattern: True if patterned ACL is permitted.
3891 *
3892 * Returns 0 on success, -EPERM otherwise.
3893 + *
3894 + * Caller holds tomoyo_read_lock().
3895 */
3896 -static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
3897 - domain,
3898 - const struct tomoyo_path_info *
3899 - filename,
3900 - const u16 perm,
3901 - const bool may_use_pattern)
3902 +static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain,
3903 + const struct tomoyo_path_info *filename,
3904 + const u32 perm, const bool may_use_pattern)
3905 {
3906 struct tomoyo_acl_info *ptr;
3907 int error = -EPERM;
3908
3909 - down_read(&tomoyo_domain_acl_info_list_lock);
3910 - list_for_each_entry(ptr, &domain->acl_info_list, list) {
3911 - struct tomoyo_single_path_acl_record *acl;
3912 - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
3913 - continue;
3914 - acl = container_of(ptr, struct tomoyo_single_path_acl_record,
3915 - head);
3916 - if (!(acl->perm & perm))
3917 - continue;
3918 - if (may_use_pattern || !acl->filename->is_patterned) {
3919 - if (!tomoyo_path_matches_pattern(filename,
3920 - acl->filename))
3921 + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
3922 + struct tomoyo_path_acl *acl;
3923 + if (ptr->type != TOMOYO_TYPE_PATH_ACL)
3924 + continue;
3925 + acl = container_of(ptr, struct tomoyo_path_acl, head);
3926 + if (perm <= 0xFFFF) {
3927 + if (!(acl->perm & perm))
3928 continue;
3929 } else {
3930 - continue;
3931 + if (!(acl->perm_high & (perm >> 16)))
3932 + continue;
3933 }
3934 + if (!tomoyo_compare_name_union_pattern(filename, &acl->name,
3935 + may_use_pattern))
3936 + continue;
3937 error = 0;
3938 break;
3939 }
3940 - up_read(&tomoyo_domain_acl_info_list_lock);
3941 return error;
3942 }
3943
3944 @@ -692,27 +686,28 @@ static int tomoyo_check_single_path_acl2
3945 * @operation: Mode ("read" or "write" or "read/write" or "execute").
3946 *
3947 * Returns 0 on success, -EPERM otherwise.
3948 + *
3949 + * Caller holds tomoyo_read_lock().
3950 */
3951 static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
3952 const struct tomoyo_path_info *filename,
3953 const u8 operation)
3954 {
3955 - u16 perm = 0;
3956 + u32 perm = 0;
3957
3958 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
3959 return 0;
3960 if (operation == 6)
3961 - perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL;
3962 + perm = 1 << TOMOYO_TYPE_READ_WRITE;
3963 else if (operation == 4)
3964 - perm = 1 << TOMOYO_TYPE_READ_ACL;
3965 + perm = 1 << TOMOYO_TYPE_READ;
3966 else if (operation == 2)
3967 - perm = 1 << TOMOYO_TYPE_WRITE_ACL;
3968 + perm = 1 << TOMOYO_TYPE_WRITE;
3969 else if (operation == 1)
3970 - perm = 1 << TOMOYO_TYPE_EXECUTE_ACL;
3971 + perm = 1 << TOMOYO_TYPE_EXECUTE;
3972 else
3973 BUG();
3974 - return tomoyo_check_single_path_acl2(domain, filename, perm,
3975 - operation != 1);
3976 + return tomoyo_path_acl2(domain, filename, perm, operation != 1);
3977 }
3978
3979 /**
3980 @@ -725,6 +720,8 @@ static int tomoyo_check_file_acl(const s
3981 * @mode: Access control mode.
3982 *
3983 * Returns 0 on success, negative value otherwise.
3984 + *
3985 + * Caller holds tomoyo_read_lock().
3986 */
3987 static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
3988 const struct tomoyo_path_info *filename,
3989 @@ -738,18 +735,17 @@ static int tomoyo_check_file_perm2(struc
3990 if (!filename)
3991 return 0;
3992 error = tomoyo_check_file_acl(domain, filename, perm);
3993 - if (error && perm == 4 &&
3994 - (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
3995 + if (error && perm == 4 && !domain->ignore_global_allow_read
3996 && tomoyo_is_globally_readable_file(filename))
3997 error = 0;
3998 if (perm == 6)
3999 - msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL);
4000 + msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE);
4001 else if (perm == 4)
4002 - msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL);
4003 + msg = tomoyo_path2keyword(TOMOYO_TYPE_READ);
4004 else if (perm == 2)
4005 - msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL);
4006 + msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE);
4007 else if (perm == 1)
4008 - msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL);
4009 + msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE);
4010 else
4011 BUG();
4012 if (!error)
4013 @@ -778,6 +774,8 @@ static int tomoyo_check_file_perm2(struc
4014 * @is_delete: True if it is a delete request.
4015 *
4016 * Returns 0 on success, negative value otherwise.
4017 + *
4018 + * Caller holds tomoyo_read_lock().
4019 */
4020 int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
4021 const bool is_delete)
4022 @@ -796,28 +794,28 @@ int tomoyo_write_file_policy(char *data,
4023 if (strncmp(data, "allow_", 6))
4024 goto out;
4025 data += 6;
4026 - for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) {
4027 - if (strcmp(data, tomoyo_sp_keyword[type]))
4028 + for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
4029 + if (strcmp(data, tomoyo_path_keyword[type]))
4030 continue;
4031 - return tomoyo_update_single_path_acl(type, filename,
4032 - domain, is_delete);
4033 + return tomoyo_update_path_acl(type, filename, domain,
4034 + is_delete);
4035 }
4036 filename2 = strchr(filename, ' ');
4037 if (!filename2)
4038 goto out;
4039 *filename2++ = '\0';
4040 - for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) {
4041 - if (strcmp(data, tomoyo_dp_keyword[type]))
4042 + for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) {
4043 + if (strcmp(data, tomoyo_path2_keyword[type]))
4044 continue;
4045 - return tomoyo_update_double_path_acl(type, filename, filename2,
4046 - domain, is_delete);
4047 + return tomoyo_update_path2_acl(type, filename, filename2,
4048 + domain, is_delete);
4049 }
4050 out:
4051 return -EINVAL;
4052 }
4053
4054 /**
4055 - * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list.
4056 + * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
4057 *
4058 * @type: Type of operation.
4059 * @filename: Filename.
4060 @@ -825,85 +823,76 @@ int tomoyo_write_file_policy(char *data,
4061 * @is_delete: True if it is a delete request.
4062 *
4063 * Returns 0 on success, negative value otherwise.
4064 + *
4065 + * Caller holds tomoyo_read_lock().
4066 */
4067 -static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
4068 - struct tomoyo_domain_info *
4069 - const domain, const bool is_delete)
4070 -{
4071 - static const u16 rw_mask =
4072 - (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
4073 - const struct tomoyo_path_info *saved_filename;
4074 +static int tomoyo_update_path_acl(const u8 type, const char *filename,
4075 + struct tomoyo_domain_info *const domain,
4076 + const bool is_delete)
4077 +{
4078 + static const u32 tomoyo_rw_mask =
4079 + (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE);
4080 + const u32 perm = 1 << type;
4081 struct tomoyo_acl_info *ptr;
4082 - struct tomoyo_single_path_acl_record *acl;
4083 - int error = -ENOMEM;
4084 - const u16 perm = 1 << type;
4085 + struct tomoyo_path_acl e = {
4086 + .head.type = TOMOYO_TYPE_PATH_ACL,
4087 + .perm_high = perm >> 16,
4088 + .perm = perm
4089 + };
4090 + int error = is_delete ? -ENOENT : -ENOMEM;
4091
4092 + if (type == TOMOYO_TYPE_READ_WRITE)
4093 + e.perm |= tomoyo_rw_mask;
4094 if (!domain)
4095 return -EINVAL;
4096 - if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
4097 + if (!tomoyo_parse_name_union(filename, &e.name))
4098 return -EINVAL;
4099 - saved_filename = tomoyo_save_name(filename);
4100 - if (!saved_filename)
4101 - return -ENOMEM;
4102 - down_write(&tomoyo_domain_acl_info_list_lock);
4103 - if (is_delete)
4104 - goto delete;
4105 - list_for_each_entry(ptr, &domain->acl_info_list, list) {
4106 - if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
4107 - continue;
4108 - acl = container_of(ptr, struct tomoyo_single_path_acl_record,
4109 - head);
4110 - if (acl->filename != saved_filename)
4111 - continue;
4112 - /* Special case. Clear all bits if marked as deleted. */
4113 - if (ptr->type & TOMOYO_ACL_DELETED)
4114 - acl->perm = 0;
4115 - acl->perm |= perm;
4116 - if ((acl->perm & rw_mask) == rw_mask)
4117 - acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
4118 - else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
4119 - acl->perm |= rw_mask;
4120 - ptr->type &= ~TOMOYO_ACL_DELETED;
4121 - error = 0;
4122 - goto out;
4123 - }
4124 - /* Not found. Append it to the tail. */
4125 - acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
4126 - if (!acl)
4127 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
4128 goto out;
4129 - acl->perm = perm;
4130 - if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
4131 - acl->perm |= rw_mask;
4132 - acl->filename = saved_filename;
4133 - list_add_tail(&acl->head.list, &domain->acl_info_list);
4134 - error = 0;
4135 - goto out;
4136 - delete:
4137 - error = -ENOENT;
4138 - list_for_each_entry(ptr, &domain->acl_info_list, list) {
4139 - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
4140 - continue;
4141 - acl = container_of(ptr, struct tomoyo_single_path_acl_record,
4142 - head);
4143 - if (acl->filename != saved_filename)
4144 - continue;
4145 - acl->perm &= ~perm;
4146 - if ((acl->perm & rw_mask) != rw_mask)
4147 - acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
4148 - else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
4149 - acl->perm &= ~rw_mask;
4150 - if (!acl->perm)
4151 - ptr->type |= TOMOYO_ACL_DELETED;
4152 + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
4153 + struct tomoyo_path_acl *acl =
4154 + container_of(ptr, struct tomoyo_path_acl, head);
4155 + if (!tomoyo_is_same_path_acl(acl, &e))
4156 + continue;
4157 + if (is_delete) {
4158 + if (perm <= 0xFFFF)
4159 + acl->perm &= ~perm;
4160 + else
4161 + acl->perm_high &= ~(perm >> 16);
4162 + if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask)
4163 + acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
4164 + else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)))
4165 + acl->perm &= ~tomoyo_rw_mask;
4166 + } else {
4167 + if (perm <= 0xFFFF)
4168 + acl->perm |= perm;
4169 + else
4170 + acl->perm_high |= (perm >> 16);
4171 + if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask)
4172 + acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
4173 + else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))
4174 + acl->perm |= tomoyo_rw_mask;
4175 + }
4176 error = 0;
4177 break;
4178 }
4179 + if (!is_delete && error) {
4180 + struct tomoyo_path_acl *entry =
4181 + tomoyo_commit_ok(&e, sizeof(e));
4182 + if (entry) {
4183 + list_add_tail_rcu(&entry->head.list,
4184 + &domain->acl_info_list);
4185 + error = 0;
4186 + }
4187 + }
4188 + mutex_unlock(&tomoyo_policy_lock);
4189 out:
4190 - up_write(&tomoyo_domain_acl_info_list_lock);
4191 + tomoyo_put_name_union(&e.name);
4192 return error;
4193 }
4194
4195 /**
4196 - * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list.
4197 + * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
4198 *
4199 * @type: Type of operation.
4200 * @filename1: First filename.
4201 @@ -912,98 +901,78 @@ static int tomoyo_update_single_path_acl
4202 * @is_delete: True if it is a delete request.
4203 *
4204 * Returns 0 on success, negative value otherwise.
4205 + *
4206 + * Caller holds tomoyo_read_lock().
4207 */
4208 -static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
4209 - const char *filename2,
4210 - struct tomoyo_domain_info *
4211 - const domain, const bool is_delete)
4212 +static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
4213 + const char *filename2,
4214 + struct tomoyo_domain_info *const domain,
4215 + const bool is_delete)
4216 {
4217 - const struct tomoyo_path_info *saved_filename1;
4218 - const struct tomoyo_path_info *saved_filename2;
4219 - struct tomoyo_acl_info *ptr;
4220 - struct tomoyo_double_path_acl_record *acl;
4221 - int error = -ENOMEM;
4222 const u8 perm = 1 << type;
4223 + struct tomoyo_path2_acl e = {
4224 + .head.type = TOMOYO_TYPE_PATH2_ACL,
4225 + .perm = perm
4226 + };
4227 + struct tomoyo_acl_info *ptr;
4228 + int error = is_delete ? -ENOENT : -ENOMEM;
4229
4230 if (!domain)
4231 return -EINVAL;
4232 - if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
4233 - !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
4234 - return -EINVAL;
4235 - saved_filename1 = tomoyo_save_name(filename1);
4236 - saved_filename2 = tomoyo_save_name(filename2);
4237 - if (!saved_filename1 || !saved_filename2)
4238 - return -ENOMEM;
4239 - down_write(&tomoyo_domain_acl_info_list_lock);
4240 - if (is_delete)
4241 - goto delete;
4242 - list_for_each_entry(ptr, &domain->acl_info_list, list) {
4243 - if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
4244 - continue;
4245 - acl = container_of(ptr, struct tomoyo_double_path_acl_record,
4246 - head);
4247 - if (acl->filename1 != saved_filename1 ||
4248 - acl->filename2 != saved_filename2)
4249 - continue;
4250 - /* Special case. Clear all bits if marked as deleted. */
4251 - if (ptr->type & TOMOYO_ACL_DELETED)
4252 - acl->perm = 0;
4253 - acl->perm |= perm;
4254 - ptr->type &= ~TOMOYO_ACL_DELETED;
4255 - error = 0;
4256 + if (!tomoyo_parse_name_union(filename1, &e.name1) ||
4257 + !tomoyo_parse_name_union(filename2, &e.name2))
4258 goto out;
4259 - }
4260 - /* Not found. Append it to the tail. */
4261 - acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
4262 - if (!acl)
4263 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
4264 goto out;
4265 - acl->perm = perm;
4266 - acl->filename1 = saved_filename1;
4267 - acl->filename2 = saved_filename2;
4268 - list_add_tail(&acl->head.list, &domain->acl_info_list);
4269 - error = 0;
4270 - goto out;
4271 - delete:
4272 - error = -ENOENT;
4273 - list_for_each_entry(ptr, &domain->acl_info_list, list) {
4274 - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
4275 - continue;
4276 - acl = container_of(ptr, struct tomoyo_double_path_acl_record,
4277 - head);
4278 - if (acl->filename1 != saved_filename1 ||
4279 - acl->filename2 != saved_filename2)
4280 - continue;
4281 - acl->perm &= ~perm;
4282 - if (!acl->perm)
4283 - ptr->type |= TOMOYO_ACL_DELETED;
4284 + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
4285 + struct tomoyo_path2_acl *acl =
4286 + container_of(ptr, struct tomoyo_path2_acl, head);
4287 + if (!tomoyo_is_same_path2_acl(acl, &e))
4288 + continue;
4289 + if (is_delete)
4290 + acl->perm &= ~perm;
4291 + else
4292 + acl->perm |= perm;
4293 error = 0;
4294 break;
4295 }
4296 + if (!is_delete && error) {
4297 + struct tomoyo_path2_acl *entry =
4298 + tomoyo_commit_ok(&e, sizeof(e));
4299 + if (entry) {
4300 + list_add_tail_rcu(&entry->head.list,
4301 + &domain->acl_info_list);
4302 + error = 0;
4303 + }
4304 + }
4305 + mutex_unlock(&tomoyo_policy_lock);
4306 out:
4307 - up_write(&tomoyo_domain_acl_info_list_lock);
4308 + tomoyo_put_name_union(&e.name1);
4309 + tomoyo_put_name_union(&e.name2);
4310 return error;
4311 }
4312
4313 /**
4314 - * tomoyo_check_single_path_acl - Check permission for single path operation.
4315 + * tomoyo_path_acl - Check permission for single path operation.
4316 *
4317 * @domain: Pointer to "struct tomoyo_domain_info".
4318 * @type: Type of operation.
4319 * @filename: Filename to check.
4320 *
4321 * Returns 0 on success, negative value otherwise.
4322 + *
4323 + * Caller holds tomoyo_read_lock().
4324 */
4325 -static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
4326 - const u8 type,
4327 - const struct tomoyo_path_info *filename)
4328 +static int tomoyo_path_acl(struct tomoyo_domain_info *domain, const u8 type,
4329 + const struct tomoyo_path_info *filename)
4330 {
4331 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
4332 return 0;
4333 - return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1);
4334 + return tomoyo_path_acl2(domain, filename, 1 << type, 1);
4335 }
4336
4337 /**
4338 - * tomoyo_check_double_path_acl - Check permission for double path operation.
4339 + * tomoyo_path2_acl - Check permission for double path operation.
4340 *
4341 * @domain: Pointer to "struct tomoyo_domain_info".
4342 * @type: Type of operation.
4343 @@ -1011,13 +980,13 @@ static int tomoyo_check_single_path_acl(
4344 * @filename2: Second filename to check.
4345 *
4346 * Returns 0 on success, -EPERM otherwise.
4347 + *
4348 + * Caller holds tomoyo_read_lock().
4349 */
4350 -static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
4351 - const u8 type,
4352 - const struct tomoyo_path_info *
4353 - filename1,
4354 - const struct tomoyo_path_info *
4355 - filename2)
4356 +static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain,
4357 + const u8 type,
4358 + const struct tomoyo_path_info *filename1,
4359 + const struct tomoyo_path_info *filename2)
4360 {
4361 struct tomoyo_acl_info *ptr;
4362 const u8 perm = 1 << type;
4363 @@ -1025,28 +994,25 @@ static int tomoyo_check_double_path_acl(
4364
4365 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
4366 return 0;
4367 - down_read(&tomoyo_domain_acl_info_list_lock);
4368 - list_for_each_entry(ptr, &domain->acl_info_list, list) {
4369 - struct tomoyo_double_path_acl_record *acl;
4370 - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
4371 + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
4372 + struct tomoyo_path2_acl *acl;
4373 + if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
4374 continue;
4375 - acl = container_of(ptr, struct tomoyo_double_path_acl_record,
4376 - head);
4377 + acl = container_of(ptr, struct tomoyo_path2_acl, head);
4378 if (!(acl->perm & perm))
4379 continue;
4380 - if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
4381 + if (!tomoyo_compare_name_union(filename1, &acl->name1))
4382 continue;
4383 - if (!tomoyo_path_matches_pattern(filename2, acl->filename2))
4384 + if (!tomoyo_compare_name_union(filename2, &acl->name2))
4385 continue;
4386 error = 0;
4387 break;
4388 }
4389 - up_read(&tomoyo_domain_acl_info_list_lock);
4390 return error;
4391 }
4392
4393 /**
4394 - * tomoyo_check_single_path_permission2 - Check permission for single path operation.
4395 + * tomoyo_path_permission2 - Check permission for single path operation.
4396 *
4397 * @domain: Pointer to "struct tomoyo_domain_info".
4398 * @operation: Type of operation.
4399 @@ -1054,11 +1020,13 @@ static int tomoyo_check_double_path_acl(
4400 * @mode: Access control mode.
4401 *
4402 * Returns 0 on success, negative value otherwise.
4403 + *
4404 + * Caller holds tomoyo_read_lock().
4405 */
4406 -static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
4407 - const domain, u8 operation,
4408 - const struct tomoyo_path_info *
4409 - filename, const u8 mode)
4410 +static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain,
4411 + u8 operation,
4412 + const struct tomoyo_path_info *filename,
4413 + const u8 mode)
4414 {
4415 const char *msg;
4416 int error;
4417 @@ -1067,8 +1035,8 @@ static int tomoyo_check_single_path_perm
4418 if (!mode)
4419 return 0;
4420 next:
4421 - error = tomoyo_check_single_path_acl(domain, operation, filename);
4422 - msg = tomoyo_sp2keyword(operation);
4423 + error = tomoyo_path_acl(domain, operation, filename);
4424 + msg = tomoyo_path2keyword(operation);
4425 if (!error)
4426 goto ok;
4427 if (tomoyo_verbose_mode(domain))
4428 @@ -1077,7 +1045,7 @@ static int tomoyo_check_single_path_perm
4429 tomoyo_get_last_name(domain));
4430 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
4431 const char *name = tomoyo_get_file_pattern(filename)->name;
4432 - tomoyo_update_single_path_acl(operation, name, domain, false);
4433 + tomoyo_update_path_acl(operation, name, domain, false);
4434 }
4435 if (!is_enforce)
4436 error = 0;
4437 @@ -1087,9 +1055,9 @@ static int tomoyo_check_single_path_perm
4438 * we need to check "allow_rewrite" permission if the filename is
4439 * specified by "deny_rewrite" keyword.
4440 */
4441 - if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL &&
4442 + if (!error && operation == TOMOYO_TYPE_TRUNCATE &&
4443 tomoyo_is_no_rewrite_file(filename)) {
4444 - operation = TOMOYO_TYPE_REWRITE_ACL;
4445 + operation = TOMOYO_TYPE_REWRITE;
4446 goto next;
4447 }
4448 return error;
4449 @@ -1098,22 +1066,27 @@ static int tomoyo_check_single_path_perm
4450 /**
4451 * tomoyo_check_file_perm - Check permission for sysctl()'s "read" and "write".
4452 *
4453 - * @domain: Pointer to "struct tomoyo_domain_info".
4454 * @filename: Filename to check.
4455 * @perm: Mode ("read" or "write" or "read/write").
4456 * Returns 0 on success, negative value otherwise.
4457 */
4458 -int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
4459 - const char *filename, const u8 perm)
4460 +int tomoyo_check_file_perm(const char *filename, const u8 perm)
4461 {
4462 + int error;
4463 + int idx;
4464 struct tomoyo_path_info name;
4465 + struct tomoyo_domain_info *domain = tomoyo_domain();
4466 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
4467
4468 if (!mode)
4469 return 0;
4470 name.name = filename;
4471 tomoyo_fill_path_info(&name);
4472 - return tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode);
4473 +
4474 + idx = tomoyo_read_lock();
4475 + error = tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode);
4476 + tomoyo_read_unlock(idx);
4477 + return error;
4478 }
4479
4480 /**
4481 @@ -1123,6 +1096,8 @@ int tomoyo_check_file_perm(struct tomoyo
4482 * @filename: Check permission for "execute".
4483 *
4484 * Returns 0 on success, negativevalue otherwise.
4485 + *
4486 + * Caller holds tomoyo_read_lock().
4487 */
4488 int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
4489 const struct tomoyo_path_info *filename)
4490 @@ -1151,6 +1126,7 @@ int tomoyo_check_open_permission(struct
4491 struct tomoyo_path_info *buf;
4492 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
4493 const bool is_enforce = (mode == 3);
4494 + int idx;
4495
4496 if (!mode || !path->mnt)
4497 return 0;
4498 @@ -1162,6 +1138,7 @@ int tomoyo_check_open_permission(struct
4499 * don't call me.
4500 */
4501 return 0;
4502 + idx = tomoyo_read_lock();
4503 buf = tomoyo_get_path(path);
4504 if (!buf)
4505 goto out;
4506 @@ -1174,49 +1151,50 @@ int tomoyo_check_open_permission(struct
4507 if ((acc_mode & MAY_WRITE) &&
4508 ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
4509 (tomoyo_is_no_rewrite_file(buf))) {
4510 - error = tomoyo_check_single_path_permission2(domain,
4511 - TOMOYO_TYPE_REWRITE_ACL,
4512 - buf, mode);
4513 + error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE,
4514 + buf, mode);
4515 }
4516 if (!error)
4517 error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
4518 mode);
4519 if (!error && (flag & O_TRUNC))
4520 - error = tomoyo_check_single_path_permission2(domain,
4521 - TOMOYO_TYPE_TRUNCATE_ACL,
4522 - buf, mode);
4523 + error = tomoyo_path_permission2(domain, TOMOYO_TYPE_TRUNCATE,
4524 + buf, mode);
4525 out:
4526 - tomoyo_free(buf);
4527 + kfree(buf);
4528 + tomoyo_read_unlock(idx);
4529 if (!is_enforce)
4530 error = 0;
4531 return error;
4532 }
4533
4534 /**
4535 - * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink".
4536 + * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount".
4537 *
4538 - * @domain: Pointer to "struct tomoyo_domain_info".
4539 * @operation: Type of operation.
4540 * @path: Pointer to "struct path".
4541 *
4542 * Returns 0 on success, negative value otherwise.
4543 */
4544 -int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
4545 - const u8 operation, struct path *path)
4546 +int tomoyo_path_perm(const u8 operation, struct path *path)
4547 {
4548 int error = -ENOMEM;
4549 struct tomoyo_path_info *buf;
4550 + struct tomoyo_domain_info *domain = tomoyo_domain();
4551 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
4552 const bool is_enforce = (mode == 3);
4553 + int idx;
4554
4555 if (!mode || !path->mnt)
4556 return 0;
4557 + idx = tomoyo_read_lock();
4558 buf = tomoyo_get_path(path);
4559 if (!buf)
4560 goto out;
4561 switch (operation) {
4562 - case TOMOYO_TYPE_MKDIR_ACL:
4563 - case TOMOYO_TYPE_RMDIR_ACL:
4564 + case TOMOYO_TYPE_MKDIR:
4565 + case TOMOYO_TYPE_RMDIR:
4566 + case TOMOYO_TYPE_CHROOT:
4567 if (!buf->is_dir) {
4568 /*
4569 * tomoyo_get_path() reserves space for appending "/."
4570 @@ -1225,10 +1203,10 @@ int tomoyo_check_1path_perm(struct tomoy
4571 tomoyo_fill_path_info(buf);
4572 }
4573 }
4574 - error = tomoyo_check_single_path_permission2(domain, operation, buf,
4575 - mode);
4576 + error = tomoyo_path_permission2(domain, operation, buf, mode);
4577 out:
4578 - tomoyo_free(buf);
4579 + kfree(buf);
4580 + tomoyo_read_unlock(idx);
4581 if (!is_enforce)
4582 error = 0;
4583 return error;
4584 @@ -1237,21 +1215,23 @@ int tomoyo_check_1path_perm(struct tomoy
4585 /**
4586 * tomoyo_check_rewrite_permission - Check permission for "rewrite".
4587 *
4588 - * @domain: Pointer to "struct tomoyo_domain_info".
4589 * @filp: Pointer to "struct file".
4590 *
4591 * Returns 0 on success, negative value otherwise.
4592 */
4593 -int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
4594 - struct file *filp)
4595 +int tomoyo_check_rewrite_permission(struct file *filp)
4596 {
4597 int error = -ENOMEM;
4598 + struct tomoyo_domain_info *domain = tomoyo_domain();
4599 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
4600 const bool is_enforce = (mode == 3);
4601 struct tomoyo_path_info *buf;
4602 + int idx;
4603
4604 if (!mode || !filp->f_path.mnt)
4605 return 0;
4606 +
4607 + idx = tomoyo_read_lock();
4608 buf = tomoyo_get_path(&filp->f_path);
4609 if (!buf)
4610 goto out;
4611 @@ -1259,38 +1239,38 @@ int tomoyo_check_rewrite_permission(stru
4612 error = 0;
4613 goto out;
4614 }
4615 - error = tomoyo_check_single_path_permission2(domain,
4616 - TOMOYO_TYPE_REWRITE_ACL,
4617 - buf, mode);
4618 + error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, buf, mode);
4619 out:
4620 - tomoyo_free(buf);
4621 + kfree(buf);
4622 + tomoyo_read_unlock(idx);
4623 if (!is_enforce)
4624 error = 0;
4625 return error;
4626 }
4627
4628 /**
4629 - * tomoyo_check_2path_perm - Check permission for "rename" and "link".
4630 + * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
4631 *
4632 - * @domain: Pointer to "struct tomoyo_domain_info".
4633 * @operation: Type of operation.
4634 * @path1: Pointer to "struct path".
4635 * @path2: Pointer to "struct path".
4636 *
4637 * Returns 0 on success, negative value otherwise.
4638 */
4639 -int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
4640 - const u8 operation, struct path *path1,
4641 - struct path *path2)
4642 +int tomoyo_path2_perm(const u8 operation, struct path *path1,
4643 + struct path *path2)
4644 {
4645 int error = -ENOMEM;
4646 struct tomoyo_path_info *buf1, *buf2;
4647 + struct tomoyo_domain_info *domain = tomoyo_domain();
4648 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
4649 const bool is_enforce = (mode == 3);
4650 const char *msg;
4651 + int idx;
4652
4653 if (!mode || !path1->mnt || !path2->mnt)
4654 return 0;
4655 + idx = tomoyo_read_lock();
4656 buf1 = tomoyo_get_path(path1);
4657 buf2 = tomoyo_get_path(path2);
4658 if (!buf1 || !buf2)
4659 @@ -1311,8 +1291,8 @@ int tomoyo_check_2path_perm(struct tomoy
4660 }
4661 }
4662 }
4663 - error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2);
4664 - msg = tomoyo_dp2keyword(operation);
4665 + error = tomoyo_path2_acl(domain, operation, buf1, buf2);
4666 + msg = tomoyo_path22keyword(operation);
4667 if (!error)
4668 goto out;
4669 if (tomoyo_verbose_mode(domain))
4670 @@ -1323,12 +1303,13 @@ int tomoyo_check_2path_perm(struct tomoy
4671 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
4672 const char *name1 = tomoyo_get_file_pattern(buf1)->name;
4673 const char *name2 = tomoyo_get_file_pattern(buf2)->name;
4674 - tomoyo_update_double_path_acl(operation, name1, name2, domain,
4675 - false);
4676 + tomoyo_update_path2_acl(operation, name1, name2, domain,
4677 + false);
4678 }
4679 out:
4680 - tomoyo_free(buf1);
4681 - tomoyo_free(buf2);
4682 + kfree(buf1);
4683 + kfree(buf2);
4684 + tomoyo_read_unlock(idx);
4685 if (!is_enforce)
4686 error = 0;
4687 return error;
4688 --- /dev/null
4689 +++ linux-2.6.32.28/security/tomoyo/gc.c
4690 @@ -0,0 +1,412 @@
4691 +/*
4692 + * security/tomoyo/gc.c
4693 + *
4694 + * Implementation of the Domain-Based Mandatory Access Control.
4695 + *
4696 + * Copyright (C) 2005-2010 NTT DATA CORPORATION
4697 + *
4698 + */
4699 +
4700 +#include "common.h"
4701 +#include <linux/kthread.h>
4702 +#include <linux/slab.h>
4703 +
4704 +enum tomoyo_gc_id {
4705 + TOMOYO_ID_PATH_GROUP,
4706 + TOMOYO_ID_PATH_GROUP_MEMBER,
4707 + TOMOYO_ID_DOMAIN_INITIALIZER,
4708 + TOMOYO_ID_DOMAIN_KEEPER,
4709 + TOMOYO_ID_ALIAS,
4710 + TOMOYO_ID_GLOBALLY_READABLE,
4711 + TOMOYO_ID_PATTERN,
4712 + TOMOYO_ID_NO_REWRITE,
4713 + TOMOYO_ID_MANAGER,
4714 + TOMOYO_ID_NAME,
4715 + TOMOYO_ID_ACL,
4716 + TOMOYO_ID_DOMAIN
4717 +};
4718 +
4719 +struct tomoyo_gc_entry {
4720 + struct list_head list;
4721 + int type;
4722 + void *element;
4723 +};
4724 +static LIST_HEAD(tomoyo_gc_queue);
4725 +static DEFINE_MUTEX(tomoyo_gc_mutex);
4726 +
4727 +/* Caller holds tomoyo_policy_lock mutex. */
4728 +static bool tomoyo_add_to_gc(const int type, void *element)
4729 +{
4730 + struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
4731 + if (!entry)
4732 + return false;
4733 + entry->type = type;
4734 + entry->element = element;
4735 + list_add(&entry->list, &tomoyo_gc_queue);
4736 + return true;
4737 +}
4738 +
4739 +static void tomoyo_del_allow_read
4740 +(struct tomoyo_globally_readable_file_entry *ptr)
4741 +{
4742 + tomoyo_put_name(ptr->filename);
4743 +}
4744 +
4745 +static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr)
4746 +{
4747 + tomoyo_put_name(ptr->pattern);
4748 +}
4749 +
4750 +static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr)
4751 +{
4752 + tomoyo_put_name(ptr->pattern);
4753 +}
4754 +
4755 +static void tomoyo_del_domain_initializer
4756 +(struct tomoyo_domain_initializer_entry *ptr)
4757 +{
4758 + tomoyo_put_name(ptr->domainname);
4759 + tomoyo_put_name(ptr->program);
4760 +}
4761 +
4762 +static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr)
4763 +{
4764 + tomoyo_put_name(ptr->domainname);
4765 + tomoyo_put_name(ptr->program);
4766 +}
4767 +
4768 +static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr)
4769 +{
4770 + tomoyo_put_name(ptr->original_name);
4771 + tomoyo_put_name(ptr->aliased_name);
4772 +}
4773 +
4774 +static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr)
4775 +{
4776 + tomoyo_put_name(ptr->manager);
4777 +}
4778 +
4779 +static void tomoyo_del_acl(struct tomoyo_acl_info *acl)
4780 +{
4781 + switch (acl->type) {
4782 + case TOMOYO_TYPE_PATH_ACL:
4783 + {
4784 + struct tomoyo_path_acl *entry
4785 + = container_of(acl, typeof(*entry), head);
4786 + tomoyo_put_name_union(&entry->name);
4787 + }
4788 + break;
4789 + case TOMOYO_TYPE_PATH2_ACL:
4790 + {
4791 + struct tomoyo_path2_acl *entry
4792 + = container_of(acl, typeof(*entry), head);
4793 + tomoyo_put_name_union(&entry->name1);
4794 + tomoyo_put_name_union(&entry->name2);
4795 + }
4796 + break;
4797 + default:
4798 + printk(KERN_WARNING "Unknown type\n");
4799 + break;
4800 + }
4801 +}
4802 +
4803 +static bool tomoyo_del_domain(struct tomoyo_domain_info *domain)
4804 +{
4805 + struct tomoyo_acl_info *acl;
4806 + struct tomoyo_acl_info *tmp;
4807 + /*
4808 + * Since we don't protect whole execve() operation using SRCU,
4809 + * we need to recheck domain->users at this point.
4810 + *
4811 + * (1) Reader starts SRCU section upon execve().
4812 + * (2) Reader traverses tomoyo_domain_list and finds this domain.
4813 + * (3) Writer marks this domain as deleted.
4814 + * (4) Garbage collector removes this domain from tomoyo_domain_list
4815 + * because this domain is marked as deleted and used by nobody.
4816 + * (5) Reader saves reference to this domain into
4817 + * "struct linux_binprm"->cred->security .
4818 + * (6) Reader finishes SRCU section, although execve() operation has
4819 + * not finished yet.
4820 + * (7) Garbage collector waits for SRCU synchronization.
4821 + * (8) Garbage collector kfree() this domain because this domain is
4822 + * used by nobody.
4823 + * (9) Reader finishes execve() operation and restores this domain from
4824 + * "struct linux_binprm"->cred->security.
4825 + *
4826 + * By updating domain->users at (5), we can solve this race problem
4827 + * by rechecking domain->users at (8).
4828 + */
4829 + if (atomic_read(&domain->users))
4830 + return false;
4831 + list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
4832 + tomoyo_del_acl(acl);
4833 + tomoyo_memory_free(acl);
4834 + }
4835 + tomoyo_put_name(domain->domainname);
4836 + return true;
4837 +}
4838 +
4839 +
4840 +static void tomoyo_del_name(const struct tomoyo_name_entry *ptr)
4841 +{
4842 +}
4843 +
4844 +static void tomoyo_del_path_group_member(struct tomoyo_path_group_member
4845 + *member)
4846 +{
4847 + tomoyo_put_name(member->member_name);
4848 +}
4849 +
4850 +static void tomoyo_del_path_group(struct tomoyo_path_group *group)
4851 +{
4852 + tomoyo_put_name(group->group_name);
4853 +}
4854 +
4855 +static void tomoyo_collect_entry(void)
4856 +{
4857 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
4858 + return;
4859 + {
4860 + struct tomoyo_globally_readable_file_entry *ptr;
4861 + list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list,
4862 + list) {
4863 + if (!ptr->is_deleted)
4864 + continue;
4865 + if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr))
4866 + list_del_rcu(&ptr->list);
4867 + else
4868 + break;
4869 + }
4870 + }
4871 + {
4872 + struct tomoyo_pattern_entry *ptr;
4873 + list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
4874 + if (!ptr->is_deleted)
4875 + continue;
4876 + if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr))
4877 + list_del_rcu(&ptr->list);
4878 + else
4879 + break;
4880 + }
4881 + }
4882 + {
4883 + struct tomoyo_no_rewrite_entry *ptr;
4884 + list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
4885 + if (!ptr->is_deleted)
4886 + continue;
4887 + if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr))
4888 + list_del_rcu(&ptr->list);
4889 + else
4890 + break;
4891 + }
4892 + }
4893 + {
4894 + struct tomoyo_domain_initializer_entry *ptr;
4895 + list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list,
4896 + list) {
4897 + if (!ptr->is_deleted)
4898 + continue;
4899 + if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr))
4900 + list_del_rcu(&ptr->list);
4901 + else
4902 + break;
4903 + }
4904 + }
4905 + {
4906 + struct tomoyo_domain_keeper_entry *ptr;
4907 + list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
4908 + if (!ptr->is_deleted)
4909 + continue;
4910 + if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr))
4911 + list_del_rcu(&ptr->list);
4912 + else
4913 + break;
4914 + }
4915 + }
4916 + {
4917 + struct tomoyo_alias_entry *ptr;
4918 + list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
4919 + if (!ptr->is_deleted)
4920 + continue;
4921 + if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr))
4922 + list_del_rcu(&ptr->list);
4923 + else
4924 + break;
4925 + }
4926 + }
4927 + {
4928 + struct tomoyo_policy_manager_entry *ptr;
4929 + list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list,
4930 + list) {
4931 + if (!ptr->is_deleted)
4932 + continue;
4933 + if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr))
4934 + list_del_rcu(&ptr->list);
4935 + else
4936 + break;
4937 + }
4938 + }
4939 + {
4940 + struct tomoyo_domain_info *domain;
4941 + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
4942 + struct tomoyo_acl_info *acl;
4943 + list_for_each_entry_rcu(acl, &domain->acl_info_list,
4944 + list) {
4945 + switch (acl->type) {
4946 + case TOMOYO_TYPE_PATH_ACL:
4947 + if (container_of(acl,
4948 + struct tomoyo_path_acl,
4949 + head)->perm ||
4950 + container_of(acl,
4951 + struct tomoyo_path_acl,
4952 + head)->perm_high)
4953 + continue;
4954 + break;
4955 + case TOMOYO_TYPE_PATH2_ACL:
4956 + if (container_of(acl,
4957 + struct tomoyo_path2_acl,
4958 + head)->perm)
4959 + continue;
4960 + break;
4961 + default:
4962 + continue;
4963 + }
4964 + if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl))
4965 + list_del_rcu(&acl->list);
4966 + else
4967 + break;
4968 + }
4969 + if (!domain->is_deleted || atomic_read(&domain->users))
4970 + continue;
4971 + /*
4972 + * Nobody is referring this domain. But somebody may
4973 + * refer this domain after successful execve().
4974 + * We recheck domain->users after SRCU synchronization.
4975 + */
4976 + if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain))
4977 + list_del_rcu(&domain->list);
4978 + else
4979 + break;
4980 + }
4981 + }
4982 + {
4983 + int i;
4984 + for (i = 0; i < TOMOYO_MAX_HASH; i++) {
4985 + struct tomoyo_name_entry *ptr;
4986 + list_for_each_entry_rcu(ptr, &tomoyo_name_list[i],
4987 + list) {
4988 + if (atomic_read(&ptr->users))
4989 + continue;
4990 + if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr))
4991 + list_del_rcu(&ptr->list);
4992 + else {
4993 + i = TOMOYO_MAX_HASH;
4994 + break;
4995 + }
4996 + }
4997 + }
4998 + }
4999 + {
5000 + struct tomoyo_path_group *group;
5001 + list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) {
5002 + struct tomoyo_path_group_member *member;
5003 + list_for_each_entry_rcu(member, &group->member_list,
5004 + list) {
5005 + if (!member->is_deleted)
5006 + continue;
5007 + if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER,
5008 + member))
5009 + list_del_rcu(&member->list);
5010 + else
5011 + break;
5012 + }
5013 + if (!list_empty(&group->member_list) ||
5014 + atomic_read(&group->users))
5015 + continue;
5016 + if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group))
5017 + list_del_rcu(&group->list);
5018 + else
5019 + break;
5020 + }
5021 + }
5022 + mutex_unlock(&tomoyo_policy_lock);
5023 +}
5024 +
5025 +static void tomoyo_kfree_entry(void)
5026 +{
5027 + struct tomoyo_gc_entry *p;
5028 + struct tomoyo_gc_entry *tmp;
5029 +
5030 + list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
5031 + switch (p->type) {
5032 + case TOMOYO_ID_DOMAIN_INITIALIZER:
5033 + tomoyo_del_domain_initializer(p->element);
5034 + break;
5035 + case TOMOYO_ID_DOMAIN_KEEPER:
5036 + tomoyo_del_domain_keeper(p->element);
5037 + break;
5038 + case TOMOYO_ID_ALIAS:
5039 + tomoyo_del_alias(p->element);
5040 + break;
5041 + case TOMOYO_ID_GLOBALLY_READABLE:
5042 + tomoyo_del_allow_read(p->element);
5043 + break;
5044 + case TOMOYO_ID_PATTERN:
5045 + tomoyo_del_file_pattern(p->element);
5046 + break;
5047 + case TOMOYO_ID_NO_REWRITE:
5048 + tomoyo_del_no_rewrite(p->element);
5049 + break;
5050 + case TOMOYO_ID_MANAGER:
5051 + tomoyo_del_manager(p->element);
5052 + break;
5053 + case TOMOYO_ID_NAME:
5054 + tomoyo_del_name(p->element);
5055 + break;
5056 + case TOMOYO_ID_ACL:
5057 + tomoyo_del_acl(p->element);
5058 + break;
5059 + case TOMOYO_ID_DOMAIN:
5060 + if (!tomoyo_del_domain(p->element))
5061 + continue;
5062 + break;
5063 + case TOMOYO_ID_PATH_GROUP_MEMBER:
5064 + tomoyo_del_path_group_member(p->element);
5065 + break;
5066 + case TOMOYO_ID_PATH_GROUP:
5067 + tomoyo_del_path_group(p->element);
5068 + break;
5069 + default:
5070 + printk(KERN_WARNING "Unknown type\n");
5071 + break;
5072 + }
5073 + tomoyo_m