1 |
[TOMOYO] Add chroot() handler. |
2 |
|
3 |
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> |
4 |
--- |
5 |
security/tomoyo/chroot.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++ |
6 |
1 file changed, 152 insertions(+) |
7 |
|
8 |
--- /dev/null |
9 |
+++ linux-2.6.32-rc1/security/tomoyo/chroot.c |
10 |
@@ -0,0 +1,152 @@ |
11 |
+/* |
12 |
+ * security/tomoyo/chroot.c |
13 |
+ * |
14 |
+ * Copyright (C) 2005-2009 NTT DATA CORPORATION |
15 |
+ */ |
16 |
+#include "internal.h" |
17 |
+ |
18 |
+/** |
19 |
+ * tomoyo_audit_chroot_log - Audit chroot log. |
20 |
+ * |
21 |
+ * @r: Pointer to "struct tomoyo_request_info". |
22 |
+ * @root: New root directory. |
23 |
+ * @is_granted: True if this is a granted log. |
24 |
+ * |
25 |
+ * Returns 0 on success, negative value otherwise. |
26 |
+ */ |
27 |
+static int tomoyo_audit_chroot_log(struct tomoyo_request_info *r, |
28 |
+ const char *root, const bool is_granted) |
29 |
+{ |
30 |
+ if (!is_granted) |
31 |
+ tomoyo_warn_log(r, "chroot %s", root); |
32 |
+ return tomoyo_write_audit_log(is_granted, r, |
33 |
+ TOMOYO_KEYWORD_ALLOW_CHROOT "%s\n", |
34 |
+ root); |
35 |
+} |
36 |
+ |
37 |
+/** |
38 |
+ * tomoyo_chroot_acl - Check permission for chroot(). |
39 |
+ * |
40 |
+ * @path: Pointer to "struct path". |
41 |
+ * |
42 |
+ * Returns 0 on success, negative value otherwise. |
43 |
+ * |
44 |
+ * Caller holds tomoyo_read_lock(). |
45 |
+ */ |
46 |
+static int tomoyo_chroot_acl(struct path *path) |
47 |
+{ |
48 |
+ struct tomoyo_request_info r; |
49 |
+ int error; |
50 |
+ struct tomoyo_path_info dir; |
51 |
+ char *root_name; |
52 |
+ struct tomoyo_obj_info obj = { |
53 |
+ .path1 = *path |
54 |
+ }; |
55 |
+ if (!tomoyo_capable(TOMOYO_SYS_CHROOT)) |
56 |
+ return -EPERM; |
57 |
+ if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_CHROOT) |
58 |
+ == TOMOYO_CONFIG_DISABLED) |
59 |
+ return 0; |
60 |
+ r.obj = &obj; |
61 |
+ error = -ENOMEM; |
62 |
+ root_name = tomoyo_realpath_from_path(path); |
63 |
+ if (!root_name) |
64 |
+ goto out; |
65 |
+ dir.name = root_name; |
66 |
+ tomoyo_fill_path_info(&dir); |
67 |
+ if (!dir.is_dir) |
68 |
+ goto out; |
69 |
+ do { |
70 |
+ struct tomoyo_acl_info *ptr; |
71 |
+ error = -EPERM; |
72 |
+ list_for_each_entry_rcu(ptr, &r.domain->acl_info_list, list) { |
73 |
+ struct tomoyo_chroot_acl *acl; |
74 |
+ if (ptr->is_deleted || |
75 |
+ ptr->type != TOMOYO_TYPE_CHROOT_ACL) |
76 |
+ continue; |
77 |
+ acl = container_of(ptr, struct tomoyo_chroot_acl, |
78 |
+ head); |
79 |
+ if (!tomoyo_compare_name_union(&dir, &acl->dir) || |
80 |
+ !tomoyo_condition(&r, ptr)) |
81 |
+ continue; |
82 |
+ r.cond = ptr->cond; |
83 |
+ error = 0; |
84 |
+ break; |
85 |
+ } |
86 |
+ tomoyo_audit_chroot_log(&r, root_name, !error); |
87 |
+ if (!error) |
88 |
+ break; |
89 |
+ error = tomoyo_supervisor(&r, TOMOYO_KEYWORD_ALLOW_CHROOT |
90 |
+ "%s\n", tomoyo_file_pattern(&dir)); |
91 |
+ } while (error == 1); |
92 |
+ out: |
93 |
+ kfree(root_name); |
94 |
+ if (r.mode != TOMOYO_CONFIG_ENFORCING) |
95 |
+ error = 0; |
96 |
+ return error; |
97 |
+} |
98 |
+ |
99 |
+/** |
100 |
+ * tomoyo_chroot_permission - Check permission for chroot(). |
101 |
+ * |
102 |
+ * @path: Pointer to "struct path". |
103 |
+ * |
104 |
+ * Returns 0 on success, negative value otherwise. |
105 |
+ */ |
106 |
+int tomoyo_chroot_permission(struct path *path) |
107 |
+{ |
108 |
+ const int idx = tomoyo_read_lock(); |
109 |
+ const int error = tomoyo_chroot_acl(path); |
110 |
+ tomoyo_read_unlock(idx); |
111 |
+ return error; |
112 |
+} |
113 |
+ |
114 |
+/** |
115 |
+ * tomoyo_write_chroot_policy - Write "struct tomoyo_chroot_acl" list. |
116 |
+ * |
117 |
+ * @data: String to parse. |
118 |
+ * @domain: Pointer to "struct tomoyo_domain_info". |
119 |
+ * @condition: Pointer to "struct tomoyo_condition". May be NULL. |
120 |
+ * @is_delete: True if it is a delete request. |
121 |
+ * |
122 |
+ * Returns 0 on success, negative value otherwise. |
123 |
+ */ |
124 |
+int tomoyo_write_chroot_policy(char *data, struct tomoyo_domain_info *domain, |
125 |
+ struct tomoyo_condition *condition, |
126 |
+ const bool is_delete) |
127 |
+{ |
128 |
+ struct tomoyo_chroot_acl *entry = NULL; |
129 |
+ struct tomoyo_acl_info *ptr; |
130 |
+ struct tomoyo_chroot_acl e = { |
131 |
+ .head.type = TOMOYO_TYPE_CHROOT_ACL, |
132 |
+ .head.cond = condition |
133 |
+ }; |
134 |
+ int error = is_delete ? -ENOENT : -ENOMEM; |
135 |
+ if (data[0] != '@' && !tomoyo_is_correct_path(data, 1, 0, 1)) |
136 |
+ return -EINVAL; |
137 |
+ if (!tomoyo_parse_name_union(data, &e.dir)) |
138 |
+ return error; |
139 |
+ if (!is_delete) |
140 |
+ entry = kmalloc(sizeof(e), GFP_KERNEL); |
141 |
+ mutex_lock(&tomoyo_policy_lock); |
142 |
+ list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
143 |
+ struct tomoyo_chroot_acl *acl = |
144 |
+ container_of(ptr, struct tomoyo_chroot_acl, head); |
145 |
+ if (ptr->type != TOMOYO_TYPE_CHROOT_ACL || |
146 |
+ ptr->cond != condition |
147 |
+ || memcmp(&acl->dir, &e.dir, sizeof(e.dir))) |
148 |
+ continue; |
149 |
+ ptr->is_deleted = is_delete; |
150 |
+ error = 0; |
151 |
+ break; |
152 |
+ } |
153 |
+ if (!is_delete && error && tomoyo_commit_ok(entry, &e, sizeof(e))) { |
154 |
+ tomoyo_add_domain_acl(domain, &entry->head); |
155 |
+ entry = NULL; |
156 |
+ error = 0; |
157 |
+ } |
158 |
+ mutex_unlock(&tomoyo_policy_lock); |
159 |
+ tomoyo_put_name_union(&e.dir); |
160 |
+ kfree(entry); |
161 |
+ return error; |
162 |
+} |