diff options
Diffstat (limited to 'security/tomoyo/file.c')
-rw-r--r-- | security/tomoyo/file.c | 731 |
1 files changed, 349 insertions, 382 deletions
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 9a6c58881c0a..1b24304edb7d 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -10,108 +10,64 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include "common.h" | 12 | #include "common.h" |
13 | #include "tomoyo.h" | ||
14 | #include "realpath.h" | ||
15 | |||
16 | /* | ||
17 | * tomoyo_globally_readable_file_entry is a structure which is used for holding | ||
18 | * "allow_read" entries. | ||
19 | * It has following fields. | ||
20 | * | ||
21 | * (1) "list" which is linked to tomoyo_globally_readable_list . | ||
22 | * (2) "filename" is a pathname which is allowed to open(O_RDONLY). | ||
23 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
24 | * otherwise. | ||
25 | */ | ||
26 | struct tomoyo_globally_readable_file_entry { | ||
27 | struct list_head list; | ||
28 | const struct tomoyo_path_info *filename; | ||
29 | bool is_deleted; | ||
30 | }; | ||
31 | |||
32 | /* | ||
33 | * tomoyo_pattern_entry is a structure which is used for holding | ||
34 | * "tomoyo_pattern_list" entries. | ||
35 | * It has following fields. | ||
36 | * | ||
37 | * (1) "list" which is linked to tomoyo_pattern_list . | ||
38 | * (2) "pattern" is a pathname pattern which is used for converting pathnames | ||
39 | * to pathname patterns during learning mode. | ||
40 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
41 | * otherwise. | ||
42 | */ | ||
43 | struct tomoyo_pattern_entry { | ||
44 | struct list_head list; | ||
45 | const struct tomoyo_path_info *pattern; | ||
46 | bool is_deleted; | ||
47 | }; | ||
48 | |||
49 | /* | ||
50 | * tomoyo_no_rewrite_entry is a structure which is used for holding | ||
51 | * "deny_rewrite" entries. | ||
52 | * It has following fields. | ||
53 | * | ||
54 | * (1) "list" which is linked to tomoyo_no_rewrite_list . | ||
55 | * (2) "pattern" is a pathname which is by default not permitted to modify | ||
56 | * already existing content. | ||
57 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
58 | * otherwise. | ||
59 | */ | ||
60 | struct tomoyo_no_rewrite_entry { | ||
61 | struct list_head list; | ||
62 | const struct tomoyo_path_info *pattern; | ||
63 | bool is_deleted; | ||
64 | }; | ||
65 | 13 | ||
66 | /* Keyword array for single path operations. */ | 14 | /* Keyword array for single path operations. */ |
67 | static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = { | 15 | static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { |
68 | [TOMOYO_TYPE_READ_WRITE_ACL] = "read/write", | 16 | [TOMOYO_TYPE_READ_WRITE] = "read/write", |
69 | [TOMOYO_TYPE_EXECUTE_ACL] = "execute", | 17 | [TOMOYO_TYPE_EXECUTE] = "execute", |
70 | [TOMOYO_TYPE_READ_ACL] = "read", | 18 | [TOMOYO_TYPE_READ] = "read", |
71 | [TOMOYO_TYPE_WRITE_ACL] = "write", | 19 | [TOMOYO_TYPE_WRITE] = "write", |
72 | [TOMOYO_TYPE_CREATE_ACL] = "create", | 20 | [TOMOYO_TYPE_CREATE] = "create", |
73 | [TOMOYO_TYPE_UNLINK_ACL] = "unlink", | 21 | [TOMOYO_TYPE_UNLINK] = "unlink", |
74 | [TOMOYO_TYPE_MKDIR_ACL] = "mkdir", | 22 | [TOMOYO_TYPE_MKDIR] = "mkdir", |
75 | [TOMOYO_TYPE_RMDIR_ACL] = "rmdir", | 23 | [TOMOYO_TYPE_RMDIR] = "rmdir", |
76 | [TOMOYO_TYPE_MKFIFO_ACL] = "mkfifo", | 24 | [TOMOYO_TYPE_MKFIFO] = "mkfifo", |
77 | [TOMOYO_TYPE_MKSOCK_ACL] = "mksock", | 25 | [TOMOYO_TYPE_MKSOCK] = "mksock", |
78 | [TOMOYO_TYPE_MKBLOCK_ACL] = "mkblock", | 26 | [TOMOYO_TYPE_MKBLOCK] = "mkblock", |
79 | [TOMOYO_TYPE_MKCHAR_ACL] = "mkchar", | 27 | [TOMOYO_TYPE_MKCHAR] = "mkchar", |
80 | [TOMOYO_TYPE_TRUNCATE_ACL] = "truncate", | 28 | [TOMOYO_TYPE_TRUNCATE] = "truncate", |
81 | [TOMOYO_TYPE_SYMLINK_ACL] = "symlink", | 29 | [TOMOYO_TYPE_SYMLINK] = "symlink", |
82 | [TOMOYO_TYPE_REWRITE_ACL] = "rewrite", | 30 | [TOMOYO_TYPE_REWRITE] = "rewrite", |
31 | [TOMOYO_TYPE_IOCTL] = "ioctl", | ||
32 | [TOMOYO_TYPE_CHMOD] = "chmod", | ||
33 | [TOMOYO_TYPE_CHOWN] = "chown", | ||
34 | [TOMOYO_TYPE_CHGRP] = "chgrp", | ||
35 | [TOMOYO_TYPE_CHROOT] = "chroot", | ||
36 | [TOMOYO_TYPE_MOUNT] = "mount", | ||
37 | [TOMOYO_TYPE_UMOUNT] = "unmount", | ||
83 | }; | 38 | }; |
84 | 39 | ||
85 | /* Keyword array for double path operations. */ | 40 | /* Keyword array for double path operations. */ |
86 | static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = { | 41 | static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { |
87 | [TOMOYO_TYPE_LINK_ACL] = "link", | 42 | [TOMOYO_TYPE_LINK] = "link", |
88 | [TOMOYO_TYPE_RENAME_ACL] = "rename", | 43 | [TOMOYO_TYPE_RENAME] = "rename", |
44 | [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", | ||
89 | }; | 45 | }; |
90 | 46 | ||
91 | /** | 47 | /** |
92 | * tomoyo_sp2keyword - Get the name of single path operation. | 48 | * tomoyo_path2keyword - Get the name of single path operation. |
93 | * | 49 | * |
94 | * @operation: Type of operation. | 50 | * @operation: Type of operation. |
95 | * | 51 | * |
96 | * Returns the name of single path operation. | 52 | * Returns the name of single path operation. |
97 | */ | 53 | */ |
98 | const char *tomoyo_sp2keyword(const u8 operation) | 54 | const char *tomoyo_path2keyword(const u8 operation) |
99 | { | 55 | { |
100 | return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION) | 56 | return (operation < TOMOYO_MAX_PATH_OPERATION) |
101 | ? tomoyo_sp_keyword[operation] : NULL; | 57 | ? tomoyo_path_keyword[operation] : NULL; |
102 | } | 58 | } |
103 | 59 | ||
104 | /** | 60 | /** |
105 | * tomoyo_dp2keyword - Get the name of double path operation. | 61 | * tomoyo_path22keyword - Get the name of double path operation. |
106 | * | 62 | * |
107 | * @operation: Type of operation. | 63 | * @operation: Type of operation. |
108 | * | 64 | * |
109 | * Returns the name of double path operation. | 65 | * Returns the name of double path operation. |
110 | */ | 66 | */ |
111 | const char *tomoyo_dp2keyword(const u8 operation) | 67 | const char *tomoyo_path22keyword(const u8 operation) |
112 | { | 68 | { |
113 | return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION) | 69 | return (operation < TOMOYO_MAX_PATH2_OPERATION) |
114 | ? tomoyo_dp_keyword[operation] : NULL; | 70 | ? tomoyo_path2_keyword[operation] : NULL; |
115 | } | 71 | } |
116 | 72 | ||
117 | /** | 73 | /** |
@@ -142,7 +98,8 @@ static bool tomoyo_strendswith(const char *name, const char *tail) | |||
142 | static struct tomoyo_path_info *tomoyo_get_path(struct path *path) | 98 | static struct tomoyo_path_info *tomoyo_get_path(struct path *path) |
143 | { | 99 | { |
144 | int error; | 100 | int error; |
145 | struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf)); | 101 | struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), |
102 | GFP_KERNEL); | ||
146 | 103 | ||
147 | if (!buf) | 104 | if (!buf) |
148 | return NULL; | 105 | return NULL; |
@@ -154,20 +111,17 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path) | |||
154 | tomoyo_fill_path_info(&buf->head); | 111 | tomoyo_fill_path_info(&buf->head); |
155 | return &buf->head; | 112 | return &buf->head; |
156 | } | 113 | } |
157 | tomoyo_free(buf); | 114 | kfree(buf); |
158 | return NULL; | 115 | return NULL; |
159 | } | 116 | } |
160 | 117 | ||
161 | /* Lock for domain->acl_info_list. */ | 118 | static int tomoyo_update_path2_acl(const u8 type, const char *filename1, |
162 | DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock); | 119 | const char *filename2, |
163 | 120 | struct tomoyo_domain_info *const domain, | |
164 | static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | 121 | const bool is_delete); |
165 | const char *filename2, | 122 | static int tomoyo_update_path_acl(const u8 type, const char *filename, |
166 | struct tomoyo_domain_info * | 123 | struct tomoyo_domain_info *const domain, |
167 | const domain, const bool is_delete); | 124 | const bool is_delete); |
168 | static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | ||
169 | struct tomoyo_domain_info * | ||
170 | const domain, const bool is_delete); | ||
171 | 125 | ||
172 | /* | 126 | /* |
173 | * tomoyo_globally_readable_list is used for holding list of pathnames which | 127 | * tomoyo_globally_readable_list is used for holding list of pathnames which |
@@ -194,8 +148,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
194 | * given "allow_read /lib/libc-2.5.so" to the domain which current process | 148 | * given "allow_read /lib/libc-2.5.so" to the domain which current process |
195 | * belongs to. | 149 | * belongs to. |
196 | */ | 150 | */ |
197 | static LIST_HEAD(tomoyo_globally_readable_list); | 151 | LIST_HEAD(tomoyo_globally_readable_list); |
198 | static DECLARE_RWSEM(tomoyo_globally_readable_list_lock); | ||
199 | 152 | ||
200 | /** | 153 | /** |
201 | * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. | 154 | * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. |
@@ -204,40 +157,42 @@ static DECLARE_RWSEM(tomoyo_globally_readable_list_lock); | |||
204 | * @is_delete: True if it is a delete request. | 157 | * @is_delete: True if it is a delete request. |
205 | * | 158 | * |
206 | * Returns 0 on success, negative value otherwise. | 159 | * Returns 0 on success, negative value otherwise. |
160 | * | ||
161 | * Caller holds tomoyo_read_lock(). | ||
207 | */ | 162 | */ |
208 | static int tomoyo_update_globally_readable_entry(const char *filename, | 163 | static int tomoyo_update_globally_readable_entry(const char *filename, |
209 | const bool is_delete) | 164 | const bool is_delete) |
210 | { | 165 | { |
211 | struct tomoyo_globally_readable_file_entry *new_entry; | 166 | struct tomoyo_globally_readable_file_entry *entry = NULL; |
212 | struct tomoyo_globally_readable_file_entry *ptr; | 167 | struct tomoyo_globally_readable_file_entry *ptr; |
213 | const struct tomoyo_path_info *saved_filename; | 168 | const struct tomoyo_path_info *saved_filename; |
214 | int error = -ENOMEM; | 169 | int error = is_delete ? -ENOENT : -ENOMEM; |
215 | 170 | ||
216 | if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) | 171 | if (!tomoyo_is_correct_path(filename, 1, 0, -1)) |
217 | return -EINVAL; | 172 | return -EINVAL; |
218 | saved_filename = tomoyo_save_name(filename); | 173 | saved_filename = tomoyo_get_name(filename); |
219 | if (!saved_filename) | 174 | if (!saved_filename) |
220 | return -ENOMEM; | 175 | return -ENOMEM; |
221 | down_write(&tomoyo_globally_readable_list_lock); | 176 | if (!is_delete) |
222 | list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { | 177 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
178 | mutex_lock(&tomoyo_policy_lock); | ||
179 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { | ||
223 | if (ptr->filename != saved_filename) | 180 | if (ptr->filename != saved_filename) |
224 | continue; | 181 | continue; |
225 | ptr->is_deleted = is_delete; | 182 | ptr->is_deleted = is_delete; |
226 | error = 0; | 183 | error = 0; |
227 | goto out; | 184 | break; |
228 | } | 185 | } |
229 | if (is_delete) { | 186 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
230 | error = -ENOENT; | 187 | entry->filename = saved_filename; |
231 | goto out; | 188 | saved_filename = NULL; |
189 | list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); | ||
190 | entry = NULL; | ||
191 | error = 0; | ||
232 | } | 192 | } |
233 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 193 | mutex_unlock(&tomoyo_policy_lock); |
234 | if (!new_entry) | 194 | tomoyo_put_name(saved_filename); |
235 | goto out; | 195 | kfree(entry); |
236 | new_entry->filename = saved_filename; | ||
237 | list_add_tail(&new_entry->list, &tomoyo_globally_readable_list); | ||
238 | error = 0; | ||
239 | out: | ||
240 | up_write(&tomoyo_globally_readable_list_lock); | ||
241 | return error; | 196 | return error; |
242 | } | 197 | } |
243 | 198 | ||
@@ -247,21 +202,22 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
247 | * @filename: The filename to check. | 202 | * @filename: The filename to check. |
248 | * | 203 | * |
249 | * Returns true if any domain can open @filename for reading, false otherwise. | 204 | * Returns true if any domain can open @filename for reading, false otherwise. |
205 | * | ||
206 | * Caller holds tomoyo_read_lock(). | ||
250 | */ | 207 | */ |
251 | static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * | 208 | static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * |
252 | filename) | 209 | filename) |
253 | { | 210 | { |
254 | struct tomoyo_globally_readable_file_entry *ptr; | 211 | struct tomoyo_globally_readable_file_entry *ptr; |
255 | bool found = false; | 212 | bool found = false; |
256 | down_read(&tomoyo_globally_readable_list_lock); | 213 | |
257 | list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { | 214 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { |
258 | if (!ptr->is_deleted && | 215 | if (!ptr->is_deleted && |
259 | tomoyo_path_matches_pattern(filename, ptr->filename)) { | 216 | tomoyo_path_matches_pattern(filename, ptr->filename)) { |
260 | found = true; | 217 | found = true; |
261 | break; | 218 | break; |
262 | } | 219 | } |
263 | } | 220 | } |
264 | up_read(&tomoyo_globally_readable_list_lock); | ||
265 | return found; | 221 | return found; |
266 | } | 222 | } |
267 | 223 | ||
@@ -272,6 +228,8 @@ static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * | |||
272 | * @is_delete: True if it is a delete request. | 228 | * @is_delete: True if it is a delete request. |
273 | * | 229 | * |
274 | * Returns 0 on success, negative value otherwise. | 230 | * Returns 0 on success, negative value otherwise. |
231 | * | ||
232 | * Caller holds tomoyo_read_lock(). | ||
275 | */ | 233 | */ |
276 | int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) | 234 | int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) |
277 | { | 235 | { |
@@ -284,13 +242,14 @@ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) | |||
284 | * @head: Pointer to "struct tomoyo_io_buffer". | 242 | * @head: Pointer to "struct tomoyo_io_buffer". |
285 | * | 243 | * |
286 | * Returns true on success, false otherwise. | 244 | * Returns true on success, false otherwise. |
245 | * | ||
246 | * Caller holds tomoyo_read_lock(). | ||
287 | */ | 247 | */ |
288 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) | 248 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) |
289 | { | 249 | { |
290 | struct list_head *pos; | 250 | struct list_head *pos; |
291 | bool done = true; | 251 | bool done = true; |
292 | 252 | ||
293 | down_read(&tomoyo_globally_readable_list_lock); | ||
294 | list_for_each_cookie(pos, head->read_var2, | 253 | list_for_each_cookie(pos, head->read_var2, |
295 | &tomoyo_globally_readable_list) { | 254 | &tomoyo_globally_readable_list) { |
296 | struct tomoyo_globally_readable_file_entry *ptr; | 255 | struct tomoyo_globally_readable_file_entry *ptr; |
@@ -304,7 +263,6 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) | |||
304 | if (!done) | 263 | if (!done) |
305 | break; | 264 | break; |
306 | } | 265 | } |
307 | up_read(&tomoyo_globally_readable_list_lock); | ||
308 | return done; | 266 | return done; |
309 | } | 267 | } |
310 | 268 | ||
@@ -337,8 +295,7 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) | |||
337 | * which pretends as if /proc/self/ is not a symlink; so that we can forbid | 295 | * which pretends as if /proc/self/ is not a symlink; so that we can forbid |
338 | * current process from accessing other process's information. | 296 | * current process from accessing other process's information. |
339 | */ | 297 | */ |
340 | static LIST_HEAD(tomoyo_pattern_list); | 298 | LIST_HEAD(tomoyo_pattern_list); |
341 | static DECLARE_RWSEM(tomoyo_pattern_list_lock); | ||
342 | 299 | ||
343 | /** | 300 | /** |
344 | * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. | 301 | * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. |
@@ -347,40 +304,43 @@ static DECLARE_RWSEM(tomoyo_pattern_list_lock); | |||
347 | * @is_delete: True if it is a delete request. | 304 | * @is_delete: True if it is a delete request. |
348 | * | 305 | * |
349 | * Returns 0 on success, negative value otherwise. | 306 | * Returns 0 on success, negative value otherwise. |
307 | * | ||
308 | * Caller holds tomoyo_read_lock(). | ||
350 | */ | 309 | */ |
351 | static int tomoyo_update_file_pattern_entry(const char *pattern, | 310 | static int tomoyo_update_file_pattern_entry(const char *pattern, |
352 | const bool is_delete) | 311 | const bool is_delete) |
353 | { | 312 | { |
354 | struct tomoyo_pattern_entry *new_entry; | 313 | struct tomoyo_pattern_entry *entry = NULL; |
355 | struct tomoyo_pattern_entry *ptr; | 314 | struct tomoyo_pattern_entry *ptr; |
356 | const struct tomoyo_path_info *saved_pattern; | 315 | const struct tomoyo_path_info *saved_pattern; |
357 | int error = -ENOMEM; | 316 | int error = is_delete ? -ENOENT : -ENOMEM; |
358 | 317 | ||
359 | if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__)) | 318 | saved_pattern = tomoyo_get_name(pattern); |
360 | return -EINVAL; | ||
361 | saved_pattern = tomoyo_save_name(pattern); | ||
362 | if (!saved_pattern) | 319 | if (!saved_pattern) |
363 | return -ENOMEM; | 320 | return error; |
364 | down_write(&tomoyo_pattern_list_lock); | 321 | if (!saved_pattern->is_patterned) |
365 | list_for_each_entry(ptr, &tomoyo_pattern_list, list) { | 322 | goto out; |
323 | if (!is_delete) | ||
324 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
325 | mutex_lock(&tomoyo_policy_lock); | ||
326 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { | ||
366 | if (saved_pattern != ptr->pattern) | 327 | if (saved_pattern != ptr->pattern) |
367 | continue; | 328 | continue; |
368 | ptr->is_deleted = is_delete; | 329 | ptr->is_deleted = is_delete; |
369 | error = 0; | 330 | error = 0; |
370 | goto out; | 331 | break; |
371 | } | 332 | } |
372 | if (is_delete) { | 333 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
373 | error = -ENOENT; | 334 | entry->pattern = saved_pattern; |
374 | goto out; | 335 | saved_pattern = NULL; |
336 | list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); | ||
337 | entry = NULL; | ||
338 | error = 0; | ||
375 | } | 339 | } |
376 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 340 | mutex_unlock(&tomoyo_policy_lock); |
377 | if (!new_entry) | ||
378 | goto out; | ||
379 | new_entry->pattern = saved_pattern; | ||
380 | list_add_tail(&new_entry->list, &tomoyo_pattern_list); | ||
381 | error = 0; | ||
382 | out: | 341 | out: |
383 | up_write(&tomoyo_pattern_list_lock); | 342 | kfree(entry); |
343 | tomoyo_put_name(saved_pattern); | ||
384 | return error; | 344 | return error; |
385 | } | 345 | } |
386 | 346 | ||
@@ -390,6 +350,8 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
390 | * @filename: The filename to find patterned pathname. | 350 | * @filename: The filename to find patterned pathname. |
391 | * | 351 | * |
392 | * Returns pointer to pathname pattern if matched, @filename otherwise. | 352 | * Returns pointer to pathname pattern if matched, @filename otherwise. |
353 | * | ||
354 | * Caller holds tomoyo_read_lock(). | ||
393 | */ | 355 | */ |
394 | static const struct tomoyo_path_info * | 356 | static const struct tomoyo_path_info * |
395 | tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | 357 | tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) |
@@ -397,8 +359,7 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | |||
397 | struct tomoyo_pattern_entry *ptr; | 359 | struct tomoyo_pattern_entry *ptr; |
398 | const struct tomoyo_path_info *pattern = NULL; | 360 | const struct tomoyo_path_info *pattern = NULL; |
399 | 361 | ||
400 | down_read(&tomoyo_pattern_list_lock); | 362 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { |
401 | list_for_each_entry(ptr, &tomoyo_pattern_list, list) { | ||
402 | if (ptr->is_deleted) | 363 | if (ptr->is_deleted) |
403 | continue; | 364 | continue; |
404 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | 365 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) |
@@ -411,7 +372,6 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | |||
411 | break; | 372 | break; |
412 | } | 373 | } |
413 | } | 374 | } |
414 | up_read(&tomoyo_pattern_list_lock); | ||
415 | if (pattern) | 375 | if (pattern) |
416 | filename = pattern; | 376 | filename = pattern; |
417 | return filename; | 377 | return filename; |
@@ -424,6 +384,8 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | |||
424 | * @is_delete: True if it is a delete request. | 384 | * @is_delete: True if it is a delete request. |
425 | * | 385 | * |
426 | * Returns 0 on success, negative value otherwise. | 386 | * Returns 0 on success, negative value otherwise. |
387 | * | ||
388 | * Caller holds tomoyo_read_lock(). | ||
427 | */ | 389 | */ |
428 | int tomoyo_write_pattern_policy(char *data, const bool is_delete) | 390 | int tomoyo_write_pattern_policy(char *data, const bool is_delete) |
429 | { | 391 | { |
@@ -436,13 +398,14 @@ int tomoyo_write_pattern_policy(char *data, const bool is_delete) | |||
436 | * @head: Pointer to "struct tomoyo_io_buffer". | 398 | * @head: Pointer to "struct tomoyo_io_buffer". |
437 | * | 399 | * |
438 | * Returns true on success, false otherwise. | 400 | * Returns true on success, false otherwise. |
401 | * | ||
402 | * Caller holds tomoyo_read_lock(). | ||
439 | */ | 403 | */ |
440 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) | 404 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) |
441 | { | 405 | { |
442 | struct list_head *pos; | 406 | struct list_head *pos; |
443 | bool done = true; | 407 | bool done = true; |
444 | 408 | ||
445 | down_read(&tomoyo_pattern_list_lock); | ||
446 | list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) { | 409 | list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) { |
447 | struct tomoyo_pattern_entry *ptr; | 410 | struct tomoyo_pattern_entry *ptr; |
448 | ptr = list_entry(pos, struct tomoyo_pattern_entry, list); | 411 | ptr = list_entry(pos, struct tomoyo_pattern_entry, list); |
@@ -453,7 +416,6 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) | |||
453 | if (!done) | 416 | if (!done) |
454 | break; | 417 | break; |
455 | } | 418 | } |
456 | up_read(&tomoyo_pattern_list_lock); | ||
457 | return done; | 419 | return done; |
458 | } | 420 | } |
459 | 421 | ||
@@ -486,8 +448,7 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) | |||
486 | * " (deleted)" suffix if the file is already unlink()ed; so that we don't | 448 | * " (deleted)" suffix if the file is already unlink()ed; so that we don't |
487 | * need to worry whether the file is already unlink()ed or not. | 449 | * need to worry whether the file is already unlink()ed or not. |
488 | */ | 450 | */ |
489 | static LIST_HEAD(tomoyo_no_rewrite_list); | 451 | LIST_HEAD(tomoyo_no_rewrite_list); |
490 | static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock); | ||
491 | 452 | ||
492 | /** | 453 | /** |
493 | * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. | 454 | * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. |
@@ -496,39 +457,42 @@ static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock); | |||
496 | * @is_delete: True if it is a delete request. | 457 | * @is_delete: True if it is a delete request. |
497 | * | 458 | * |
498 | * Returns 0 on success, negative value otherwise. | 459 | * Returns 0 on success, negative value otherwise. |
460 | * | ||
461 | * Caller holds tomoyo_read_lock(). | ||
499 | */ | 462 | */ |
500 | static int tomoyo_update_no_rewrite_entry(const char *pattern, | 463 | static int tomoyo_update_no_rewrite_entry(const char *pattern, |
501 | const bool is_delete) | 464 | const bool is_delete) |
502 | { | 465 | { |
503 | struct tomoyo_no_rewrite_entry *new_entry, *ptr; | 466 | struct tomoyo_no_rewrite_entry *entry = NULL; |
467 | struct tomoyo_no_rewrite_entry *ptr; | ||
504 | const struct tomoyo_path_info *saved_pattern; | 468 | const struct tomoyo_path_info *saved_pattern; |
505 | int error = -ENOMEM; | 469 | int error = is_delete ? -ENOENT : -ENOMEM; |
506 | 470 | ||
507 | if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) | 471 | if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) |
508 | return -EINVAL; | 472 | return -EINVAL; |
509 | saved_pattern = tomoyo_save_name(pattern); | 473 | saved_pattern = tomoyo_get_name(pattern); |
510 | if (!saved_pattern) | 474 | if (!saved_pattern) |
511 | return -ENOMEM; | 475 | return error; |
512 | down_write(&tomoyo_no_rewrite_list_lock); | 476 | if (!is_delete) |
513 | list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) { | 477 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
478 | mutex_lock(&tomoyo_policy_lock); | ||
479 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { | ||
514 | if (ptr->pattern != saved_pattern) | 480 | if (ptr->pattern != saved_pattern) |
515 | continue; | 481 | continue; |
516 | ptr->is_deleted = is_delete; | 482 | ptr->is_deleted = is_delete; |
517 | error = 0; | 483 | error = 0; |
518 | goto out; | 484 | break; |
519 | } | 485 | } |
520 | if (is_delete) { | 486 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
521 | error = -ENOENT; | 487 | entry->pattern = saved_pattern; |
522 | goto out; | 488 | saved_pattern = NULL; |
489 | list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); | ||
490 | entry = NULL; | ||
491 | error = 0; | ||
523 | } | 492 | } |
524 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 493 | mutex_unlock(&tomoyo_policy_lock); |
525 | if (!new_entry) | 494 | tomoyo_put_name(saved_pattern); |
526 | goto out; | 495 | kfree(entry); |
527 | new_entry->pattern = saved_pattern; | ||
528 | list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list); | ||
529 | error = 0; | ||
530 | out: | ||
531 | up_write(&tomoyo_no_rewrite_list_lock); | ||
532 | return error; | 496 | return error; |
533 | } | 497 | } |
534 | 498 | ||
@@ -539,14 +503,15 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
539 | * | 503 | * |
540 | * Returns true if @filename is specified by "deny_rewrite" directive, | 504 | * Returns true if @filename is specified by "deny_rewrite" directive, |
541 | * false otherwise. | 505 | * false otherwise. |
506 | * | ||
507 | * Caller holds tomoyo_read_lock(). | ||
542 | */ | 508 | */ |
543 | static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) | 509 | static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) |
544 | { | 510 | { |
545 | struct tomoyo_no_rewrite_entry *ptr; | 511 | struct tomoyo_no_rewrite_entry *ptr; |
546 | bool found = false; | 512 | bool found = false; |
547 | 513 | ||
548 | down_read(&tomoyo_no_rewrite_list_lock); | 514 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { |
549 | list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) { | ||
550 | if (ptr->is_deleted) | 515 | if (ptr->is_deleted) |
551 | continue; | 516 | continue; |
552 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | 517 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) |
@@ -554,7 +519,6 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) | |||
554 | found = true; | 519 | found = true; |
555 | break; | 520 | break; |
556 | } | 521 | } |
557 | up_read(&tomoyo_no_rewrite_list_lock); | ||
558 | return found; | 522 | return found; |
559 | } | 523 | } |
560 | 524 | ||
@@ -565,6 +529,8 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) | |||
565 | * @is_delete: True if it is a delete request. | 529 | * @is_delete: True if it is a delete request. |
566 | * | 530 | * |
567 | * Returns 0 on success, negative value otherwise. | 531 | * Returns 0 on success, negative value otherwise. |
532 | * | ||
533 | * Caller holds tomoyo_read_lock(). | ||
568 | */ | 534 | */ |
569 | int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) | 535 | int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) |
570 | { | 536 | { |
@@ -577,13 +543,14 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) | |||
577 | * @head: Pointer to "struct tomoyo_io_buffer". | 543 | * @head: Pointer to "struct tomoyo_io_buffer". |
578 | * | 544 | * |
579 | * Returns true on success, false otherwise. | 545 | * Returns true on success, false otherwise. |
546 | * | ||
547 | * Caller holds tomoyo_read_lock(). | ||
580 | */ | 548 | */ |
581 | bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | 549 | bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) |
582 | { | 550 | { |
583 | struct list_head *pos; | 551 | struct list_head *pos; |
584 | bool done = true; | 552 | bool done = true; |
585 | 553 | ||
586 | down_read(&tomoyo_no_rewrite_list_lock); | ||
587 | list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) { | 554 | list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) { |
588 | struct tomoyo_no_rewrite_entry *ptr; | 555 | struct tomoyo_no_rewrite_entry *ptr; |
589 | ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); | 556 | ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); |
@@ -594,7 +561,6 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | |||
594 | if (!done) | 561 | if (!done) |
595 | break; | 562 | break; |
596 | } | 563 | } |
597 | up_read(&tomoyo_no_rewrite_list_lock); | ||
598 | return done; | 564 | return done; |
599 | } | 565 | } |
600 | 566 | ||
@@ -612,6 +578,8 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | |||
612 | * Current policy syntax uses "allow_read/write" instead of "6", | 578 | * Current policy syntax uses "allow_read/write" instead of "6", |
613 | * "allow_read" instead of "4", "allow_write" instead of "2", | 579 | * "allow_read" instead of "4", "allow_write" instead of "2", |
614 | * "allow_execute" instead of "1". | 580 | * "allow_execute" instead of "1". |
581 | * | ||
582 | * Caller holds tomoyo_read_lock(). | ||
615 | */ | 583 | */ |
616 | static int tomoyo_update_file_acl(const char *filename, u8 perm, | 584 | static int tomoyo_update_file_acl(const char *filename, u8 perm, |
617 | struct tomoyo_domain_info * const domain, | 585 | struct tomoyo_domain_info * const domain, |
@@ -629,19 +597,19 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm, | |||
629 | */ | 597 | */ |
630 | return 0; | 598 | return 0; |
631 | if (perm & 4) | 599 | if (perm & 4) |
632 | tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename, | 600 | tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain, |
633 | domain, is_delete); | 601 | is_delete); |
634 | if (perm & 2) | 602 | if (perm & 2) |
635 | tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename, | 603 | tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain, |
636 | domain, is_delete); | 604 | is_delete); |
637 | if (perm & 1) | 605 | if (perm & 1) |
638 | tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL, | 606 | tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain, |
639 | filename, domain, is_delete); | 607 | is_delete); |
640 | return 0; | 608 | return 0; |
641 | } | 609 | } |
642 | 610 | ||
643 | /** | 611 | /** |
644 | * tomoyo_check_single_path_acl2 - Check permission for single path operation. | 612 | * tomoyo_path_acl2 - Check permission for single path operation. |
645 | * | 613 | * |
646 | * @domain: Pointer to "struct tomoyo_domain_info". | 614 | * @domain: Pointer to "struct tomoyo_domain_info". |
647 | * @filename: Filename to check. | 615 | * @filename: Filename to check. |
@@ -649,26 +617,28 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm, | |||
649 | * @may_use_pattern: True if patterned ACL is permitted. | 617 | * @may_use_pattern: True if patterned ACL is permitted. |
650 | * | 618 | * |
651 | * Returns 0 on success, -EPERM otherwise. | 619 | * Returns 0 on success, -EPERM otherwise. |
620 | * | ||
621 | * Caller holds tomoyo_read_lock(). | ||
652 | */ | 622 | */ |
653 | static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | 623 | static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain, |
654 | domain, | 624 | const struct tomoyo_path_info *filename, |
655 | const struct tomoyo_path_info * | 625 | const u32 perm, const bool may_use_pattern) |
656 | filename, | ||
657 | const u16 perm, | ||
658 | const bool may_use_pattern) | ||
659 | { | 626 | { |
660 | struct tomoyo_acl_info *ptr; | 627 | struct tomoyo_acl_info *ptr; |
661 | int error = -EPERM; | 628 | int error = -EPERM; |
662 | 629 | ||
663 | down_read(&tomoyo_domain_acl_info_list_lock); | 630 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
664 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 631 | struct tomoyo_path_acl *acl; |
665 | struct tomoyo_single_path_acl_record *acl; | 632 | if (ptr->type != TOMOYO_TYPE_PATH_ACL) |
666 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | ||
667 | continue; | ||
668 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | ||
669 | head); | ||
670 | if (!(acl->perm & perm)) | ||
671 | continue; | 633 | continue; |
634 | acl = container_of(ptr, struct tomoyo_path_acl, head); | ||
635 | if (perm <= 0xFFFF) { | ||
636 | if (!(acl->perm & perm)) | ||
637 | continue; | ||
638 | } else { | ||
639 | if (!(acl->perm_high & (perm >> 16))) | ||
640 | continue; | ||
641 | } | ||
672 | if (may_use_pattern || !acl->filename->is_patterned) { | 642 | if (may_use_pattern || !acl->filename->is_patterned) { |
673 | if (!tomoyo_path_matches_pattern(filename, | 643 | if (!tomoyo_path_matches_pattern(filename, |
674 | acl->filename)) | 644 | acl->filename)) |
@@ -679,7 +649,6 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | |||
679 | error = 0; | 649 | error = 0; |
680 | break; | 650 | break; |
681 | } | 651 | } |
682 | up_read(&tomoyo_domain_acl_info_list_lock); | ||
683 | return error; | 652 | return error; |
684 | } | 653 | } |
685 | 654 | ||
@@ -691,27 +660,28 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | |||
691 | * @operation: Mode ("read" or "write" or "read/write" or "execute"). | 660 | * @operation: Mode ("read" or "write" or "read/write" or "execute"). |
692 | * | 661 | * |
693 | * Returns 0 on success, -EPERM otherwise. | 662 | * Returns 0 on success, -EPERM otherwise. |
663 | * | ||
664 | * Caller holds tomoyo_read_lock(). | ||
694 | */ | 665 | */ |
695 | static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, | 666 | static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, |
696 | const struct tomoyo_path_info *filename, | 667 | const struct tomoyo_path_info *filename, |
697 | const u8 operation) | 668 | const u8 operation) |
698 | { | 669 | { |
699 | u16 perm = 0; | 670 | u32 perm = 0; |
700 | 671 | ||
701 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) | 672 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) |
702 | return 0; | 673 | return 0; |
703 | if (operation == 6) | 674 | if (operation == 6) |
704 | perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL; | 675 | perm = 1 << TOMOYO_TYPE_READ_WRITE; |
705 | else if (operation == 4) | 676 | else if (operation == 4) |
706 | perm = 1 << TOMOYO_TYPE_READ_ACL; | 677 | perm = 1 << TOMOYO_TYPE_READ; |
707 | else if (operation == 2) | 678 | else if (operation == 2) |
708 | perm = 1 << TOMOYO_TYPE_WRITE_ACL; | 679 | perm = 1 << TOMOYO_TYPE_WRITE; |
709 | else if (operation == 1) | 680 | else if (operation == 1) |
710 | perm = 1 << TOMOYO_TYPE_EXECUTE_ACL; | 681 | perm = 1 << TOMOYO_TYPE_EXECUTE; |
711 | else | 682 | else |
712 | BUG(); | 683 | BUG(); |
713 | return tomoyo_check_single_path_acl2(domain, filename, perm, | 684 | return tomoyo_path_acl2(domain, filename, perm, operation != 1); |
714 | operation != 1); | ||
715 | } | 685 | } |
716 | 686 | ||
717 | /** | 687 | /** |
@@ -724,6 +694,8 @@ static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, | |||
724 | * @mode: Access control mode. | 694 | * @mode: Access control mode. |
725 | * | 695 | * |
726 | * Returns 0 on success, negative value otherwise. | 696 | * Returns 0 on success, negative value otherwise. |
697 | * | ||
698 | * Caller holds tomoyo_read_lock(). | ||
727 | */ | 699 | */ |
728 | static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, | 700 | static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, |
729 | const struct tomoyo_path_info *filename, | 701 | const struct tomoyo_path_info *filename, |
@@ -737,18 +709,17 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, | |||
737 | if (!filename) | 709 | if (!filename) |
738 | return 0; | 710 | return 0; |
739 | error = tomoyo_check_file_acl(domain, filename, perm); | 711 | error = tomoyo_check_file_acl(domain, filename, perm); |
740 | if (error && perm == 4 && | 712 | if (error && perm == 4 && !domain->ignore_global_allow_read |
741 | (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0 | ||
742 | && tomoyo_is_globally_readable_file(filename)) | 713 | && tomoyo_is_globally_readable_file(filename)) |
743 | error = 0; | 714 | error = 0; |
744 | if (perm == 6) | 715 | if (perm == 6) |
745 | msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL); | 716 | msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE); |
746 | else if (perm == 4) | 717 | else if (perm == 4) |
747 | msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL); | 718 | msg = tomoyo_path2keyword(TOMOYO_TYPE_READ); |
748 | else if (perm == 2) | 719 | else if (perm == 2) |
749 | msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL); | 720 | msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE); |
750 | else if (perm == 1) | 721 | else if (perm == 1) |
751 | msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL); | 722 | msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE); |
752 | else | 723 | else |
753 | BUG(); | 724 | BUG(); |
754 | if (!error) | 725 | if (!error) |
@@ -777,6 +748,8 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, | |||
777 | * @is_delete: True if it is a delete request. | 748 | * @is_delete: True if it is a delete request. |
778 | * | 749 | * |
779 | * Returns 0 on success, negative value otherwise. | 750 | * Returns 0 on success, negative value otherwise. |
751 | * | ||
752 | * Caller holds tomoyo_read_lock(). | ||
780 | */ | 753 | */ |
781 | int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, | 754 | int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, |
782 | const bool is_delete) | 755 | const bool is_delete) |
@@ -795,28 +768,28 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, | |||
795 | if (strncmp(data, "allow_", 6)) | 768 | if (strncmp(data, "allow_", 6)) |
796 | goto out; | 769 | goto out; |
797 | data += 6; | 770 | data += 6; |
798 | for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) { | 771 | for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { |
799 | if (strcmp(data, tomoyo_sp_keyword[type])) | 772 | if (strcmp(data, tomoyo_path_keyword[type])) |
800 | continue; | 773 | continue; |
801 | return tomoyo_update_single_path_acl(type, filename, | 774 | return tomoyo_update_path_acl(type, filename, domain, |
802 | domain, is_delete); | 775 | is_delete); |
803 | } | 776 | } |
804 | filename2 = strchr(filename, ' '); | 777 | filename2 = strchr(filename, ' '); |
805 | if (!filename2) | 778 | if (!filename2) |
806 | goto out; | 779 | goto out; |
807 | *filename2++ = '\0'; | 780 | *filename2++ = '\0'; |
808 | for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) { | 781 | for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { |
809 | if (strcmp(data, tomoyo_dp_keyword[type])) | 782 | if (strcmp(data, tomoyo_path2_keyword[type])) |
810 | continue; | 783 | continue; |
811 | return tomoyo_update_double_path_acl(type, filename, filename2, | 784 | return tomoyo_update_path2_acl(type, filename, filename2, |
812 | domain, is_delete); | 785 | domain, is_delete); |
813 | } | 786 | } |
814 | out: | 787 | out: |
815 | return -EINVAL; | 788 | return -EINVAL; |
816 | } | 789 | } |
817 | 790 | ||
818 | /** | 791 | /** |
819 | * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list. | 792 | * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. |
820 | * | 793 | * |
821 | * @type: Type of operation. | 794 | * @type: Type of operation. |
822 | * @filename: Filename. | 795 | * @filename: Filename. |
@@ -824,85 +797,82 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, | |||
824 | * @is_delete: True if it is a delete request. | 797 | * @is_delete: True if it is a delete request. |
825 | * | 798 | * |
826 | * Returns 0 on success, negative value otherwise. | 799 | * Returns 0 on success, negative value otherwise. |
800 | * | ||
801 | * Caller holds tomoyo_read_lock(). | ||
827 | */ | 802 | */ |
828 | static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | 803 | static int tomoyo_update_path_acl(const u8 type, const char *filename, |
829 | struct tomoyo_domain_info * | 804 | struct tomoyo_domain_info *const domain, |
830 | const domain, const bool is_delete) | 805 | const bool is_delete) |
831 | { | 806 | { |
832 | static const u16 rw_mask = | 807 | static const u32 rw_mask = |
833 | (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL); | 808 | (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); |
834 | const struct tomoyo_path_info *saved_filename; | 809 | const struct tomoyo_path_info *saved_filename; |
835 | struct tomoyo_acl_info *ptr; | 810 | struct tomoyo_acl_info *ptr; |
836 | struct tomoyo_single_path_acl_record *acl; | 811 | struct tomoyo_path_acl *entry = NULL; |
837 | int error = -ENOMEM; | 812 | int error = is_delete ? -ENOENT : -ENOMEM; |
838 | const u16 perm = 1 << type; | 813 | const u32 perm = 1 << type; |
839 | 814 | ||
840 | if (!domain) | 815 | if (!domain) |
841 | return -EINVAL; | 816 | return -EINVAL; |
842 | if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__)) | 817 | if (!tomoyo_is_correct_path(filename, 0, 0, 0)) |
843 | return -EINVAL; | 818 | return -EINVAL; |
844 | saved_filename = tomoyo_save_name(filename); | 819 | saved_filename = tomoyo_get_name(filename); |
845 | if (!saved_filename) | 820 | if (!saved_filename) |
846 | return -ENOMEM; | 821 | return -ENOMEM; |
847 | down_write(&tomoyo_domain_acl_info_list_lock); | 822 | if (!is_delete) |
848 | if (is_delete) | 823 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
849 | goto delete; | 824 | mutex_lock(&tomoyo_policy_lock); |
850 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 825 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
851 | if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | 826 | struct tomoyo_path_acl *acl = |
827 | container_of(ptr, struct tomoyo_path_acl, head); | ||
828 | if (ptr->type != TOMOYO_TYPE_PATH_ACL) | ||
852 | continue; | 829 | continue; |
853 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | ||
854 | head); | ||
855 | if (acl->filename != saved_filename) | 830 | if (acl->filename != saved_filename) |
856 | continue; | 831 | continue; |
857 | /* Special case. Clear all bits if marked as deleted. */ | 832 | if (is_delete) { |
858 | if (ptr->type & TOMOYO_ACL_DELETED) | 833 | if (perm <= 0xFFFF) |
859 | acl->perm = 0; | 834 | acl->perm &= ~perm; |
860 | acl->perm |= perm; | 835 | else |
861 | if ((acl->perm & rw_mask) == rw_mask) | 836 | acl->perm_high &= ~(perm >> 16); |
862 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; | 837 | if ((acl->perm & rw_mask) != rw_mask) |
863 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) | 838 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); |
864 | acl->perm |= rw_mask; | 839 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) |
865 | ptr->type &= ~TOMOYO_ACL_DELETED; | 840 | acl->perm &= ~rw_mask; |
841 | } else { | ||
842 | if (perm <= 0xFFFF) | ||
843 | acl->perm |= perm; | ||
844 | else | ||
845 | acl->perm_high |= (perm >> 16); | ||
846 | if ((acl->perm & rw_mask) == rw_mask) | ||
847 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; | ||
848 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) | ||
849 | acl->perm |= rw_mask; | ||
850 | } | ||
866 | error = 0; | 851 | error = 0; |
867 | goto out; | 852 | break; |
868 | } | 853 | } |
869 | /* Not found. Append it to the tail. */ | 854 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
870 | acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL); | 855 | entry->head.type = TOMOYO_TYPE_PATH_ACL; |
871 | if (!acl) | 856 | if (perm <= 0xFFFF) |
872 | goto out; | 857 | entry->perm = perm; |
873 | acl->perm = perm; | 858 | else |
874 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) | 859 | entry->perm_high = (perm >> 16); |
875 | acl->perm |= rw_mask; | 860 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE)) |
876 | acl->filename = saved_filename; | 861 | entry->perm |= rw_mask; |
877 | list_add_tail(&acl->head.list, &domain->acl_info_list); | 862 | entry->filename = saved_filename; |
878 | error = 0; | 863 | saved_filename = NULL; |
879 | goto out; | 864 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); |
880 | delete: | 865 | entry = NULL; |
881 | error = -ENOENT; | ||
882 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | ||
883 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | ||
884 | continue; | ||
885 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | ||
886 | head); | ||
887 | if (acl->filename != saved_filename) | ||
888 | continue; | ||
889 | acl->perm &= ~perm; | ||
890 | if ((acl->perm & rw_mask) != rw_mask) | ||
891 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); | ||
892 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) | ||
893 | acl->perm &= ~rw_mask; | ||
894 | if (!acl->perm) | ||
895 | ptr->type |= TOMOYO_ACL_DELETED; | ||
896 | error = 0; | 866 | error = 0; |
897 | break; | ||
898 | } | 867 | } |
899 | out: | 868 | mutex_unlock(&tomoyo_policy_lock); |
900 | up_write(&tomoyo_domain_acl_info_list_lock); | 869 | kfree(entry); |
870 | tomoyo_put_name(saved_filename); | ||
901 | return error; | 871 | return error; |
902 | } | 872 | } |
903 | 873 | ||
904 | /** | 874 | /** |
905 | * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list. | 875 | * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. |
906 | * | 876 | * |
907 | * @type: Type of operation. | 877 | * @type: Type of operation. |
908 | * @filename1: First filename. | 878 | * @filename1: First filename. |
@@ -911,98 +881,88 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
911 | * @is_delete: True if it is a delete request. | 881 | * @is_delete: True if it is a delete request. |
912 | * | 882 | * |
913 | * Returns 0 on success, negative value otherwise. | 883 | * Returns 0 on success, negative value otherwise. |
884 | * | ||
885 | * Caller holds tomoyo_read_lock(). | ||
914 | */ | 886 | */ |
915 | static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | 887 | static int tomoyo_update_path2_acl(const u8 type, const char *filename1, |
916 | const char *filename2, | 888 | const char *filename2, |
917 | struct tomoyo_domain_info * | 889 | struct tomoyo_domain_info *const domain, |
918 | const domain, const bool is_delete) | 890 | const bool is_delete) |
919 | { | 891 | { |
920 | const struct tomoyo_path_info *saved_filename1; | 892 | const struct tomoyo_path_info *saved_filename1; |
921 | const struct tomoyo_path_info *saved_filename2; | 893 | const struct tomoyo_path_info *saved_filename2; |
922 | struct tomoyo_acl_info *ptr; | 894 | struct tomoyo_acl_info *ptr; |
923 | struct tomoyo_double_path_acl_record *acl; | 895 | struct tomoyo_path2_acl *entry = NULL; |
924 | int error = -ENOMEM; | 896 | int error = is_delete ? -ENOENT : -ENOMEM; |
925 | const u8 perm = 1 << type; | 897 | const u8 perm = 1 << type; |
926 | 898 | ||
927 | if (!domain) | 899 | if (!domain) |
928 | return -EINVAL; | 900 | return -EINVAL; |
929 | if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) || | 901 | if (!tomoyo_is_correct_path(filename1, 0, 0, 0) || |
930 | !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__)) | 902 | !tomoyo_is_correct_path(filename2, 0, 0, 0)) |
931 | return -EINVAL; | 903 | return -EINVAL; |
932 | saved_filename1 = tomoyo_save_name(filename1); | 904 | saved_filename1 = tomoyo_get_name(filename1); |
933 | saved_filename2 = tomoyo_save_name(filename2); | 905 | saved_filename2 = tomoyo_get_name(filename2); |
934 | if (!saved_filename1 || !saved_filename2) | 906 | if (!saved_filename1 || !saved_filename2) |
935 | return -ENOMEM; | ||
936 | down_write(&tomoyo_domain_acl_info_list_lock); | ||
937 | if (is_delete) | ||
938 | goto delete; | ||
939 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | ||
940 | if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | ||
941 | continue; | ||
942 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | ||
943 | head); | ||
944 | if (acl->filename1 != saved_filename1 || | ||
945 | acl->filename2 != saved_filename2) | ||
946 | continue; | ||
947 | /* Special case. Clear all bits if marked as deleted. */ | ||
948 | if (ptr->type & TOMOYO_ACL_DELETED) | ||
949 | acl->perm = 0; | ||
950 | acl->perm |= perm; | ||
951 | ptr->type &= ~TOMOYO_ACL_DELETED; | ||
952 | error = 0; | ||
953 | goto out; | 907 | goto out; |
954 | } | 908 | if (!is_delete) |
955 | /* Not found. Append it to the tail. */ | 909 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
956 | acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL); | 910 | mutex_lock(&tomoyo_policy_lock); |
957 | if (!acl) | 911 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
958 | goto out; | 912 | struct tomoyo_path2_acl *acl = |
959 | acl->perm = perm; | 913 | container_of(ptr, struct tomoyo_path2_acl, head); |
960 | acl->filename1 = saved_filename1; | 914 | if (ptr->type != TOMOYO_TYPE_PATH2_ACL) |
961 | acl->filename2 = saved_filename2; | ||
962 | list_add_tail(&acl->head.list, &domain->acl_info_list); | ||
963 | error = 0; | ||
964 | goto out; | ||
965 | delete: | ||
966 | error = -ENOENT; | ||
967 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | ||
968 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | ||
969 | continue; | 915 | continue; |
970 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | ||
971 | head); | ||
972 | if (acl->filename1 != saved_filename1 || | 916 | if (acl->filename1 != saved_filename1 || |
973 | acl->filename2 != saved_filename2) | 917 | acl->filename2 != saved_filename2) |
974 | continue; | 918 | continue; |
975 | acl->perm &= ~perm; | 919 | if (is_delete) |
976 | if (!acl->perm) | 920 | acl->perm &= ~perm; |
977 | ptr->type |= TOMOYO_ACL_DELETED; | 921 | else |
922 | acl->perm |= perm; | ||
978 | error = 0; | 923 | error = 0; |
979 | break; | 924 | break; |
980 | } | 925 | } |
926 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | ||
927 | entry->head.type = TOMOYO_TYPE_PATH2_ACL; | ||
928 | entry->perm = perm; | ||
929 | entry->filename1 = saved_filename1; | ||
930 | saved_filename1 = NULL; | ||
931 | entry->filename2 = saved_filename2; | ||
932 | saved_filename2 = NULL; | ||
933 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); | ||
934 | entry = NULL; | ||
935 | error = 0; | ||
936 | } | ||
937 | mutex_unlock(&tomoyo_policy_lock); | ||
981 | out: | 938 | out: |
982 | up_write(&tomoyo_domain_acl_info_list_lock); | 939 | tomoyo_put_name(saved_filename1); |
940 | tomoyo_put_name(saved_filename2); | ||
941 | kfree(entry); | ||
983 | return error; | 942 | return error; |
984 | } | 943 | } |
985 | 944 | ||
986 | /** | 945 | /** |
987 | * tomoyo_check_single_path_acl - Check permission for single path operation. | 946 | * tomoyo_path_acl - Check permission for single path operation. |
988 | * | 947 | * |
989 | * @domain: Pointer to "struct tomoyo_domain_info". | 948 | * @domain: Pointer to "struct tomoyo_domain_info". |
990 | * @type: Type of operation. | 949 | * @type: Type of operation. |
991 | * @filename: Filename to check. | 950 | * @filename: Filename to check. |
992 | * | 951 | * |
993 | * Returns 0 on success, negative value otherwise. | 952 | * Returns 0 on success, negative value otherwise. |
953 | * | ||
954 | * Caller holds tomoyo_read_lock(). | ||
994 | */ | 955 | */ |
995 | static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, | 956 | static int tomoyo_path_acl(struct tomoyo_domain_info *domain, const u8 type, |
996 | const u8 type, | 957 | const struct tomoyo_path_info *filename) |
997 | const struct tomoyo_path_info *filename) | ||
998 | { | 958 | { |
999 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) | 959 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) |
1000 | return 0; | 960 | return 0; |
1001 | return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1); | 961 | return tomoyo_path_acl2(domain, filename, 1 << type, 1); |
1002 | } | 962 | } |
1003 | 963 | ||
1004 | /** | 964 | /** |
1005 | * tomoyo_check_double_path_acl - Check permission for double path operation. | 965 | * tomoyo_path2_acl - Check permission for double path operation. |
1006 | * | 966 | * |
1007 | * @domain: Pointer to "struct tomoyo_domain_info". | 967 | * @domain: Pointer to "struct tomoyo_domain_info". |
1008 | * @type: Type of operation. | 968 | * @type: Type of operation. |
@@ -1010,13 +970,13 @@ static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, | |||
1010 | * @filename2: Second filename to check. | 970 | * @filename2: Second filename to check. |
1011 | * | 971 | * |
1012 | * Returns 0 on success, -EPERM otherwise. | 972 | * Returns 0 on success, -EPERM otherwise. |
973 | * | ||
974 | * Caller holds tomoyo_read_lock(). | ||
1013 | */ | 975 | */ |
1014 | static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | 976 | static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain, |
1015 | const u8 type, | 977 | const u8 type, |
1016 | const struct tomoyo_path_info * | 978 | const struct tomoyo_path_info *filename1, |
1017 | filename1, | 979 | const struct tomoyo_path_info *filename2) |
1018 | const struct tomoyo_path_info * | ||
1019 | filename2) | ||
1020 | { | 980 | { |
1021 | struct tomoyo_acl_info *ptr; | 981 | struct tomoyo_acl_info *ptr; |
1022 | const u8 perm = 1 << type; | 982 | const u8 perm = 1 << type; |
@@ -1024,13 +984,11 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | |||
1024 | 984 | ||
1025 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) | 985 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) |
1026 | return 0; | 986 | return 0; |
1027 | down_read(&tomoyo_domain_acl_info_list_lock); | 987 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
1028 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 988 | struct tomoyo_path2_acl *acl; |
1029 | struct tomoyo_double_path_acl_record *acl; | 989 | if (ptr->type != TOMOYO_TYPE_PATH2_ACL) |
1030 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | ||
1031 | continue; | 990 | continue; |
1032 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | 991 | acl = container_of(ptr, struct tomoyo_path2_acl, head); |
1033 | head); | ||
1034 | if (!(acl->perm & perm)) | 992 | if (!(acl->perm & perm)) |
1035 | continue; | 993 | continue; |
1036 | if (!tomoyo_path_matches_pattern(filename1, acl->filename1)) | 994 | if (!tomoyo_path_matches_pattern(filename1, acl->filename1)) |
@@ -1040,12 +998,11 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | |||
1040 | error = 0; | 998 | error = 0; |
1041 | break; | 999 | break; |
1042 | } | 1000 | } |
1043 | up_read(&tomoyo_domain_acl_info_list_lock); | ||
1044 | return error; | 1001 | return error; |
1045 | } | 1002 | } |
1046 | 1003 | ||
1047 | /** | 1004 | /** |
1048 | * tomoyo_check_single_path_permission2 - Check permission for single path operation. | 1005 | * tomoyo_path_permission2 - Check permission for single path operation. |
1049 | * | 1006 | * |
1050 | * @domain: Pointer to "struct tomoyo_domain_info". | 1007 | * @domain: Pointer to "struct tomoyo_domain_info". |
1051 | * @operation: Type of operation. | 1008 | * @operation: Type of operation. |
@@ -1053,11 +1010,13 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | |||
1053 | * @mode: Access control mode. | 1010 | * @mode: Access control mode. |
1054 | * | 1011 | * |
1055 | * Returns 0 on success, negative value otherwise. | 1012 | * Returns 0 on success, negative value otherwise. |
1013 | * | ||
1014 | * Caller holds tomoyo_read_lock(). | ||
1056 | */ | 1015 | */ |
1057 | static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | 1016 | static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain, |
1058 | const domain, u8 operation, | 1017 | u8 operation, |
1059 | const struct tomoyo_path_info * | 1018 | const struct tomoyo_path_info *filename, |
1060 | filename, const u8 mode) | 1019 | const u8 mode) |
1061 | { | 1020 | { |
1062 | const char *msg; | 1021 | const char *msg; |
1063 | int error; | 1022 | int error; |
@@ -1066,8 +1025,8 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | |||
1066 | if (!mode) | 1025 | if (!mode) |
1067 | return 0; | 1026 | return 0; |
1068 | next: | 1027 | next: |
1069 | error = tomoyo_check_single_path_acl(domain, operation, filename); | 1028 | error = tomoyo_path_acl(domain, operation, filename); |
1070 | msg = tomoyo_sp2keyword(operation); | 1029 | msg = tomoyo_path2keyword(operation); |
1071 | if (!error) | 1030 | if (!error) |
1072 | goto ok; | 1031 | goto ok; |
1073 | if (tomoyo_verbose_mode(domain)) | 1032 | if (tomoyo_verbose_mode(domain)) |
@@ -1076,7 +1035,7 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | |||
1076 | tomoyo_get_last_name(domain)); | 1035 | tomoyo_get_last_name(domain)); |
1077 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { | 1036 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { |
1078 | const char *name = tomoyo_get_file_pattern(filename)->name; | 1037 | const char *name = tomoyo_get_file_pattern(filename)->name; |
1079 | tomoyo_update_single_path_acl(operation, name, domain, false); | 1038 | tomoyo_update_path_acl(operation, name, domain, false); |
1080 | } | 1039 | } |
1081 | if (!is_enforce) | 1040 | if (!is_enforce) |
1082 | error = 0; | 1041 | error = 0; |
@@ -1086,9 +1045,9 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | |||
1086 | * we need to check "allow_rewrite" permission if the filename is | 1045 | * we need to check "allow_rewrite" permission if the filename is |
1087 | * specified by "deny_rewrite" keyword. | 1046 | * specified by "deny_rewrite" keyword. |
1088 | */ | 1047 | */ |
1089 | if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL && | 1048 | if (!error && operation == TOMOYO_TYPE_TRUNCATE && |
1090 | tomoyo_is_no_rewrite_file(filename)) { | 1049 | tomoyo_is_no_rewrite_file(filename)) { |
1091 | operation = TOMOYO_TYPE_REWRITE_ACL; | 1050 | operation = TOMOYO_TYPE_REWRITE; |
1092 | goto next; | 1051 | goto next; |
1093 | } | 1052 | } |
1094 | return error; | 1053 | return error; |
@@ -1101,6 +1060,8 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | |||
1101 | * @filename: Check permission for "execute". | 1060 | * @filename: Check permission for "execute". |
1102 | * | 1061 | * |
1103 | * Returns 0 on success, negativevalue otherwise. | 1062 | * Returns 0 on success, negativevalue otherwise. |
1063 | * | ||
1064 | * Caller holds tomoyo_read_lock(). | ||
1104 | */ | 1065 | */ |
1105 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, | 1066 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, |
1106 | const struct tomoyo_path_info *filename) | 1067 | const struct tomoyo_path_info *filename) |
@@ -1129,6 +1090,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1129 | struct tomoyo_path_info *buf; | 1090 | struct tomoyo_path_info *buf; |
1130 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1091 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1131 | const bool is_enforce = (mode == 3); | 1092 | const bool is_enforce = (mode == 3); |
1093 | int idx; | ||
1132 | 1094 | ||
1133 | if (!mode || !path->mnt) | 1095 | if (!mode || !path->mnt) |
1134 | return 0; | 1096 | return 0; |
@@ -1140,6 +1102,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1140 | * don't call me. | 1102 | * don't call me. |
1141 | */ | 1103 | */ |
1142 | return 0; | 1104 | return 0; |
1105 | idx = tomoyo_read_lock(); | ||
1143 | buf = tomoyo_get_path(path); | 1106 | buf = tomoyo_get_path(path); |
1144 | if (!buf) | 1107 | if (!buf) |
1145 | goto out; | 1108 | goto out; |
@@ -1152,49 +1115,50 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1152 | if ((acc_mode & MAY_WRITE) && | 1115 | if ((acc_mode & MAY_WRITE) && |
1153 | ((flag & O_TRUNC) || !(flag & O_APPEND)) && | 1116 | ((flag & O_TRUNC) || !(flag & O_APPEND)) && |
1154 | (tomoyo_is_no_rewrite_file(buf))) { | 1117 | (tomoyo_is_no_rewrite_file(buf))) { |
1155 | error = tomoyo_check_single_path_permission2(domain, | 1118 | error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, |
1156 | TOMOYO_TYPE_REWRITE_ACL, | 1119 | buf, mode); |
1157 | buf, mode); | ||
1158 | } | 1120 | } |
1159 | if (!error) | 1121 | if (!error) |
1160 | error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open", | 1122 | error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open", |
1161 | mode); | 1123 | mode); |
1162 | if (!error && (flag & O_TRUNC)) | 1124 | if (!error && (flag & O_TRUNC)) |
1163 | error = tomoyo_check_single_path_permission2(domain, | 1125 | error = tomoyo_path_permission2(domain, TOMOYO_TYPE_TRUNCATE, |
1164 | TOMOYO_TYPE_TRUNCATE_ACL, | 1126 | buf, mode); |
1165 | buf, mode); | ||
1166 | out: | 1127 | out: |
1167 | tomoyo_free(buf); | 1128 | kfree(buf); |
1129 | tomoyo_read_unlock(idx); | ||
1168 | if (!is_enforce) | 1130 | if (!is_enforce) |
1169 | error = 0; | 1131 | error = 0; |
1170 | return error; | 1132 | return error; |
1171 | } | 1133 | } |
1172 | 1134 | ||
1173 | /** | 1135 | /** |
1174 | * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink". | 1136 | * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount". |
1175 | * | 1137 | * |
1176 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
1177 | * @operation: Type of operation. | 1138 | * @operation: Type of operation. |
1178 | * @path: Pointer to "struct path". | 1139 | * @path: Pointer to "struct path". |
1179 | * | 1140 | * |
1180 | * Returns 0 on success, negative value otherwise. | 1141 | * Returns 0 on success, negative value otherwise. |
1181 | */ | 1142 | */ |
1182 | int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, | 1143 | int tomoyo_path_perm(const u8 operation, struct path *path) |
1183 | const u8 operation, struct path *path) | ||
1184 | { | 1144 | { |
1185 | int error = -ENOMEM; | 1145 | int error = -ENOMEM; |
1186 | struct tomoyo_path_info *buf; | 1146 | struct tomoyo_path_info *buf; |
1147 | struct tomoyo_domain_info *domain = tomoyo_domain(); | ||
1187 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1148 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1188 | const bool is_enforce = (mode == 3); | 1149 | const bool is_enforce = (mode == 3); |
1150 | int idx; | ||
1189 | 1151 | ||
1190 | if (!mode || !path->mnt) | 1152 | if (!mode || !path->mnt) |
1191 | return 0; | 1153 | return 0; |
1154 | idx = tomoyo_read_lock(); | ||
1192 | buf = tomoyo_get_path(path); | 1155 | buf = tomoyo_get_path(path); |
1193 | if (!buf) | 1156 | if (!buf) |
1194 | goto out; | 1157 | goto out; |
1195 | switch (operation) { | 1158 | switch (operation) { |
1196 | case TOMOYO_TYPE_MKDIR_ACL: | 1159 | case TOMOYO_TYPE_MKDIR: |
1197 | case TOMOYO_TYPE_RMDIR_ACL: | 1160 | case TOMOYO_TYPE_RMDIR: |
1161 | case TOMOYO_TYPE_CHROOT: | ||
1198 | if (!buf->is_dir) { | 1162 | if (!buf->is_dir) { |
1199 | /* | 1163 | /* |
1200 | * tomoyo_get_path() reserves space for appending "/." | 1164 | * tomoyo_get_path() reserves space for appending "/." |
@@ -1203,10 +1167,10 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, | |||
1203 | tomoyo_fill_path_info(buf); | 1167 | tomoyo_fill_path_info(buf); |
1204 | } | 1168 | } |
1205 | } | 1169 | } |
1206 | error = tomoyo_check_single_path_permission2(domain, operation, buf, | 1170 | error = tomoyo_path_permission2(domain, operation, buf, mode); |
1207 | mode); | ||
1208 | out: | 1171 | out: |
1209 | tomoyo_free(buf); | 1172 | kfree(buf); |
1173 | tomoyo_read_unlock(idx); | ||
1210 | if (!is_enforce) | 1174 | if (!is_enforce) |
1211 | error = 0; | 1175 | error = 0; |
1212 | return error; | 1176 | return error; |
@@ -1215,21 +1179,23 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, | |||
1215 | /** | 1179 | /** |
1216 | * tomoyo_check_rewrite_permission - Check permission for "rewrite". | 1180 | * tomoyo_check_rewrite_permission - Check permission for "rewrite". |
1217 | * | 1181 | * |
1218 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
1219 | * @filp: Pointer to "struct file". | 1182 | * @filp: Pointer to "struct file". |
1220 | * | 1183 | * |
1221 | * Returns 0 on success, negative value otherwise. | 1184 | * Returns 0 on success, negative value otherwise. |
1222 | */ | 1185 | */ |
1223 | int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, | 1186 | int tomoyo_check_rewrite_permission(struct file *filp) |
1224 | struct file *filp) | ||
1225 | { | 1187 | { |
1226 | int error = -ENOMEM; | 1188 | int error = -ENOMEM; |
1189 | struct tomoyo_domain_info *domain = tomoyo_domain(); | ||
1227 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1190 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1228 | const bool is_enforce = (mode == 3); | 1191 | const bool is_enforce = (mode == 3); |
1229 | struct tomoyo_path_info *buf; | 1192 | struct tomoyo_path_info *buf; |
1193 | int idx; | ||
1230 | 1194 | ||
1231 | if (!mode || !filp->f_path.mnt) | 1195 | if (!mode || !filp->f_path.mnt) |
1232 | return 0; | 1196 | return 0; |
1197 | |||
1198 | idx = tomoyo_read_lock(); | ||
1233 | buf = tomoyo_get_path(&filp->f_path); | 1199 | buf = tomoyo_get_path(&filp->f_path); |
1234 | if (!buf) | 1200 | if (!buf) |
1235 | goto out; | 1201 | goto out; |
@@ -1237,38 +1203,38 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, | |||
1237 | error = 0; | 1203 | error = 0; |
1238 | goto out; | 1204 | goto out; |
1239 | } | 1205 | } |
1240 | error = tomoyo_check_single_path_permission2(domain, | 1206 | error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, buf, mode); |
1241 | TOMOYO_TYPE_REWRITE_ACL, | ||
1242 | buf, mode); | ||
1243 | out: | 1207 | out: |
1244 | tomoyo_free(buf); | 1208 | kfree(buf); |
1209 | tomoyo_read_unlock(idx); | ||
1245 | if (!is_enforce) | 1210 | if (!is_enforce) |
1246 | error = 0; | 1211 | error = 0; |
1247 | return error; | 1212 | return error; |
1248 | } | 1213 | } |
1249 | 1214 | ||
1250 | /** | 1215 | /** |
1251 | * tomoyo_check_2path_perm - Check permission for "rename" and "link". | 1216 | * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". |
1252 | * | 1217 | * |
1253 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
1254 | * @operation: Type of operation. | 1218 | * @operation: Type of operation. |
1255 | * @path1: Pointer to "struct path". | 1219 | * @path1: Pointer to "struct path". |
1256 | * @path2: Pointer to "struct path". | 1220 | * @path2: Pointer to "struct path". |
1257 | * | 1221 | * |
1258 | * Returns 0 on success, negative value otherwise. | 1222 | * Returns 0 on success, negative value otherwise. |
1259 | */ | 1223 | */ |
1260 | int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, | 1224 | int tomoyo_path2_perm(const u8 operation, struct path *path1, |
1261 | const u8 operation, struct path *path1, | 1225 | struct path *path2) |
1262 | struct path *path2) | ||
1263 | { | 1226 | { |
1264 | int error = -ENOMEM; | 1227 | int error = -ENOMEM; |
1265 | struct tomoyo_path_info *buf1, *buf2; | 1228 | struct tomoyo_path_info *buf1, *buf2; |
1229 | struct tomoyo_domain_info *domain = tomoyo_domain(); | ||
1266 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1230 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1267 | const bool is_enforce = (mode == 3); | 1231 | const bool is_enforce = (mode == 3); |
1268 | const char *msg; | 1232 | const char *msg; |
1233 | int idx; | ||
1269 | 1234 | ||
1270 | if (!mode || !path1->mnt || !path2->mnt) | 1235 | if (!mode || !path1->mnt || !path2->mnt) |
1271 | return 0; | 1236 | return 0; |
1237 | idx = tomoyo_read_lock(); | ||
1272 | buf1 = tomoyo_get_path(path1); | 1238 | buf1 = tomoyo_get_path(path1); |
1273 | buf2 = tomoyo_get_path(path2); | 1239 | buf2 = tomoyo_get_path(path2); |
1274 | if (!buf1 || !buf2) | 1240 | if (!buf1 || !buf2) |
@@ -1289,8 +1255,8 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, | |||
1289 | } | 1255 | } |
1290 | } | 1256 | } |
1291 | } | 1257 | } |
1292 | error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2); | 1258 | error = tomoyo_path2_acl(domain, operation, buf1, buf2); |
1293 | msg = tomoyo_dp2keyword(operation); | 1259 | msg = tomoyo_path22keyword(operation); |
1294 | if (!error) | 1260 | if (!error) |
1295 | goto out; | 1261 | goto out; |
1296 | if (tomoyo_verbose_mode(domain)) | 1262 | if (tomoyo_verbose_mode(domain)) |
@@ -1301,12 +1267,13 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, | |||
1301 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { | 1267 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { |
1302 | const char *name1 = tomoyo_get_file_pattern(buf1)->name; | 1268 | const char *name1 = tomoyo_get_file_pattern(buf1)->name; |
1303 | const char *name2 = tomoyo_get_file_pattern(buf2)->name; | 1269 | const char *name2 = tomoyo_get_file_pattern(buf2)->name; |
1304 | tomoyo_update_double_path_acl(operation, name1, name2, domain, | 1270 | tomoyo_update_path2_acl(operation, name1, name2, domain, |
1305 | false); | 1271 | false); |
1306 | } | 1272 | } |
1307 | out: | 1273 | out: |
1308 | tomoyo_free(buf1); | 1274 | kfree(buf1); |
1309 | tomoyo_free(buf2); | 1275 | kfree(buf2); |
1276 | tomoyo_read_unlock(idx); | ||
1310 | if (!is_enforce) | 1277 | if (!is_enforce) |
1311 | error = 0; | 1278 | error = 0; |
1312 | return error; | 1279 | return error; |