.. | .. |
---|
9 | 9 | #include "common.h" |
---|
10 | 10 | |
---|
11 | 11 | /** |
---|
12 | | - * tomoyo_cred_alloc_blank - Target for security_cred_alloc_blank(). |
---|
| 12 | + * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. |
---|
13 | 13 | * |
---|
14 | | - * @new: Pointer to "struct cred". |
---|
15 | | - * @gfp: Memory allocation flags. |
---|
16 | | - * |
---|
17 | | - * Returns 0. |
---|
| 14 | + * Returns pointer to "struct tomoyo_domain_info" for current thread. |
---|
18 | 15 | */ |
---|
19 | | -static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) |
---|
| 16 | +struct tomoyo_domain_info *tomoyo_domain(void) |
---|
20 | 17 | { |
---|
21 | | - new->security = NULL; |
---|
22 | | - return 0; |
---|
| 18 | + struct tomoyo_task *s = tomoyo_task(current); |
---|
| 19 | + |
---|
| 20 | + if (s->old_domain_info && !current->in_execve) { |
---|
| 21 | + atomic_dec(&s->old_domain_info->users); |
---|
| 22 | + s->old_domain_info = NULL; |
---|
| 23 | + } |
---|
| 24 | + return s->domain_info; |
---|
23 | 25 | } |
---|
24 | 26 | |
---|
25 | 27 | /** |
---|
.. | .. |
---|
34 | 36 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, |
---|
35 | 37 | gfp_t gfp) |
---|
36 | 38 | { |
---|
37 | | - struct tomoyo_domain_info *domain = old->security; |
---|
38 | | - new->security = domain; |
---|
39 | | - if (domain) |
---|
40 | | - atomic_inc(&domain->users); |
---|
| 39 | + /* Restore old_domain_info saved by previous execve() request. */ |
---|
| 40 | + struct tomoyo_task *s = tomoyo_task(current); |
---|
| 41 | + |
---|
| 42 | + if (s->old_domain_info && !current->in_execve) { |
---|
| 43 | + atomic_dec(&s->domain_info->users); |
---|
| 44 | + s->domain_info = s->old_domain_info; |
---|
| 45 | + s->old_domain_info = NULL; |
---|
| 46 | + } |
---|
41 | 47 | return 0; |
---|
42 | 48 | } |
---|
43 | 49 | |
---|
44 | 50 | /** |
---|
45 | | - * tomoyo_cred_transfer - Target for security_transfer_creds(). |
---|
| 51 | + * tomoyo_bprm_committed_creds - Target for security_bprm_committed_creds(). |
---|
46 | 52 | * |
---|
47 | | - * @new: Pointer to "struct cred". |
---|
48 | | - * @old: Pointer to "struct cred". |
---|
| 53 | + * @bprm: Pointer to "struct linux_binprm". |
---|
49 | 54 | */ |
---|
50 | | -static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) |
---|
| 55 | +static void tomoyo_bprm_committed_creds(struct linux_binprm *bprm) |
---|
51 | 56 | { |
---|
52 | | - tomoyo_cred_prepare(new, old, 0); |
---|
| 57 | + /* Clear old_domain_info saved by execve() request. */ |
---|
| 58 | + struct tomoyo_task *s = tomoyo_task(current); |
---|
| 59 | + |
---|
| 60 | + atomic_dec(&s->old_domain_info->users); |
---|
| 61 | + s->old_domain_info = NULL; |
---|
53 | 62 | } |
---|
54 | 63 | |
---|
| 64 | +#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER |
---|
55 | 65 | /** |
---|
56 | | - * tomoyo_cred_free - Target for security_cred_free(). |
---|
57 | | - * |
---|
58 | | - * @cred: Pointer to "struct cred". |
---|
59 | | - */ |
---|
60 | | -static void tomoyo_cred_free(struct cred *cred) |
---|
61 | | -{ |
---|
62 | | - struct tomoyo_domain_info *domain = cred->security; |
---|
63 | | - if (domain) |
---|
64 | | - atomic_dec(&domain->users); |
---|
65 | | -} |
---|
66 | | - |
---|
67 | | -/** |
---|
68 | | - * tomoyo_bprm_set_creds - Target for security_bprm_set_creds(). |
---|
| 66 | + * tomoyo_bprm_for_exec - Target for security_bprm_creds_for_exec(). |
---|
69 | 67 | * |
---|
70 | 68 | * @bprm: Pointer to "struct linux_binprm". |
---|
71 | 69 | * |
---|
72 | | - * Returns 0 on success, negative value otherwise. |
---|
| 70 | + * Returns 0. |
---|
73 | 71 | */ |
---|
74 | | -static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) |
---|
| 72 | +static int tomoyo_bprm_creds_for_exec(struct linux_binprm *bprm) |
---|
75 | 73 | { |
---|
76 | | - /* |
---|
77 | | - * Do only if this function is called for the first time of an execve |
---|
78 | | - * operation. |
---|
79 | | - */ |
---|
80 | | - if (bprm->called_set_creds) |
---|
81 | | - return 0; |
---|
82 | | -#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER |
---|
83 | 74 | /* |
---|
84 | 75 | * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested |
---|
85 | 76 | * for the first time. |
---|
86 | 77 | */ |
---|
87 | 78 | if (!tomoyo_policy_loaded) |
---|
88 | 79 | tomoyo_load_policy(bprm->filename); |
---|
89 | | -#endif |
---|
90 | | - /* |
---|
91 | | - * Release reference to "struct tomoyo_domain_info" stored inside |
---|
92 | | - * "bprm->cred->security". New reference to "struct tomoyo_domain_info" |
---|
93 | | - * stored inside "bprm->cred->security" will be acquired later inside |
---|
94 | | - * tomoyo_find_next_domain(). |
---|
95 | | - */ |
---|
96 | | - atomic_dec(&((struct tomoyo_domain_info *) |
---|
97 | | - bprm->cred->security)->users); |
---|
98 | | - /* |
---|
99 | | - * Tell tomoyo_bprm_check_security() is called for the first time of an |
---|
100 | | - * execve operation. |
---|
101 | | - */ |
---|
102 | | - bprm->cred->security = NULL; |
---|
103 | 80 | return 0; |
---|
104 | 81 | } |
---|
| 82 | +#endif |
---|
105 | 83 | |
---|
106 | 84 | /** |
---|
107 | 85 | * tomoyo_bprm_check_security - Target for security_bprm_check(). |
---|
.. | .. |
---|
112 | 90 | */ |
---|
113 | 91 | static int tomoyo_bprm_check_security(struct linux_binprm *bprm) |
---|
114 | 92 | { |
---|
115 | | - struct tomoyo_domain_info *domain = bprm->cred->security; |
---|
| 93 | + struct tomoyo_task *s = tomoyo_task(current); |
---|
116 | 94 | |
---|
117 | 95 | /* |
---|
118 | | - * Execute permission is checked against pathname passed to do_execve() |
---|
| 96 | + * Execute permission is checked against pathname passed to execve() |
---|
119 | 97 | * using current domain. |
---|
120 | 98 | */ |
---|
121 | | - if (!domain) { |
---|
| 99 | + if (!s->old_domain_info) { |
---|
122 | 100 | const int idx = tomoyo_read_lock(); |
---|
123 | 101 | const int err = tomoyo_find_next_domain(bprm); |
---|
| 102 | + |
---|
124 | 103 | tomoyo_read_unlock(idx); |
---|
125 | 104 | return err; |
---|
126 | 105 | } |
---|
127 | 106 | /* |
---|
128 | 107 | * Read permission is checked against interpreters using next domain. |
---|
129 | 108 | */ |
---|
130 | | - return tomoyo_check_open_permission(domain, &bprm->file->f_path, |
---|
131 | | - O_RDONLY); |
---|
| 109 | + return tomoyo_check_open_permission(s->domain_info, |
---|
| 110 | + &bprm->file->f_path, O_RDONLY); |
---|
132 | 111 | } |
---|
133 | 112 | |
---|
134 | 113 | /** |
---|
.. | .. |
---|
167 | 146 | static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) |
---|
168 | 147 | { |
---|
169 | 148 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
---|
| 149 | + |
---|
170 | 150 | return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); |
---|
171 | 151 | } |
---|
172 | 152 | |
---|
.. | .. |
---|
183 | 163 | umode_t mode) |
---|
184 | 164 | { |
---|
185 | 165 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
---|
| 166 | + |
---|
186 | 167 | return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, |
---|
187 | 168 | mode & S_IALLUGO); |
---|
188 | 169 | } |
---|
.. | .. |
---|
198 | 179 | static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) |
---|
199 | 180 | { |
---|
200 | 181 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
---|
| 182 | + |
---|
201 | 183 | return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); |
---|
202 | 184 | } |
---|
203 | 185 | |
---|
.. | .. |
---|
214 | 196 | const char *old_name) |
---|
215 | 197 | { |
---|
216 | 198 | struct path path = { .mnt = parent->mnt, .dentry = dentry }; |
---|
| 199 | + |
---|
217 | 200 | return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); |
---|
218 | 201 | } |
---|
219 | 202 | |
---|
.. | .. |
---|
271 | 254 | { |
---|
272 | 255 | struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry }; |
---|
273 | 256 | struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry }; |
---|
| 257 | + |
---|
274 | 258 | return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); |
---|
275 | 259 | } |
---|
276 | 260 | |
---|
.. | .. |
---|
291 | 275 | { |
---|
292 | 276 | struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry }; |
---|
293 | 277 | struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry }; |
---|
| 278 | + |
---|
294 | 279 | return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); |
---|
295 | 280 | } |
---|
296 | 281 | |
---|
.. | .. |
---|
322 | 307 | */ |
---|
323 | 308 | static int tomoyo_file_open(struct file *f) |
---|
324 | 309 | { |
---|
325 | | - int flags = f->f_flags; |
---|
326 | | - /* Don't check read permission here if called from do_execve(). */ |
---|
| 310 | + /* Don't check read permission here if called from execve(). */ |
---|
327 | 311 | if (current->in_execve) |
---|
328 | 312 | return 0; |
---|
329 | | - return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); |
---|
| 313 | + return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, |
---|
| 314 | + f->f_flags); |
---|
330 | 315 | } |
---|
331 | 316 | |
---|
332 | 317 | /** |
---|
.. | .. |
---|
370 | 355 | static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid) |
---|
371 | 356 | { |
---|
372 | 357 | int error = 0; |
---|
| 358 | + |
---|
373 | 359 | if (uid_valid(uid)) |
---|
374 | 360 | error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, |
---|
375 | 361 | from_kuid(&init_user_ns, uid)); |
---|
.. | .. |
---|
419 | 405 | static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) |
---|
420 | 406 | { |
---|
421 | 407 | struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; |
---|
| 408 | + |
---|
422 | 409 | return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); |
---|
423 | 410 | } |
---|
424 | 411 | |
---|
.. | .. |
---|
493 | 480 | return tomoyo_socket_sendmsg_permission(sock, msg, size); |
---|
494 | 481 | } |
---|
495 | 482 | |
---|
| 483 | +struct lsm_blob_sizes tomoyo_blob_sizes __lsm_ro_after_init = { |
---|
| 484 | + .lbs_task = sizeof(struct tomoyo_task), |
---|
| 485 | +}; |
---|
| 486 | + |
---|
| 487 | +/** |
---|
| 488 | + * tomoyo_task_alloc - Target for security_task_alloc(). |
---|
| 489 | + * |
---|
| 490 | + * @task: Pointer to "struct task_struct". |
---|
| 491 | + * @flags: clone() flags. |
---|
| 492 | + * |
---|
| 493 | + * Returns 0. |
---|
| 494 | + */ |
---|
| 495 | +static int tomoyo_task_alloc(struct task_struct *task, |
---|
| 496 | + unsigned long clone_flags) |
---|
| 497 | +{ |
---|
| 498 | + struct tomoyo_task *old = tomoyo_task(current); |
---|
| 499 | + struct tomoyo_task *new = tomoyo_task(task); |
---|
| 500 | + |
---|
| 501 | + new->domain_info = old->domain_info; |
---|
| 502 | + atomic_inc(&new->domain_info->users); |
---|
| 503 | + new->old_domain_info = NULL; |
---|
| 504 | + return 0; |
---|
| 505 | +} |
---|
| 506 | + |
---|
| 507 | +/** |
---|
| 508 | + * tomoyo_task_free - Target for security_task_free(). |
---|
| 509 | + * |
---|
| 510 | + * @task: Pointer to "struct task_struct". |
---|
| 511 | + */ |
---|
| 512 | +static void tomoyo_task_free(struct task_struct *task) |
---|
| 513 | +{ |
---|
| 514 | + struct tomoyo_task *s = tomoyo_task(task); |
---|
| 515 | + |
---|
| 516 | + if (s->domain_info) { |
---|
| 517 | + atomic_dec(&s->domain_info->users); |
---|
| 518 | + s->domain_info = NULL; |
---|
| 519 | + } |
---|
| 520 | + if (s->old_domain_info) { |
---|
| 521 | + atomic_dec(&s->old_domain_info->users); |
---|
| 522 | + s->old_domain_info = NULL; |
---|
| 523 | + } |
---|
| 524 | +} |
---|
| 525 | + |
---|
496 | 526 | /* |
---|
497 | 527 | * tomoyo_security_ops is a "struct security_operations" which is used for |
---|
498 | 528 | * registering TOMOYO. |
---|
499 | 529 | */ |
---|
500 | 530 | static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = { |
---|
501 | | - LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank), |
---|
502 | 531 | LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), |
---|
503 | | - LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer), |
---|
504 | | - LSM_HOOK_INIT(cred_free, tomoyo_cred_free), |
---|
505 | | - LSM_HOOK_INIT(bprm_set_creds, tomoyo_bprm_set_creds), |
---|
| 532 | + LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds), |
---|
| 533 | + LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc), |
---|
| 534 | + LSM_HOOK_INIT(task_free, tomoyo_task_free), |
---|
| 535 | +#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER |
---|
| 536 | + LSM_HOOK_INIT(bprm_creds_for_exec, tomoyo_bprm_creds_for_exec), |
---|
| 537 | +#endif |
---|
506 | 538 | LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security), |
---|
507 | 539 | LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl), |
---|
508 | 540 | LSM_HOOK_INIT(file_open, tomoyo_file_open), |
---|
.. | .. |
---|
531 | 563 | /* Lock for GC. */ |
---|
532 | 564 | DEFINE_SRCU(tomoyo_ss); |
---|
533 | 565 | |
---|
| 566 | +int tomoyo_enabled __lsm_ro_after_init = 1; |
---|
| 567 | + |
---|
534 | 568 | /** |
---|
535 | 569 | * tomoyo_init - Register TOMOYO Linux as a LSM module. |
---|
536 | 570 | * |
---|
.. | .. |
---|
538 | 572 | */ |
---|
539 | 573 | static int __init tomoyo_init(void) |
---|
540 | 574 | { |
---|
541 | | - struct cred *cred = (struct cred *) current_cred(); |
---|
| 575 | + struct tomoyo_task *s = tomoyo_task(current); |
---|
542 | 576 | |
---|
543 | | - if (!security_module_enable("tomoyo")) |
---|
544 | | - return 0; |
---|
545 | 577 | /* register ourselves with the security framework */ |
---|
546 | 578 | security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); |
---|
547 | | - printk(KERN_INFO "TOMOYO Linux initialized\n"); |
---|
548 | | - cred->security = &tomoyo_kernel_domain; |
---|
| 579 | + pr_info("TOMOYO Linux initialized\n"); |
---|
| 580 | + s->domain_info = &tomoyo_kernel_domain; |
---|
| 581 | + atomic_inc(&tomoyo_kernel_domain.users); |
---|
| 582 | + s->old_domain_info = NULL; |
---|
549 | 583 | tomoyo_mm_init(); |
---|
| 584 | + |
---|
550 | 585 | return 0; |
---|
551 | 586 | } |
---|
552 | 587 | |
---|
553 | | -security_initcall(tomoyo_init); |
---|
| 588 | +DEFINE_LSM(tomoyo) = { |
---|
| 589 | + .name = "tomoyo", |
---|
| 590 | + .enabled = &tomoyo_enabled, |
---|
| 591 | + .flags = LSM_FLAG_LEGACY_MAJOR, |
---|
| 592 | + .blobs = &tomoyo_blob_sizes, |
---|
| 593 | + .init = tomoyo_init, |
---|
| 594 | +}; |
---|