diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/capability.c | 21 | ||||
-rw-r--r-- | security/commoncap.c | 265 | ||||
-rw-r--r-- | security/keys/internal.h | 17 | ||||
-rw-r--r-- | security/keys/key.c | 25 | ||||
-rw-r--r-- | security/keys/keyctl.c | 95 | ||||
-rw-r--r-- | security/keys/keyring.c | 14 | ||||
-rw-r--r-- | security/keys/permission.c | 24 | ||||
-rw-r--r-- | security/keys/proc.c | 8 | ||||
-rw-r--r-- | security/keys/process_keys.c | 333 | ||||
-rw-r--r-- | security/keys/request_key.c | 29 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 41 | ||||
-rw-r--r-- | security/security.c | 58 | ||||
-rw-r--r-- | security/selinux/hooks.c | 286 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 82 |
14 files changed, 668 insertions, 630 deletions
diff --git a/security/capability.c b/security/capability.c index fac2f61b69a9..efeb6d9e0e6a 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -340,12 +340,16 @@ static int cap_task_create(unsigned long clone_flags) | |||
340 | return 0; | 340 | return 0; |
341 | } | 341 | } |
342 | 342 | ||
343 | static int cap_cred_alloc_security(struct cred *cred) | 343 | static void cap_cred_free(struct cred *cred) |
344 | { | ||
345 | } | ||
346 | |||
347 | static int cap_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) | ||
344 | { | 348 | { |
345 | return 0; | 349 | return 0; |
346 | } | 350 | } |
347 | 351 | ||
348 | static void cap_cred_free(struct cred *cred) | 352 | static void cap_cred_commit(struct cred *new, const struct cred *old) |
349 | { | 353 | { |
350 | } | 354 | } |
351 | 355 | ||
@@ -750,7 +754,7 @@ static void cap_release_secctx(char *secdata, u32 seclen) | |||
750 | } | 754 | } |
751 | 755 | ||
752 | #ifdef CONFIG_KEYS | 756 | #ifdef CONFIG_KEYS |
753 | static int cap_key_alloc(struct key *key, struct task_struct *ctx, | 757 | static int cap_key_alloc(struct key *key, const struct cred *cred, |
754 | unsigned long flags) | 758 | unsigned long flags) |
755 | { | 759 | { |
756 | return 0; | 760 | return 0; |
@@ -760,7 +764,7 @@ static void cap_key_free(struct key *key) | |||
760 | { | 764 | { |
761 | } | 765 | } |
762 | 766 | ||
763 | static int cap_key_permission(key_ref_t key_ref, struct task_struct *context, | 767 | static int cap_key_permission(key_ref_t key_ref, const struct cred *cred, |
764 | key_perm_t perm) | 768 | key_perm_t perm) |
765 | { | 769 | { |
766 | return 0; | 770 | return 0; |
@@ -814,8 +818,7 @@ void security_fixup_ops(struct security_operations *ops) | |||
814 | set_to_cap_if_null(ops, ptrace_may_access); | 818 | set_to_cap_if_null(ops, ptrace_may_access); |
815 | set_to_cap_if_null(ops, ptrace_traceme); | 819 | set_to_cap_if_null(ops, ptrace_traceme); |
816 | set_to_cap_if_null(ops, capget); | 820 | set_to_cap_if_null(ops, capget); |
817 | set_to_cap_if_null(ops, capset_check); | 821 | set_to_cap_if_null(ops, capset); |
818 | set_to_cap_if_null(ops, capset_set); | ||
819 | set_to_cap_if_null(ops, acct); | 822 | set_to_cap_if_null(ops, acct); |
820 | set_to_cap_if_null(ops, capable); | 823 | set_to_cap_if_null(ops, capable); |
821 | set_to_cap_if_null(ops, quotactl); | 824 | set_to_cap_if_null(ops, quotactl); |
@@ -890,10 +893,11 @@ void security_fixup_ops(struct security_operations *ops) | |||
890 | set_to_cap_if_null(ops, file_receive); | 893 | set_to_cap_if_null(ops, file_receive); |
891 | set_to_cap_if_null(ops, dentry_open); | 894 | set_to_cap_if_null(ops, dentry_open); |
892 | set_to_cap_if_null(ops, task_create); | 895 | set_to_cap_if_null(ops, task_create); |
893 | set_to_cap_if_null(ops, cred_alloc_security); | ||
894 | set_to_cap_if_null(ops, cred_free); | 896 | set_to_cap_if_null(ops, cred_free); |
897 | set_to_cap_if_null(ops, cred_prepare); | ||
898 | set_to_cap_if_null(ops, cred_commit); | ||
895 | set_to_cap_if_null(ops, task_setuid); | 899 | set_to_cap_if_null(ops, task_setuid); |
896 | set_to_cap_if_null(ops, task_post_setuid); | 900 | set_to_cap_if_null(ops, task_fix_setuid); |
897 | set_to_cap_if_null(ops, task_setgid); | 901 | set_to_cap_if_null(ops, task_setgid); |
898 | set_to_cap_if_null(ops, task_setpgid); | 902 | set_to_cap_if_null(ops, task_setpgid); |
899 | set_to_cap_if_null(ops, task_getpgid); | 903 | set_to_cap_if_null(ops, task_getpgid); |
@@ -910,7 +914,6 @@ void security_fixup_ops(struct security_operations *ops) | |||
910 | set_to_cap_if_null(ops, task_wait); | 914 | set_to_cap_if_null(ops, task_wait); |
911 | set_to_cap_if_null(ops, task_kill); | 915 | set_to_cap_if_null(ops, task_kill); |
912 | set_to_cap_if_null(ops, task_prctl); | 916 | set_to_cap_if_null(ops, task_prctl); |
913 | set_to_cap_if_null(ops, task_reparent_to_init); | ||
914 | set_to_cap_if_null(ops, task_to_inode); | 917 | set_to_cap_if_null(ops, task_to_inode); |
915 | set_to_cap_if_null(ops, ipc_permission); | 918 | set_to_cap_if_null(ops, ipc_permission); |
916 | set_to_cap_if_null(ops, ipc_getsecid); | 919 | set_to_cap_if_null(ops, ipc_getsecid); |
diff --git a/security/commoncap.c b/security/commoncap.c index 0384bf95db68..b5419273f92d 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -72,8 +72,8 @@ int cap_ptrace_may_access(struct task_struct *child, unsigned int mode) | |||
72 | int ret = 0; | 72 | int ret = 0; |
73 | 73 | ||
74 | rcu_read_lock(); | 74 | rcu_read_lock(); |
75 | if (!cap_issubset(child->cred->cap_permitted, | 75 | if (!cap_issubset(__task_cred(child)->cap_permitted, |
76 | current->cred->cap_permitted) && | 76 | current_cred()->cap_permitted) && |
77 | !capable(CAP_SYS_PTRACE)) | 77 | !capable(CAP_SYS_PTRACE)) |
78 | ret = -EPERM; | 78 | ret = -EPERM; |
79 | rcu_read_unlock(); | 79 | rcu_read_unlock(); |
@@ -85,8 +85,8 @@ int cap_ptrace_traceme(struct task_struct *parent) | |||
85 | int ret = 0; | 85 | int ret = 0; |
86 | 86 | ||
87 | rcu_read_lock(); | 87 | rcu_read_lock(); |
88 | if (!cap_issubset(current->cred->cap_permitted, | 88 | if (!cap_issubset(current_cred()->cap_permitted, |
89 | parent->cred->cap_permitted) && | 89 | __task_cred(parent)->cap_permitted) && |
90 | !has_capability(parent, CAP_SYS_PTRACE)) | 90 | !has_capability(parent, CAP_SYS_PTRACE)) |
91 | ret = -EPERM; | 91 | ret = -EPERM; |
92 | rcu_read_unlock(); | 92 | rcu_read_unlock(); |
@@ -117,7 +117,7 @@ static inline int cap_inh_is_capped(void) | |||
117 | * to the old permitted set. That is, if the current task | 117 | * to the old permitted set. That is, if the current task |
118 | * does *not* possess the CAP_SETPCAP capability. | 118 | * does *not* possess the CAP_SETPCAP capability. |
119 | */ | 119 | */ |
120 | return (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0); | 120 | return cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | static inline int cap_limit_ptraced_target(void) { return 1; } | 123 | static inline int cap_limit_ptraced_target(void) { return 1; } |
@@ -132,52 +132,39 @@ static inline int cap_limit_ptraced_target(void) | |||
132 | 132 | ||
133 | #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ | 133 | #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ |
134 | 134 | ||
135 | int cap_capset_check(const kernel_cap_t *effective, | 135 | int cap_capset(struct cred *new, |
136 | const kernel_cap_t *inheritable, | 136 | const struct cred *old, |
137 | const kernel_cap_t *permitted) | 137 | const kernel_cap_t *effective, |
138 | const kernel_cap_t *inheritable, | ||
139 | const kernel_cap_t *permitted) | ||
138 | { | 140 | { |
139 | const struct cred *cred = current->cred; | 141 | if (cap_inh_is_capped() && |
140 | 142 | !cap_issubset(*inheritable, | |
141 | if (cap_inh_is_capped() | 143 | cap_combine(old->cap_inheritable, |
142 | && !cap_issubset(*inheritable, | 144 | old->cap_permitted))) |
143 | cap_combine(cred->cap_inheritable, | ||
144 | cred->cap_permitted))) { | ||
145 | /* incapable of using this inheritable set */ | 145 | /* incapable of using this inheritable set */ |
146 | return -EPERM; | 146 | return -EPERM; |
147 | } | 147 | |
148 | if (!cap_issubset(*inheritable, | 148 | if (!cap_issubset(*inheritable, |
149 | cap_combine(cred->cap_inheritable, | 149 | cap_combine(old->cap_inheritable, |
150 | cred->cap_bset))) { | 150 | old->cap_bset))) |
151 | /* no new pI capabilities outside bounding set */ | 151 | /* no new pI capabilities outside bounding set */ |
152 | return -EPERM; | 152 | return -EPERM; |
153 | } | ||
154 | 153 | ||
155 | /* verify restrictions on target's new Permitted set */ | 154 | /* verify restrictions on target's new Permitted set */ |
156 | if (!cap_issubset (*permitted, | 155 | if (!cap_issubset(*permitted, old->cap_permitted)) |
157 | cap_combine (cred->cap_permitted, | ||
158 | cred->cap_permitted))) { | ||
159 | return -EPERM; | 156 | return -EPERM; |
160 | } | ||
161 | 157 | ||
162 | /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ | 158 | /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ |
163 | if (!cap_issubset (*effective, *permitted)) { | 159 | if (!cap_issubset(*effective, *permitted)) |
164 | return -EPERM; | 160 | return -EPERM; |
165 | } | ||
166 | 161 | ||
162 | new->cap_effective = *effective; | ||
163 | new->cap_inheritable = *inheritable; | ||
164 | new->cap_permitted = *permitted; | ||
167 | return 0; | 165 | return 0; |
168 | } | 166 | } |
169 | 167 | ||
170 | void cap_capset_set(const kernel_cap_t *effective, | ||
171 | const kernel_cap_t *inheritable, | ||
172 | const kernel_cap_t *permitted) | ||
173 | { | ||
174 | struct cred *cred = current->cred; | ||
175 | |||
176 | cred->cap_effective = *effective; | ||
177 | cred->cap_inheritable = *inheritable; | ||
178 | cred->cap_permitted = *permitted; | ||
179 | } | ||
180 | |||
181 | static inline void bprm_clear_caps(struct linux_binprm *bprm) | 168 | static inline void bprm_clear_caps(struct linux_binprm *bprm) |
182 | { | 169 | { |
183 | cap_clear(bprm->cap_post_exec_permitted); | 170 | cap_clear(bprm->cap_post_exec_permitted); |
@@ -382,41 +369,46 @@ int cap_bprm_set_security (struct linux_binprm *bprm) | |||
382 | return ret; | 369 | return ret; |
383 | } | 370 | } |
384 | 371 | ||
385 | void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) | 372 | int cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) |
386 | { | 373 | { |
387 | struct cred *cred = current->cred; | 374 | const struct cred *old = current_cred(); |
375 | struct cred *new; | ||
376 | |||
377 | new = prepare_creds(); | ||
378 | if (!new) | ||
379 | return -ENOMEM; | ||
388 | 380 | ||
389 | if (bprm->e_uid != cred->uid || bprm->e_gid != cred->gid || | 381 | if (bprm->e_uid != old->uid || bprm->e_gid != old->gid || |
390 | !cap_issubset(bprm->cap_post_exec_permitted, | 382 | !cap_issubset(bprm->cap_post_exec_permitted, |
391 | cred->cap_permitted)) { | 383 | old->cap_permitted)) { |
392 | set_dumpable(current->mm, suid_dumpable); | 384 | set_dumpable(current->mm, suid_dumpable); |
393 | current->pdeath_signal = 0; | 385 | current->pdeath_signal = 0; |
394 | 386 | ||
395 | if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) { | 387 | if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) { |
396 | if (!capable(CAP_SETUID)) { | 388 | if (!capable(CAP_SETUID)) { |
397 | bprm->e_uid = cred->uid; | 389 | bprm->e_uid = old->uid; |
398 | bprm->e_gid = cred->gid; | 390 | bprm->e_gid = old->gid; |
399 | } | 391 | } |
400 | if (cap_limit_ptraced_target()) { | 392 | if (cap_limit_ptraced_target()) { |
401 | bprm->cap_post_exec_permitted = cap_intersect( | 393 | bprm->cap_post_exec_permitted = cap_intersect( |
402 | bprm->cap_post_exec_permitted, | 394 | bprm->cap_post_exec_permitted, |
403 | cred->cap_permitted); | 395 | new->cap_permitted); |
404 | } | 396 | } |
405 | } | 397 | } |
406 | } | 398 | } |
407 | 399 | ||
408 | cred->suid = cred->euid = cred->fsuid = bprm->e_uid; | 400 | new->suid = new->euid = new->fsuid = bprm->e_uid; |
409 | cred->sgid = cred->egid = cred->fsgid = bprm->e_gid; | 401 | new->sgid = new->egid = new->fsgid = bprm->e_gid; |
410 | 402 | ||
411 | /* For init, we want to retain the capabilities set | 403 | /* For init, we want to retain the capabilities set |
412 | * in the init_task struct. Thus we skip the usual | 404 | * in the init_task struct. Thus we skip the usual |
413 | * capability rules */ | 405 | * capability rules */ |
414 | if (!is_global_init(current)) { | 406 | if (!is_global_init(current)) { |
415 | cred->cap_permitted = bprm->cap_post_exec_permitted; | 407 | new->cap_permitted = bprm->cap_post_exec_permitted; |
416 | if (bprm->cap_effective) | 408 | if (bprm->cap_effective) |
417 | cred->cap_effective = bprm->cap_post_exec_permitted; | 409 | new->cap_effective = bprm->cap_post_exec_permitted; |
418 | else | 410 | else |
419 | cap_clear(cred->cap_effective); | 411 | cap_clear(new->cap_effective); |
420 | } | 412 | } |
421 | 413 | ||
422 | /* | 414 | /* |
@@ -431,15 +423,15 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) | |||
431 | * Number 1 above might fail if you don't have a full bset, but I think | 423 | * Number 1 above might fail if you don't have a full bset, but I think |
432 | * that is interesting information to audit. | 424 | * that is interesting information to audit. |
433 | */ | 425 | */ |
434 | if (!cap_isclear(cred->cap_effective)) { | 426 | if (!cap_isclear(new->cap_effective)) { |
435 | if (!cap_issubset(CAP_FULL_SET, cred->cap_effective) || | 427 | if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || |
436 | (bprm->e_uid != 0) || (cred->uid != 0) || | 428 | bprm->e_uid != 0 || new->uid != 0 || |
437 | issecure(SECURE_NOROOT)) | 429 | issecure(SECURE_NOROOT)) |
438 | audit_log_bprm_fcaps(bprm, &cred->cap_permitted, | 430 | audit_log_bprm_fcaps(bprm, new, old); |
439 | &cred->cap_effective); | ||
440 | } | 431 | } |
441 | 432 | ||
442 | cred->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); | 433 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); |
434 | return commit_creds(new); | ||
443 | } | 435 | } |
444 | 436 | ||
445 | int cap_bprm_secureexec (struct linux_binprm *bprm) | 437 | int cap_bprm_secureexec (struct linux_binprm *bprm) |
@@ -514,65 +506,49 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name) | |||
514 | * files.. | 506 | * files.. |
515 | * Thanks to Olaf Kirch and Peter Benie for spotting this. | 507 | * Thanks to Olaf Kirch and Peter Benie for spotting this. |
516 | */ | 508 | */ |
517 | static inline void cap_emulate_setxuid (int old_ruid, int old_euid, | 509 | static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) |
518 | int old_suid) | ||
519 | { | 510 | { |
520 | struct cred *cred = current->cred; | 511 | if ((old->uid == 0 || old->euid == 0 || old->suid == 0) && |
521 | 512 | (new->uid != 0 && new->euid != 0 && new->suid != 0) && | |
522 | if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) && | ||
523 | (cred->uid != 0 && cred->euid != 0 && cred->suid != 0) && | ||
524 | !issecure(SECURE_KEEP_CAPS)) { | 513 | !issecure(SECURE_KEEP_CAPS)) { |
525 | cap_clear(cred->cap_permitted); | 514 | cap_clear(new->cap_permitted); |
526 | cap_clear(cred->cap_effective); | 515 | cap_clear(new->cap_effective); |
527 | } | ||
528 | if (old_euid == 0 && cred->euid != 0) { | ||
529 | cap_clear(cred->cap_effective); | ||
530 | } | ||
531 | if (old_euid != 0 && cred->euid == 0) { | ||
532 | cred->cap_effective = cred->cap_permitted; | ||
533 | } | 516 | } |
517 | if (old->euid == 0 && new->euid != 0) | ||
518 | cap_clear(new->cap_effective); | ||
519 | if (old->euid != 0 && new->euid == 0) | ||
520 | new->cap_effective = new->cap_permitted; | ||
534 | } | 521 | } |
535 | 522 | ||
536 | int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, | 523 | int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags) |
537 | int flags) | ||
538 | { | 524 | { |
539 | struct cred *cred = current->cred; | ||
540 | |||
541 | switch (flags) { | 525 | switch (flags) { |
542 | case LSM_SETID_RE: | 526 | case LSM_SETID_RE: |
543 | case LSM_SETID_ID: | 527 | case LSM_SETID_ID: |
544 | case LSM_SETID_RES: | 528 | case LSM_SETID_RES: |
545 | /* Copied from kernel/sys.c:setreuid/setuid/setresuid. */ | 529 | /* Copied from kernel/sys.c:setreuid/setuid/setresuid. */ |
546 | if (!issecure (SECURE_NO_SETUID_FIXUP)) { | 530 | if (!issecure(SECURE_NO_SETUID_FIXUP)) |
547 | cap_emulate_setxuid (old_ruid, old_euid, old_suid); | 531 | cap_emulate_setxuid(new, old); |
548 | } | ||
549 | break; | 532 | break; |
550 | case LSM_SETID_FS: | 533 | case LSM_SETID_FS: |
551 | { | 534 | /* Copied from kernel/sys.c:setfsuid. */ |
552 | uid_t old_fsuid = old_ruid; | ||
553 | |||
554 | /* Copied from kernel/sys.c:setfsuid. */ | ||
555 | 535 | ||
556 | /* | 536 | /* |
557 | * FIXME - is fsuser used for all CAP_FS_MASK capabilities? | 537 | * FIXME - is fsuser used for all CAP_FS_MASK capabilities? |
558 | * if not, we might be a bit too harsh here. | 538 | * if not, we might be a bit too harsh here. |
559 | */ | 539 | */ |
560 | 540 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { | |
561 | if (!issecure (SECURE_NO_SETUID_FIXUP)) { | 541 | if (old->fsuid == 0 && new->fsuid != 0) { |
562 | if (old_fsuid == 0 && cred->fsuid != 0) { | 542 | new->cap_effective = |
563 | cred->cap_effective = | 543 | cap_drop_fs_set(new->cap_effective); |
564 | cap_drop_fs_set( | 544 | } |
565 | cred->cap_effective); | 545 | if (old->fsuid != 0 && new->fsuid == 0) { |
566 | } | 546 | new->cap_effective = |
567 | if (old_fsuid != 0 && cred->fsuid == 0) { | 547 | cap_raise_fs_set(new->cap_effective, |
568 | cred->cap_effective = | 548 | new->cap_permitted); |
569 | cap_raise_fs_set( | ||
570 | cred->cap_effective, | ||
571 | cred->cap_permitted); | ||
572 | } | ||
573 | } | 549 | } |
574 | break; | ||
575 | } | 550 | } |
551 | break; | ||
576 | default: | 552 | default: |
577 | return -EINVAL; | 553 | return -EINVAL; |
578 | } | 554 | } |
@@ -628,13 +604,14 @@ int cap_task_setnice (struct task_struct *p, int nice) | |||
628 | * this task could get inconsistent info. There can be no | 604 | * this task could get inconsistent info. There can be no |
629 | * racing writer bc a task can only change its own caps. | 605 | * racing writer bc a task can only change its own caps. |
630 | */ | 606 | */ |
631 | static long cap_prctl_drop(unsigned long cap) | 607 | static long cap_prctl_drop(struct cred *new, unsigned long cap) |
632 | { | 608 | { |
633 | if (!capable(CAP_SETPCAP)) | 609 | if (!capable(CAP_SETPCAP)) |
634 | return -EPERM; | 610 | return -EPERM; |
635 | if (!cap_valid(cap)) | 611 | if (!cap_valid(cap)) |
636 | return -EINVAL; | 612 | return -EINVAL; |
637 | cap_lower(current->cred->cap_bset, cap); | 613 | |
614 | cap_lower(new->cap_bset, cap); | ||
638 | return 0; | 615 | return 0; |
639 | } | 616 | } |
640 | 617 | ||
@@ -655,22 +632,29 @@ int cap_task_setnice (struct task_struct *p, int nice) | |||
655 | #endif | 632 | #endif |
656 | 633 | ||
657 | int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | 634 | int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, |
658 | unsigned long arg4, unsigned long arg5, long *rc_p) | 635 | unsigned long arg4, unsigned long arg5) |
659 | { | 636 | { |
660 | struct cred *cred = current_cred(); | 637 | struct cred *new; |
661 | long error = 0; | 638 | long error = 0; |
662 | 639 | ||
640 | new = prepare_creds(); | ||
641 | if (!new) | ||
642 | return -ENOMEM; | ||
643 | |||
663 | switch (option) { | 644 | switch (option) { |
664 | case PR_CAPBSET_READ: | 645 | case PR_CAPBSET_READ: |
646 | error = -EINVAL; | ||
665 | if (!cap_valid(arg2)) | 647 | if (!cap_valid(arg2)) |
666 | error = -EINVAL; | 648 | goto error; |
667 | else | 649 | error = !!cap_raised(new->cap_bset, arg2); |
668 | error = !!cap_raised(cred->cap_bset, arg2); | 650 | goto no_change; |
669 | break; | 651 | |
670 | #ifdef CONFIG_SECURITY_FILE_CAPABILITIES | 652 | #ifdef CONFIG_SECURITY_FILE_CAPABILITIES |
671 | case PR_CAPBSET_DROP: | 653 | case PR_CAPBSET_DROP: |
672 | error = cap_prctl_drop(arg2); | 654 | error = cap_prctl_drop(new, arg2); |
673 | break; | 655 | if (error < 0) |
656 | goto error; | ||
657 | goto changed; | ||
674 | 658 | ||
675 | /* | 659 | /* |
676 | * The next four prctl's remain to assist with transitioning a | 660 | * The next four prctl's remain to assist with transitioning a |
@@ -692,12 +676,12 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
692 | * capability-based-privilege environment. | 676 | * capability-based-privilege environment. |
693 | */ | 677 | */ |
694 | case PR_SET_SECUREBITS: | 678 | case PR_SET_SECUREBITS: |
695 | if ((((cred->securebits & SECURE_ALL_LOCKS) >> 1) | 679 | error = -EPERM; |
696 | & (cred->securebits ^ arg2)) /*[1]*/ | 680 | if ((((new->securebits & SECURE_ALL_LOCKS) >> 1) |
697 | || ((cred->securebits & SECURE_ALL_LOCKS | 681 | & (new->securebits ^ arg2)) /*[1]*/ |
698 | & ~arg2)) /*[2]*/ | 682 | || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ |
699 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ | 683 | || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ |
700 | || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0)) { /*[4]*/ | 684 | || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0) /*[4]*/ |
701 | /* | 685 | /* |
702 | * [1] no changing of bits that are locked | 686 | * [1] no changing of bits that are locked |
703 | * [2] no unlocking of locks | 687 | * [2] no unlocking of locks |
@@ -705,50 +689,51 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
705 | * [4] doing anything requires privilege (go read about | 689 | * [4] doing anything requires privilege (go read about |
706 | * the "sendmail capabilities bug") | 690 | * the "sendmail capabilities bug") |
707 | */ | 691 | */ |
708 | error = -EPERM; /* cannot change a locked bit */ | 692 | ) |
709 | } else { | 693 | /* cannot change a locked bit */ |
710 | cred->securebits = arg2; | 694 | goto error; |
711 | } | 695 | new->securebits = arg2; |
712 | break; | 696 | goto changed; |
697 | |||
713 | case PR_GET_SECUREBITS: | 698 | case PR_GET_SECUREBITS: |
714 | error = cred->securebits; | 699 | error = new->securebits; |
715 | break; | 700 | goto no_change; |
716 | 701 | ||
717 | #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ | 702 | #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ |
718 | 703 | ||
719 | case PR_GET_KEEPCAPS: | 704 | case PR_GET_KEEPCAPS: |
720 | if (issecure(SECURE_KEEP_CAPS)) | 705 | if (issecure(SECURE_KEEP_CAPS)) |
721 | error = 1; | 706 | error = 1; |
722 | break; | 707 | goto no_change; |
708 | |||
723 | case PR_SET_KEEPCAPS: | 709 | case PR_SET_KEEPCAPS: |
710 | error = -EINVAL; | ||
724 | if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */ | 711 | if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */ |
725 | error = -EINVAL; | 712 | goto error; |
726 | else if (issecure(SECURE_KEEP_CAPS_LOCKED)) | 713 | error = -EPERM; |
727 | error = -EPERM; | 714 | if (issecure(SECURE_KEEP_CAPS_LOCKED)) |
728 | else if (arg2) | 715 | goto error; |
729 | cred->securebits |= issecure_mask(SECURE_KEEP_CAPS); | 716 | if (arg2) |
717 | new->securebits |= issecure_mask(SECURE_KEEP_CAPS); | ||
730 | else | 718 | else |
731 | cred->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); | 719 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); |
732 | break; | 720 | goto changed; |
733 | 721 | ||
734 | default: | 722 | default: |
735 | /* No functionality available - continue with default */ | 723 | /* No functionality available - continue with default */ |
736 | return 0; | 724 | error = -ENOSYS; |
725 | goto error; | ||
737 | } | 726 | } |
738 | 727 | ||
739 | /* Functionality provided */ | 728 | /* Functionality provided */ |
740 | *rc_p = error; | 729 | changed: |
741 | return 1; | 730 | return commit_creds(new); |
742 | } | 731 | |
743 | 732 | no_change: | |
744 | void cap_task_reparent_to_init (struct task_struct *p) | 733 | error = 0; |
745 | { | 734 | error: |
746 | struct cred *cred = p->cred; | 735 | abort_creds(new); |
747 | 736 | return error; | |
748 | cap_set_init_eff(cred->cap_effective); | ||
749 | cap_clear(cred->cap_inheritable); | ||
750 | cap_set_full(cred->cap_permitted); | ||
751 | p->cred->securebits = SECUREBITS_DEFAULT; | ||
752 | } | 737 | } |
753 | 738 | ||
754 | int cap_syslog (int type) | 739 | int cap_syslog (int type) |
diff --git a/security/keys/internal.h b/security/keys/internal.h index d1586c629788..81932abefe7b 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #ifndef _INTERNAL_H | 12 | #ifndef _INTERNAL_H |
13 | #define _INTERNAL_H | 13 | #define _INTERNAL_H |
14 | 14 | ||
15 | #include <linux/sched.h> | ||
15 | #include <linux/key-type.h> | 16 | #include <linux/key-type.h> |
16 | 17 | ||
17 | static inline __attribute__((format(printf, 1, 2))) | 18 | static inline __attribute__((format(printf, 1, 2))) |
@@ -25,7 +26,7 @@ void no_printk(const char *fmt, ...) | |||
25 | #define kleave(FMT, ...) \ | 26 | #define kleave(FMT, ...) \ |
26 | printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__) | 27 | printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__) |
27 | #define kdebug(FMT, ...) \ | 28 | #define kdebug(FMT, ...) \ |
28 | printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__) | 29 | printk(KERN_DEBUG " "FMT"\n", ##__VA_ARGS__) |
29 | #else | 30 | #else |
30 | #define kenter(FMT, ...) \ | 31 | #define kenter(FMT, ...) \ |
31 | no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) | 32 | no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) |
@@ -97,7 +98,7 @@ extern struct key *keyring_search_instkey(struct key *keyring, | |||
97 | typedef int (*key_match_func_t)(const struct key *, const void *); | 98 | typedef int (*key_match_func_t)(const struct key *, const void *); |
98 | 99 | ||
99 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, | 100 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, |
100 | struct task_struct *tsk, | 101 | const struct cred *cred, |
101 | struct key_type *type, | 102 | struct key_type *type, |
102 | const void *description, | 103 | const void *description, |
103 | key_match_func_t match); | 104 | key_match_func_t match); |
@@ -105,13 +106,13 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
105 | extern key_ref_t search_process_keyrings(struct key_type *type, | 106 | extern key_ref_t search_process_keyrings(struct key_type *type, |
106 | const void *description, | 107 | const void *description, |
107 | key_match_func_t match, | 108 | key_match_func_t match, |
108 | struct task_struct *tsk); | 109 | const struct cred *cred); |
109 | 110 | ||
110 | extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); | 111 | extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); |
111 | 112 | ||
112 | extern int install_user_keyrings(void); | 113 | extern int install_user_keyrings(void); |
113 | extern int install_thread_keyring(void); | 114 | extern int install_thread_keyring_to_cred(struct cred *); |
114 | extern int install_process_keyring(void); | 115 | extern int install_process_keyring_to_cred(struct cred *); |
115 | 116 | ||
116 | extern struct key *request_key_and_link(struct key_type *type, | 117 | extern struct key *request_key_and_link(struct key_type *type, |
117 | const char *description, | 118 | const char *description, |
@@ -130,12 +131,12 @@ extern long join_session_keyring(const char *name); | |||
130 | * check to see whether permission is granted to use a key in the desired way | 131 | * check to see whether permission is granted to use a key in the desired way |
131 | */ | 132 | */ |
132 | extern int key_task_permission(const key_ref_t key_ref, | 133 | extern int key_task_permission(const key_ref_t key_ref, |
133 | struct task_struct *context, | 134 | const struct cred *cred, |
134 | key_perm_t perm); | 135 | key_perm_t perm); |
135 | 136 | ||
136 | static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) | 137 | static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) |
137 | { | 138 | { |
138 | return key_task_permission(key_ref, current, perm); | 139 | return key_task_permission(key_ref, current_cred(), perm); |
139 | } | 140 | } |
140 | 141 | ||
141 | /* required permissions */ | 142 | /* required permissions */ |
@@ -153,7 +154,7 @@ static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) | |||
153 | struct request_key_auth { | 154 | struct request_key_auth { |
154 | struct key *target_key; | 155 | struct key *target_key; |
155 | struct key *dest_keyring; | 156 | struct key *dest_keyring; |
156 | struct task_struct *context; | 157 | const struct cred *cred; |
157 | void *callout_info; | 158 | void *callout_info; |
158 | size_t callout_len; | 159 | size_t callout_len; |
159 | pid_t pid; | 160 | pid_t pid; |
diff --git a/security/keys/key.c b/security/keys/key.c index a6ca39ed3b0e..f76c8a546fd3 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -218,7 +218,7 @@ serial_exists: | |||
218 | * instantiate the key or discard it before returning | 218 | * instantiate the key or discard it before returning |
219 | */ | 219 | */ |
220 | struct key *key_alloc(struct key_type *type, const char *desc, | 220 | struct key *key_alloc(struct key_type *type, const char *desc, |
221 | uid_t uid, gid_t gid, struct task_struct *ctx, | 221 | uid_t uid, gid_t gid, const struct cred *cred, |
222 | key_perm_t perm, unsigned long flags) | 222 | key_perm_t perm, unsigned long flags) |
223 | { | 223 | { |
224 | struct key_user *user = NULL; | 224 | struct key_user *user = NULL; |
@@ -294,7 +294,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
294 | #endif | 294 | #endif |
295 | 295 | ||
296 | /* let the security module know about the key */ | 296 | /* let the security module know about the key */ |
297 | ret = security_key_alloc(key, ctx, flags); | 297 | ret = security_key_alloc(key, cred, flags); |
298 | if (ret < 0) | 298 | if (ret < 0) |
299 | goto security_error; | 299 | goto security_error; |
300 | 300 | ||
@@ -391,7 +391,7 @@ static int __key_instantiate_and_link(struct key *key, | |||
391 | const void *data, | 391 | const void *data, |
392 | size_t datalen, | 392 | size_t datalen, |
393 | struct key *keyring, | 393 | struct key *keyring, |
394 | struct key *instkey) | 394 | struct key *authkey) |
395 | { | 395 | { |
396 | int ret, awaken; | 396 | int ret, awaken; |
397 | 397 | ||
@@ -421,8 +421,8 @@ static int __key_instantiate_and_link(struct key *key, | |||
421 | ret = __key_link(keyring, key); | 421 | ret = __key_link(keyring, key); |
422 | 422 | ||
423 | /* disable the authorisation key */ | 423 | /* disable the authorisation key */ |
424 | if (instkey) | 424 | if (authkey) |
425 | key_revoke(instkey); | 425 | key_revoke(authkey); |
426 | } | 426 | } |
427 | } | 427 | } |
428 | 428 | ||
@@ -444,14 +444,14 @@ int key_instantiate_and_link(struct key *key, | |||
444 | const void *data, | 444 | const void *data, |
445 | size_t datalen, | 445 | size_t datalen, |
446 | struct key *keyring, | 446 | struct key *keyring, |
447 | struct key *instkey) | 447 | struct key *authkey) |
448 | { | 448 | { |
449 | int ret; | 449 | int ret; |
450 | 450 | ||
451 | if (keyring) | 451 | if (keyring) |
452 | down_write(&keyring->sem); | 452 | down_write(&keyring->sem); |
453 | 453 | ||
454 | ret = __key_instantiate_and_link(key, data, datalen, keyring, instkey); | 454 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey); |
455 | 455 | ||
456 | if (keyring) | 456 | if (keyring) |
457 | up_write(&keyring->sem); | 457 | up_write(&keyring->sem); |
@@ -469,7 +469,7 @@ EXPORT_SYMBOL(key_instantiate_and_link); | |||
469 | int key_negate_and_link(struct key *key, | 469 | int key_negate_and_link(struct key *key, |
470 | unsigned timeout, | 470 | unsigned timeout, |
471 | struct key *keyring, | 471 | struct key *keyring, |
472 | struct key *instkey) | 472 | struct key *authkey) |
473 | { | 473 | { |
474 | struct timespec now; | 474 | struct timespec now; |
475 | int ret, awaken; | 475 | int ret, awaken; |
@@ -504,8 +504,8 @@ int key_negate_and_link(struct key *key, | |||
504 | ret = __key_link(keyring, key); | 504 | ret = __key_link(keyring, key); |
505 | 505 | ||
506 | /* disable the authorisation key */ | 506 | /* disable the authorisation key */ |
507 | if (instkey) | 507 | if (authkey) |
508 | key_revoke(instkey); | 508 | key_revoke(authkey); |
509 | } | 509 | } |
510 | 510 | ||
511 | mutex_unlock(&key_construction_mutex); | 511 | mutex_unlock(&key_construction_mutex); |
@@ -743,6 +743,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
743 | key_perm_t perm, | 743 | key_perm_t perm, |
744 | unsigned long flags) | 744 | unsigned long flags) |
745 | { | 745 | { |
746 | const struct cred *cred = current_cred(); | ||
746 | struct key_type *ktype; | 747 | struct key_type *ktype; |
747 | struct key *keyring, *key = NULL; | 748 | struct key *keyring, *key = NULL; |
748 | key_ref_t key_ref; | 749 | key_ref_t key_ref; |
@@ -802,8 +803,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
802 | } | 803 | } |
803 | 804 | ||
804 | /* allocate a new key */ | 805 | /* allocate a new key */ |
805 | key = key_alloc(ktype, description, current_fsuid(), current_fsgid(), | 806 | key = key_alloc(ktype, description, cred->fsuid, cred->fsgid, cred, |
806 | current, perm, flags); | 807 | perm, flags); |
807 | if (IS_ERR(key)) { | 808 | if (IS_ERR(key)) { |
808 | key_ref = ERR_CAST(key); | 809 | key_ref = ERR_CAST(key); |
809 | goto error_3; | 810 | goto error_3; |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 8833b447adef..7c72baa02f2e 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -866,6 +866,23 @@ static long get_instantiation_keyring(key_serial_t ringid, | |||
866 | return -ENOKEY; | 866 | return -ENOKEY; |
867 | } | 867 | } |
868 | 868 | ||
869 | /* | ||
870 | * change the request_key authorisation key on the current process | ||
871 | */ | ||
872 | static int keyctl_change_reqkey_auth(struct key *key) | ||
873 | { | ||
874 | struct cred *new; | ||
875 | |||
876 | new = prepare_creds(); | ||
877 | if (!new) | ||
878 | return -ENOMEM; | ||
879 | |||
880 | key_put(new->request_key_auth); | ||
881 | new->request_key_auth = key_get(key); | ||
882 | |||
883 | return commit_creds(new); | ||
884 | } | ||
885 | |||
869 | /*****************************************************************************/ | 886 | /*****************************************************************************/ |
870 | /* | 887 | /* |
871 | * instantiate the key with the specified payload, and, if one is given, link | 888 | * instantiate the key with the specified payload, and, if one is given, link |
@@ -876,12 +893,15 @@ long keyctl_instantiate_key(key_serial_t id, | |||
876 | size_t plen, | 893 | size_t plen, |
877 | key_serial_t ringid) | 894 | key_serial_t ringid) |
878 | { | 895 | { |
896 | const struct cred *cred = current_cred(); | ||
879 | struct request_key_auth *rka; | 897 | struct request_key_auth *rka; |
880 | struct key *instkey, *dest_keyring; | 898 | struct key *instkey, *dest_keyring; |
881 | void *payload; | 899 | void *payload; |
882 | long ret; | 900 | long ret; |
883 | bool vm = false; | 901 | bool vm = false; |
884 | 902 | ||
903 | kenter("%d,,%zu,%d", id, plen, ringid); | ||
904 | |||
885 | ret = -EINVAL; | 905 | ret = -EINVAL; |
886 | if (plen > 1024 * 1024 - 1) | 906 | if (plen > 1024 * 1024 - 1) |
887 | goto error; | 907 | goto error; |
@@ -889,7 +909,7 @@ long keyctl_instantiate_key(key_serial_t id, | |||
889 | /* the appropriate instantiation authorisation key must have been | 909 | /* the appropriate instantiation authorisation key must have been |
890 | * assumed before calling this */ | 910 | * assumed before calling this */ |
891 | ret = -EPERM; | 911 | ret = -EPERM; |
892 | instkey = current->cred->request_key_auth; | 912 | instkey = cred->request_key_auth; |
893 | if (!instkey) | 913 | if (!instkey) |
894 | goto error; | 914 | goto error; |
895 | 915 | ||
@@ -931,10 +951,8 @@ long keyctl_instantiate_key(key_serial_t id, | |||
931 | 951 | ||
932 | /* discard the assumed authority if it's just been disabled by | 952 | /* discard the assumed authority if it's just been disabled by |
933 | * instantiation of the key */ | 953 | * instantiation of the key */ |
934 | if (ret == 0) { | 954 | if (ret == 0) |
935 | key_put(current->cred->request_key_auth); | 955 | keyctl_change_reqkey_auth(NULL); |
936 | current->cred->request_key_auth = NULL; | ||
937 | } | ||
938 | 956 | ||
939 | error2: | 957 | error2: |
940 | if (!vm) | 958 | if (!vm) |
@@ -953,14 +971,17 @@ error: | |||
953 | */ | 971 | */ |
954 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | 972 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) |
955 | { | 973 | { |
974 | const struct cred *cred = current_cred(); | ||
956 | struct request_key_auth *rka; | 975 | struct request_key_auth *rka; |
957 | struct key *instkey, *dest_keyring; | 976 | struct key *instkey, *dest_keyring; |
958 | long ret; | 977 | long ret; |
959 | 978 | ||
979 | kenter("%d,%u,%d", id, timeout, ringid); | ||
980 | |||
960 | /* the appropriate instantiation authorisation key must have been | 981 | /* the appropriate instantiation authorisation key must have been |
961 | * assumed before calling this */ | 982 | * assumed before calling this */ |
962 | ret = -EPERM; | 983 | ret = -EPERM; |
963 | instkey = current->cred->request_key_auth; | 984 | instkey = cred->request_key_auth; |
964 | if (!instkey) | 985 | if (!instkey) |
965 | goto error; | 986 | goto error; |
966 | 987 | ||
@@ -982,10 +1003,8 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
982 | 1003 | ||
983 | /* discard the assumed authority if it's just been disabled by | 1004 | /* discard the assumed authority if it's just been disabled by |
984 | * instantiation of the key */ | 1005 | * instantiation of the key */ |
985 | if (ret == 0) { | 1006 | if (ret == 0) |
986 | key_put(current->cred->request_key_auth); | 1007 | keyctl_change_reqkey_auth(NULL); |
987 | current->cred->request_key_auth = NULL; | ||
988 | } | ||
989 | 1008 | ||
990 | error: | 1009 | error: |
991 | return ret; | 1010 | return ret; |
@@ -999,36 +1018,56 @@ error: | |||
999 | */ | 1018 | */ |
1000 | long keyctl_set_reqkey_keyring(int reqkey_defl) | 1019 | long keyctl_set_reqkey_keyring(int reqkey_defl) |
1001 | { | 1020 | { |
1002 | struct cred *cred = current->cred; | 1021 | struct cred *new; |
1003 | int ret; | 1022 | int ret, old_setting; |
1023 | |||
1024 | old_setting = current_cred_xxx(jit_keyring); | ||
1025 | |||
1026 | if (reqkey_defl == KEY_REQKEY_DEFL_NO_CHANGE) | ||
1027 | return old_setting; | ||
1028 | |||
1029 | new = prepare_creds(); | ||
1030 | if (!new) | ||
1031 | return -ENOMEM; | ||
1004 | 1032 | ||
1005 | switch (reqkey_defl) { | 1033 | switch (reqkey_defl) { |
1006 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | 1034 | case KEY_REQKEY_DEFL_THREAD_KEYRING: |
1007 | ret = install_thread_keyring(); | 1035 | ret = install_thread_keyring_to_cred(new); |
1008 | if (ret < 0) | 1036 | if (ret < 0) |
1009 | return ret; | 1037 | goto error; |
1010 | goto set; | 1038 | goto set; |
1011 | 1039 | ||
1012 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | 1040 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: |
1013 | ret = install_process_keyring(); | 1041 | ret = install_process_keyring_to_cred(new); |
1014 | if (ret < 0) | 1042 | if (ret < 0) { |
1015 | return ret; | 1043 | if (ret != -EEXIST) |
1044 | goto error; | ||
1045 | ret = 0; | ||
1046 | } | ||
1047 | goto set; | ||
1016 | 1048 | ||
1017 | case KEY_REQKEY_DEFL_DEFAULT: | 1049 | case KEY_REQKEY_DEFL_DEFAULT: |
1018 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | 1050 | case KEY_REQKEY_DEFL_SESSION_KEYRING: |
1019 | case KEY_REQKEY_DEFL_USER_KEYRING: | 1051 | case KEY_REQKEY_DEFL_USER_KEYRING: |
1020 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: | 1052 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: |
1021 | set: | 1053 | case KEY_REQKEY_DEFL_REQUESTOR_KEYRING: |
1022 | cred->jit_keyring = reqkey_defl; | 1054 | goto set; |
1023 | 1055 | ||
1024 | case KEY_REQKEY_DEFL_NO_CHANGE: | 1056 | case KEY_REQKEY_DEFL_NO_CHANGE: |
1025 | return cred->jit_keyring; | ||
1026 | |||
1027 | case KEY_REQKEY_DEFL_GROUP_KEYRING: | 1057 | case KEY_REQKEY_DEFL_GROUP_KEYRING: |
1028 | default: | 1058 | default: |
1029 | return -EINVAL; | 1059 | ret = -EINVAL; |
1060 | goto error; | ||
1030 | } | 1061 | } |
1031 | 1062 | ||
1063 | set: | ||
1064 | new->jit_keyring = reqkey_defl; | ||
1065 | commit_creds(new); | ||
1066 | return old_setting; | ||
1067 | error: | ||
1068 | abort_creds(new); | ||
1069 | return -EINVAL; | ||
1070 | |||
1032 | } /* end keyctl_set_reqkey_keyring() */ | 1071 | } /* end keyctl_set_reqkey_keyring() */ |
1033 | 1072 | ||
1034 | /*****************************************************************************/ | 1073 | /*****************************************************************************/ |
@@ -1087,9 +1126,7 @@ long keyctl_assume_authority(key_serial_t id) | |||
1087 | 1126 | ||
1088 | /* we divest ourselves of authority if given an ID of 0 */ | 1127 | /* we divest ourselves of authority if given an ID of 0 */ |
1089 | if (id == 0) { | 1128 | if (id == 0) { |
1090 | key_put(current->cred->request_key_auth); | 1129 | ret = keyctl_change_reqkey_auth(NULL); |
1091 | current->cred->request_key_auth = NULL; | ||
1092 | ret = 0; | ||
1093 | goto error; | 1130 | goto error; |
1094 | } | 1131 | } |
1095 | 1132 | ||
@@ -1104,10 +1141,12 @@ long keyctl_assume_authority(key_serial_t id) | |||
1104 | goto error; | 1141 | goto error; |
1105 | } | 1142 | } |
1106 | 1143 | ||
1107 | key_put(current->cred->request_key_auth); | 1144 | ret = keyctl_change_reqkey_auth(authkey); |
1108 | current->cred->request_key_auth = authkey; | 1145 | if (ret < 0) |
1109 | ret = authkey->serial; | 1146 | goto error; |
1147 | key_put(authkey); | ||
1110 | 1148 | ||
1149 | ret = authkey->serial; | ||
1111 | error: | 1150 | error: |
1112 | return ret; | 1151 | return ret; |
1113 | 1152 | ||
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index fdf75f901991..ed851574d073 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -245,14 +245,14 @@ static long keyring_read(const struct key *keyring, | |||
245 | * allocate a keyring and link into the destination keyring | 245 | * allocate a keyring and link into the destination keyring |
246 | */ | 246 | */ |
247 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 247 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
248 | struct task_struct *ctx, unsigned long flags, | 248 | const struct cred *cred, unsigned long flags, |
249 | struct key *dest) | 249 | struct key *dest) |
250 | { | 250 | { |
251 | struct key *keyring; | 251 | struct key *keyring; |
252 | int ret; | 252 | int ret; |
253 | 253 | ||
254 | keyring = key_alloc(&key_type_keyring, description, | 254 | keyring = key_alloc(&key_type_keyring, description, |
255 | uid, gid, ctx, | 255 | uid, gid, cred, |
256 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | 256 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, |
257 | flags); | 257 | flags); |
258 | 258 | ||
@@ -281,7 +281,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
281 | * - we propagate the possession attribute from the keyring ref to the key ref | 281 | * - we propagate the possession attribute from the keyring ref to the key ref |
282 | */ | 282 | */ |
283 | key_ref_t keyring_search_aux(key_ref_t keyring_ref, | 283 | key_ref_t keyring_search_aux(key_ref_t keyring_ref, |
284 | struct task_struct *context, | 284 | const struct cred *cred, |
285 | struct key_type *type, | 285 | struct key_type *type, |
286 | const void *description, | 286 | const void *description, |
287 | key_match_func_t match) | 287 | key_match_func_t match) |
@@ -304,7 +304,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
304 | key_check(keyring); | 304 | key_check(keyring); |
305 | 305 | ||
306 | /* top keyring must have search permission to begin the search */ | 306 | /* top keyring must have search permission to begin the search */ |
307 | err = key_task_permission(keyring_ref, context, KEY_SEARCH); | 307 | err = key_task_permission(keyring_ref, cred, KEY_SEARCH); |
308 | if (err < 0) { | 308 | if (err < 0) { |
309 | key_ref = ERR_PTR(err); | 309 | key_ref = ERR_PTR(err); |
310 | goto error; | 310 | goto error; |
@@ -377,7 +377,7 @@ descend: | |||
377 | 377 | ||
378 | /* key must have search permissions */ | 378 | /* key must have search permissions */ |
379 | if (key_task_permission(make_key_ref(key, possessed), | 379 | if (key_task_permission(make_key_ref(key, possessed), |
380 | context, KEY_SEARCH) < 0) | 380 | cred, KEY_SEARCH) < 0) |
381 | continue; | 381 | continue; |
382 | 382 | ||
383 | /* we set a different error code if we pass a negative key */ | 383 | /* we set a different error code if we pass a negative key */ |
@@ -404,7 +404,7 @@ ascend: | |||
404 | continue; | 404 | continue; |
405 | 405 | ||
406 | if (key_task_permission(make_key_ref(key, possessed), | 406 | if (key_task_permission(make_key_ref(key, possessed), |
407 | context, KEY_SEARCH) < 0) | 407 | cred, KEY_SEARCH) < 0) |
408 | continue; | 408 | continue; |
409 | 409 | ||
410 | /* stack the current position */ | 410 | /* stack the current position */ |
@@ -459,7 +459,7 @@ key_ref_t keyring_search(key_ref_t keyring, | |||
459 | if (!type->match) | 459 | if (!type->match) |
460 | return ERR_PTR(-ENOKEY); | 460 | return ERR_PTR(-ENOKEY); |
461 | 461 | ||
462 | return keyring_search_aux(keyring, current, | 462 | return keyring_search_aux(keyring, current->cred, |
463 | type, description, type->match); | 463 | type, description, type->match); |
464 | 464 | ||
465 | } /* end keyring_search() */ | 465 | } /* end keyring_search() */ |
diff --git a/security/keys/permission.c b/security/keys/permission.c index 13c36164f284..5d9fc7b93f2e 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c | |||
@@ -14,24 +14,27 @@ | |||
14 | #include "internal.h" | 14 | #include "internal.h" |
15 | 15 | ||
16 | /*****************************************************************************/ | 16 | /*****************************************************************************/ |
17 | /* | 17 | /** |
18 | * check to see whether permission is granted to use a key in the desired way, | 18 | * key_task_permission - Check a key can be used |
19 | * but permit the security modules to override | 19 | * @key_ref: The key to check |
20 | * @cred: The credentials to use | ||
21 | * @perm: The permissions to check for | ||
22 | * | ||
23 | * Check to see whether permission is granted to use a key in the desired way, | ||
24 | * but permit the security modules to override. | ||
25 | * | ||
26 | * The caller must hold either a ref on cred or must hold the RCU readlock or a | ||
27 | * spinlock. | ||
20 | */ | 28 | */ |
21 | int key_task_permission(const key_ref_t key_ref, | 29 | int key_task_permission(const key_ref_t key_ref, const struct cred *cred, |
22 | struct task_struct *context, | ||
23 | key_perm_t perm) | 30 | key_perm_t perm) |
24 | { | 31 | { |
25 | const struct cred *cred; | ||
26 | struct key *key; | 32 | struct key *key; |
27 | key_perm_t kperm; | 33 | key_perm_t kperm; |
28 | int ret; | 34 | int ret; |
29 | 35 | ||
30 | key = key_ref_to_ptr(key_ref); | 36 | key = key_ref_to_ptr(key_ref); |
31 | 37 | ||
32 | rcu_read_lock(); | ||
33 | cred = __task_cred(context); | ||
34 | |||
35 | /* use the second 8-bits of permissions for keys the caller owns */ | 38 | /* use the second 8-bits of permissions for keys the caller owns */ |
36 | if (key->uid == cred->fsuid) { | 39 | if (key->uid == cred->fsuid) { |
37 | kperm = key->perm >> 16; | 40 | kperm = key->perm >> 16; |
@@ -57,7 +60,6 @@ int key_task_permission(const key_ref_t key_ref, | |||
57 | kperm = key->perm; | 60 | kperm = key->perm; |
58 | 61 | ||
59 | use_these_perms: | 62 | use_these_perms: |
60 | rcu_read_lock(); | ||
61 | 63 | ||
62 | /* use the top 8-bits of permissions for keys the caller possesses | 64 | /* use the top 8-bits of permissions for keys the caller possesses |
63 | * - possessor permissions are additive with other permissions | 65 | * - possessor permissions are additive with other permissions |
@@ -71,7 +73,7 @@ use_these_perms: | |||
71 | return -EACCES; | 73 | return -EACCES; |
72 | 74 | ||
73 | /* let LSM be the final arbiter */ | 75 | /* let LSM be the final arbiter */ |
74 | return security_key_permission(key_ref, context, perm); | 76 | return security_key_permission(key_ref, cred, perm); |
75 | 77 | ||
76 | } /* end key_task_permission() */ | 78 | } /* end key_task_permission() */ |
77 | 79 | ||
diff --git a/security/keys/proc.c b/security/keys/proc.c index f619170da760..7f508def50e3 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -136,8 +136,12 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
136 | int rc; | 136 | int rc; |
137 | 137 | ||
138 | /* check whether the current task is allowed to view the key (assuming | 138 | /* check whether the current task is allowed to view the key (assuming |
139 | * non-possession) */ | 139 | * non-possession) |
140 | rc = key_task_permission(make_key_ref(key, 0), current, KEY_VIEW); | 140 | * - the caller holds a spinlock, and thus the RCU read lock, making our |
141 | * access to __current_cred() safe | ||
142 | */ | ||
143 | rc = key_task_permission(make_key_ref(key, 0), current_cred(), | ||
144 | KEY_VIEW); | ||
141 | if (rc < 0) | 145 | if (rc < 0) |
142 | return 0; | 146 | return 0; |
143 | 147 | ||
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 70ee93406f30..df329f684a65 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -42,11 +42,15 @@ struct key_user root_key_user = { | |||
42 | */ | 42 | */ |
43 | int install_user_keyrings(void) | 43 | int install_user_keyrings(void) |
44 | { | 44 | { |
45 | struct user_struct *user = current->cred->user; | 45 | struct user_struct *user; |
46 | const struct cred *cred; | ||
46 | struct key *uid_keyring, *session_keyring; | 47 | struct key *uid_keyring, *session_keyring; |
47 | char buf[20]; | 48 | char buf[20]; |
48 | int ret; | 49 | int ret; |
49 | 50 | ||
51 | cred = current_cred(); | ||
52 | user = cred->user; | ||
53 | |||
50 | kenter("%p{%u}", user, user->uid); | 54 | kenter("%p{%u}", user, user->uid); |
51 | 55 | ||
52 | if (user->uid_keyring) { | 56 | if (user->uid_keyring) { |
@@ -67,7 +71,7 @@ int install_user_keyrings(void) | |||
67 | uid_keyring = find_keyring_by_name(buf, true); | 71 | uid_keyring = find_keyring_by_name(buf, true); |
68 | if (IS_ERR(uid_keyring)) { | 72 | if (IS_ERR(uid_keyring)) { |
69 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, | 73 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, |
70 | current, KEY_ALLOC_IN_QUOTA, | 74 | cred, KEY_ALLOC_IN_QUOTA, |
71 | NULL); | 75 | NULL); |
72 | if (IS_ERR(uid_keyring)) { | 76 | if (IS_ERR(uid_keyring)) { |
73 | ret = PTR_ERR(uid_keyring); | 77 | ret = PTR_ERR(uid_keyring); |
@@ -83,8 +87,7 @@ int install_user_keyrings(void) | |||
83 | if (IS_ERR(session_keyring)) { | 87 | if (IS_ERR(session_keyring)) { |
84 | session_keyring = | 88 | session_keyring = |
85 | keyring_alloc(buf, user->uid, (gid_t) -1, | 89 | keyring_alloc(buf, user->uid, (gid_t) -1, |
86 | current, KEY_ALLOC_IN_QUOTA, | 90 | cred, KEY_ALLOC_IN_QUOTA, NULL); |
87 | NULL); | ||
88 | if (IS_ERR(session_keyring)) { | 91 | if (IS_ERR(session_keyring)) { |
89 | ret = PTR_ERR(session_keyring); | 92 | ret = PTR_ERR(session_keyring); |
90 | goto error_release; | 93 | goto error_release; |
@@ -116,142 +119,128 @@ error: | |||
116 | return ret; | 119 | return ret; |
117 | } | 120 | } |
118 | 121 | ||
119 | /*****************************************************************************/ | ||
120 | /* | 122 | /* |
121 | * deal with the UID changing | 123 | * install a fresh thread keyring directly to new credentials |
122 | */ | 124 | */ |
123 | void switch_uid_keyring(struct user_struct *new_user) | 125 | int install_thread_keyring_to_cred(struct cred *new) |
124 | { | 126 | { |
125 | #if 0 /* do nothing for now */ | 127 | struct key *keyring; |
126 | struct key *old; | ||
127 | |||
128 | /* switch to the new user's session keyring if we were running under | ||
129 | * root's default session keyring */ | ||
130 | if (new_user->uid != 0 && | ||
131 | current->session_keyring == &root_session_keyring | ||
132 | ) { | ||
133 | atomic_inc(&new_user->session_keyring->usage); | ||
134 | |||
135 | task_lock(current); | ||
136 | old = current->session_keyring; | ||
137 | current->session_keyring = new_user->session_keyring; | ||
138 | task_unlock(current); | ||
139 | 128 | ||
140 | key_put(old); | 129 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, |
141 | } | 130 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
142 | #endif | 131 | if (IS_ERR(keyring)) |
132 | return PTR_ERR(keyring); | ||
143 | 133 | ||
144 | } /* end switch_uid_keyring() */ | 134 | new->thread_keyring = keyring; |
135 | return 0; | ||
136 | } | ||
145 | 137 | ||
146 | /*****************************************************************************/ | ||
147 | /* | 138 | /* |
148 | * install a fresh thread keyring, discarding the old one | 139 | * install a fresh thread keyring, discarding the old one |
149 | */ | 140 | */ |
150 | int install_thread_keyring(void) | 141 | static int install_thread_keyring(void) |
151 | { | 142 | { |
152 | struct task_struct *tsk = current; | 143 | struct cred *new; |
153 | struct key *keyring, *old; | ||
154 | char buf[20]; | ||
155 | int ret; | 144 | int ret; |
156 | 145 | ||
157 | sprintf(buf, "_tid.%u", tsk->pid); | 146 | new = prepare_creds(); |
147 | if (!new) | ||
148 | return -ENOMEM; | ||
158 | 149 | ||
159 | keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk, | 150 | BUG_ON(new->thread_keyring); |
160 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 151 | |
161 | if (IS_ERR(keyring)) { | 152 | ret = install_thread_keyring_to_cred(new); |
162 | ret = PTR_ERR(keyring); | 153 | if (ret < 0) { |
163 | goto error; | 154 | abort_creds(new); |
155 | return ret; | ||
164 | } | 156 | } |
165 | 157 | ||
166 | task_lock(tsk); | 158 | return commit_creds(new); |
167 | old = tsk->cred->thread_keyring; | 159 | } |
168 | tsk->cred->thread_keyring = keyring; | ||
169 | task_unlock(tsk); | ||
170 | 160 | ||
171 | ret = 0; | 161 | /* |
162 | * install a process keyring directly to a credentials struct | ||
163 | * - returns -EEXIST if there was already a process keyring, 0 if one installed, | ||
164 | * and other -ve on any other error | ||
165 | */ | ||
166 | int install_process_keyring_to_cred(struct cred *new) | ||
167 | { | ||
168 | struct key *keyring; | ||
169 | int ret; | ||
172 | 170 | ||
173 | key_put(old); | 171 | if (new->tgcred->process_keyring) |
174 | error: | 172 | return -EEXIST; |
173 | |||
174 | keyring = keyring_alloc("_pid", new->uid, new->gid, | ||
175 | new, KEY_ALLOC_QUOTA_OVERRUN, NULL); | ||
176 | if (IS_ERR(keyring)) | ||
177 | return PTR_ERR(keyring); | ||
178 | |||
179 | spin_lock_irq(&new->tgcred->lock); | ||
180 | if (!new->tgcred->process_keyring) { | ||
181 | new->tgcred->process_keyring = keyring; | ||
182 | keyring = NULL; | ||
183 | ret = 0; | ||
184 | } else { | ||
185 | ret = -EEXIST; | ||
186 | } | ||
187 | spin_unlock_irq(&new->tgcred->lock); | ||
188 | key_put(keyring); | ||
175 | return ret; | 189 | return ret; |
190 | } | ||
176 | 191 | ||
177 | } /* end install_thread_keyring() */ | ||
178 | |||
179 | /*****************************************************************************/ | ||
180 | /* | 192 | /* |
181 | * make sure a process keyring is installed | 193 | * make sure a process keyring is installed |
194 | * - we | ||
182 | */ | 195 | */ |
183 | int install_process_keyring(void) | 196 | static int install_process_keyring(void) |
184 | { | 197 | { |
185 | struct task_struct *tsk = current; | 198 | struct cred *new; |
186 | struct key *keyring; | ||
187 | char buf[20]; | ||
188 | int ret; | 199 | int ret; |
189 | 200 | ||
190 | might_sleep(); | 201 | new = prepare_creds(); |
191 | 202 | if (!new) | |
192 | if (!tsk->cred->tgcred->process_keyring) { | 203 | return -ENOMEM; |
193 | sprintf(buf, "_pid.%u", tsk->tgid); | ||
194 | |||
195 | keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk, | ||
196 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | ||
197 | if (IS_ERR(keyring)) { | ||
198 | ret = PTR_ERR(keyring); | ||
199 | goto error; | ||
200 | } | ||
201 | |||
202 | /* attach keyring */ | ||
203 | spin_lock_irq(&tsk->cred->tgcred->lock); | ||
204 | if (!tsk->cred->tgcred->process_keyring) { | ||
205 | tsk->cred->tgcred->process_keyring = keyring; | ||
206 | keyring = NULL; | ||
207 | } | ||
208 | spin_unlock_irq(&tsk->cred->tgcred->lock); | ||
209 | 204 | ||
210 | key_put(keyring); | 205 | ret = install_process_keyring_to_cred(new); |
206 | if (ret < 0) { | ||
207 | abort_creds(new); | ||
208 | return ret != -EEXIST ?: 0; | ||
211 | } | 209 | } |
212 | 210 | ||
213 | ret = 0; | 211 | return commit_creds(new); |
214 | error: | 212 | } |
215 | return ret; | ||
216 | |||
217 | } /* end install_process_keyring() */ | ||
218 | 213 | ||
219 | /*****************************************************************************/ | ||
220 | /* | 214 | /* |
221 | * install a session keyring, discarding the old one | 215 | * install a session keyring directly to a credentials struct |
222 | * - if a keyring is not supplied, an empty one is invented | ||
223 | */ | 216 | */ |
224 | static int install_session_keyring(struct key *keyring) | 217 | static int install_session_keyring_to_cred(struct cred *cred, |
218 | struct key *keyring) | ||
225 | { | 219 | { |
226 | struct task_struct *tsk = current; | ||
227 | unsigned long flags; | 220 | unsigned long flags; |
228 | struct key *old; | 221 | struct key *old; |
229 | char buf[20]; | ||
230 | 222 | ||
231 | might_sleep(); | 223 | might_sleep(); |
232 | 224 | ||
233 | /* create an empty session keyring */ | 225 | /* create an empty session keyring */ |
234 | if (!keyring) { | 226 | if (!keyring) { |
235 | sprintf(buf, "_ses.%u", tsk->tgid); | ||
236 | |||
237 | flags = KEY_ALLOC_QUOTA_OVERRUN; | 227 | flags = KEY_ALLOC_QUOTA_OVERRUN; |
238 | if (tsk->cred->tgcred->session_keyring) | 228 | if (cred->tgcred->session_keyring) |
239 | flags = KEY_ALLOC_IN_QUOTA; | 229 | flags = KEY_ALLOC_IN_QUOTA; |
240 | 230 | ||
241 | keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, | 231 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, |
242 | tsk, flags, NULL); | 232 | cred, flags, NULL); |
243 | if (IS_ERR(keyring)) | 233 | if (IS_ERR(keyring)) |
244 | return PTR_ERR(keyring); | 234 | return PTR_ERR(keyring); |
245 | } | 235 | } else { |
246 | else { | ||
247 | atomic_inc(&keyring->usage); | 236 | atomic_inc(&keyring->usage); |
248 | } | 237 | } |
249 | 238 | ||
250 | /* install the keyring */ | 239 | /* install the keyring */ |
251 | spin_lock_irq(&tsk->cred->tgcred->lock); | 240 | spin_lock_irq(&cred->tgcred->lock); |
252 | old = tsk->cred->tgcred->session_keyring; | 241 | old = cred->tgcred->session_keyring; |
253 | rcu_assign_pointer(tsk->cred->tgcred->session_keyring, keyring); | 242 | rcu_assign_pointer(cred->tgcred->session_keyring, keyring); |
254 | spin_unlock_irq(&tsk->cred->tgcred->lock); | 243 | spin_unlock_irq(&cred->tgcred->lock); |
255 | 244 | ||
256 | /* we're using RCU on the pointer, but there's no point synchronising | 245 | /* we're using RCU on the pointer, but there's no point synchronising |
257 | * on it if it didn't previously point to anything */ | 246 | * on it if it didn't previously point to anything */ |
@@ -261,38 +250,29 @@ static int install_session_keyring(struct key *keyring) | |||
261 | } | 250 | } |
262 | 251 | ||
263 | return 0; | 252 | return 0; |
253 | } | ||
264 | 254 | ||
265 | } /* end install_session_keyring() */ | ||
266 | |||
267 | /*****************************************************************************/ | ||
268 | /* | 255 | /* |
269 | * copy the keys for fork | 256 | * install a session keyring, discarding the old one |
257 | * - if a keyring is not supplied, an empty one is invented | ||
270 | */ | 258 | */ |
271 | int copy_keys(unsigned long clone_flags, struct task_struct *tsk) | 259 | static int install_session_keyring(struct key *keyring) |
272 | { | 260 | { |
273 | key_check(tsk->cred->thread_keyring); | 261 | struct cred *new; |
274 | key_check(tsk->cred->request_key_auth); | 262 | int ret; |
275 | |||
276 | /* no thread keyring yet */ | ||
277 | tsk->cred->thread_keyring = NULL; | ||
278 | |||
279 | /* copy the request_key() authorisation for this thread */ | ||
280 | key_get(tsk->cred->request_key_auth); | ||
281 | |||
282 | return 0; | ||
283 | 263 | ||
284 | } /* end copy_keys() */ | 264 | new = prepare_creds(); |
265 | if (!new) | ||
266 | return -ENOMEM; | ||
285 | 267 | ||
286 | /*****************************************************************************/ | 268 | ret = install_session_keyring_to_cred(new, NULL); |
287 | /* | 269 | if (ret < 0) { |
288 | * dispose of per-thread keys upon thread exit | 270 | abort_creds(new); |
289 | */ | 271 | return ret; |
290 | void exit_keys(struct task_struct *tsk) | 272 | } |
291 | { | ||
292 | key_put(tsk->cred->thread_keyring); | ||
293 | key_put(tsk->cred->request_key_auth); | ||
294 | 273 | ||
295 | } /* end exit_keys() */ | 274 | return commit_creds(new); |
275 | } | ||
296 | 276 | ||
297 | /*****************************************************************************/ | 277 | /*****************************************************************************/ |
298 | /* | 278 | /* |
@@ -300,38 +280,41 @@ void exit_keys(struct task_struct *tsk) | |||
300 | */ | 280 | */ |
301 | int exec_keys(struct task_struct *tsk) | 281 | int exec_keys(struct task_struct *tsk) |
302 | { | 282 | { |
303 | struct key *old; | 283 | struct thread_group_cred *tgcred = NULL; |
284 | struct cred *new; | ||
304 | 285 | ||
305 | /* newly exec'd tasks don't get a thread keyring */ | 286 | #ifdef CONFIG_KEYS |
306 | task_lock(tsk); | 287 | tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); |
307 | old = tsk->cred->thread_keyring; | 288 | if (!tgcred) |
308 | tsk->cred->thread_keyring = NULL; | 289 | return -ENOMEM; |
309 | task_unlock(tsk); | 290 | #endif |
310 | 291 | ||
311 | key_put(old); | 292 | new = prepare_creds(); |
293 | if (new < 0) | ||
294 | return -ENOMEM; | ||
312 | 295 | ||
313 | /* discard the process keyring from a newly exec'd task */ | 296 | /* newly exec'd tasks don't get a thread keyring */ |
314 | spin_lock_irq(&tsk->cred->tgcred->lock); | 297 | key_put(new->thread_keyring); |
315 | old = tsk->cred->tgcred->process_keyring; | 298 | new->thread_keyring = NULL; |
316 | tsk->cred->tgcred->process_keyring = NULL; | ||
317 | spin_unlock_irq(&tsk->cred->tgcred->lock); | ||
318 | 299 | ||
319 | key_put(old); | 300 | /* create a new per-thread-group creds for all this set of threads to |
301 | * share */ | ||
302 | memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred)); | ||
320 | 303 | ||
321 | return 0; | 304 | atomic_set(&tgcred->usage, 1); |
305 | spin_lock_init(&tgcred->lock); | ||
322 | 306 | ||
323 | } /* end exec_keys() */ | 307 | /* inherit the session keyring; new process keyring */ |
308 | key_get(tgcred->session_keyring); | ||
309 | tgcred->process_keyring = NULL; | ||
324 | 310 | ||
325 | /*****************************************************************************/ | 311 | release_tgcred(new); |
326 | /* | 312 | new->tgcred = tgcred; |
327 | * deal with SUID programs | 313 | |
328 | * - we might want to make this invent a new session keyring | 314 | commit_creds(new); |
329 | */ | ||
330 | int suid_keys(struct task_struct *tsk) | ||
331 | { | ||
332 | return 0; | 315 | return 0; |
333 | 316 | ||
334 | } /* end suid_keys() */ | 317 | } /* end exec_keys() */ |
335 | 318 | ||
336 | /*****************************************************************************/ | 319 | /*****************************************************************************/ |
337 | /* | 320 | /* |
@@ -376,16 +359,13 @@ void key_fsgid_changed(struct task_struct *tsk) | |||
376 | key_ref_t search_process_keyrings(struct key_type *type, | 359 | key_ref_t search_process_keyrings(struct key_type *type, |
377 | const void *description, | 360 | const void *description, |
378 | key_match_func_t match, | 361 | key_match_func_t match, |
379 | struct task_struct *context) | 362 | const struct cred *cred) |
380 | { | 363 | { |
381 | struct request_key_auth *rka; | 364 | struct request_key_auth *rka; |
382 | struct cred *cred; | ||
383 | key_ref_t key_ref, ret, err; | 365 | key_ref_t key_ref, ret, err; |
384 | 366 | ||
385 | might_sleep(); | 367 | might_sleep(); |
386 | 368 | ||
387 | cred = get_task_cred(context); | ||
388 | |||
389 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were | 369 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were |
390 | * searchable, but we failed to find a key or we found a negative key; | 370 | * searchable, but we failed to find a key or we found a negative key; |
391 | * otherwise we want to return a sample error (probably -EACCES) if | 371 | * otherwise we want to return a sample error (probably -EACCES) if |
@@ -401,7 +381,7 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
401 | if (cred->thread_keyring) { | 381 | if (cred->thread_keyring) { |
402 | key_ref = keyring_search_aux( | 382 | key_ref = keyring_search_aux( |
403 | make_key_ref(cred->thread_keyring, 1), | 383 | make_key_ref(cred->thread_keyring, 1), |
404 | context, type, description, match); | 384 | cred, type, description, match); |
405 | if (!IS_ERR(key_ref)) | 385 | if (!IS_ERR(key_ref)) |
406 | goto found; | 386 | goto found; |
407 | 387 | ||
@@ -422,7 +402,7 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
422 | if (cred->tgcred->process_keyring) { | 402 | if (cred->tgcred->process_keyring) { |
423 | key_ref = keyring_search_aux( | 403 | key_ref = keyring_search_aux( |
424 | make_key_ref(cred->tgcred->process_keyring, 1), | 404 | make_key_ref(cred->tgcred->process_keyring, 1), |
425 | context, type, description, match); | 405 | cred, type, description, match); |
426 | if (!IS_ERR(key_ref)) | 406 | if (!IS_ERR(key_ref)) |
427 | goto found; | 407 | goto found; |
428 | 408 | ||
@@ -446,7 +426,7 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
446 | make_key_ref(rcu_dereference( | 426 | make_key_ref(rcu_dereference( |
447 | cred->tgcred->session_keyring), | 427 | cred->tgcred->session_keyring), |
448 | 1), | 428 | 1), |
449 | context, type, description, match); | 429 | cred, type, description, match); |
450 | rcu_read_unlock(); | 430 | rcu_read_unlock(); |
451 | 431 | ||
452 | if (!IS_ERR(key_ref)) | 432 | if (!IS_ERR(key_ref)) |
@@ -468,7 +448,7 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
468 | else if (cred->user->session_keyring) { | 448 | else if (cred->user->session_keyring) { |
469 | key_ref = keyring_search_aux( | 449 | key_ref = keyring_search_aux( |
470 | make_key_ref(cred->user->session_keyring, 1), | 450 | make_key_ref(cred->user->session_keyring, 1), |
471 | context, type, description, match); | 451 | cred, type, description, match); |
472 | if (!IS_ERR(key_ref)) | 452 | if (!IS_ERR(key_ref)) |
473 | goto found; | 453 | goto found; |
474 | 454 | ||
@@ -490,7 +470,7 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
490 | * - we don't permit access to request_key auth keys via this method | 470 | * - we don't permit access to request_key auth keys via this method |
491 | */ | 471 | */ |
492 | if (cred->request_key_auth && | 472 | if (cred->request_key_auth && |
493 | context == current && | 473 | cred == current_cred() && |
494 | type != &key_type_request_key_auth | 474 | type != &key_type_request_key_auth |
495 | ) { | 475 | ) { |
496 | /* defend against the auth key being revoked */ | 476 | /* defend against the auth key being revoked */ |
@@ -500,7 +480,7 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
500 | rka = cred->request_key_auth->payload.data; | 480 | rka = cred->request_key_auth->payload.data; |
501 | 481 | ||
502 | key_ref = search_process_keyrings(type, description, | 482 | key_ref = search_process_keyrings(type, description, |
503 | match, rka->context); | 483 | match, rka->cred); |
504 | 484 | ||
505 | up_read(&cred->request_key_auth->sem); | 485 | up_read(&cred->request_key_auth->sem); |
506 | 486 | ||
@@ -527,7 +507,6 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
527 | key_ref = ret ? ret : err; | 507 | key_ref = ret ? ret : err; |
528 | 508 | ||
529 | found: | 509 | found: |
530 | put_cred(cred); | ||
531 | return key_ref; | 510 | return key_ref; |
532 | 511 | ||
533 | } /* end search_process_keyrings() */ | 512 | } /* end search_process_keyrings() */ |
@@ -552,8 +531,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial, | |||
552 | key_perm_t perm) | 531 | key_perm_t perm) |
553 | { | 532 | { |
554 | struct request_key_auth *rka; | 533 | struct request_key_auth *rka; |
555 | struct task_struct *t = current; | 534 | const struct cred *cred; |
556 | struct cred *cred; | ||
557 | struct key *key; | 535 | struct key *key; |
558 | key_ref_t key_ref, skey_ref; | 536 | key_ref_t key_ref, skey_ref; |
559 | int ret; | 537 | int ret; |
@@ -608,6 +586,7 @@ try_again: | |||
608 | goto error; | 586 | goto error; |
609 | ret = install_session_keyring( | 587 | ret = install_session_keyring( |
610 | cred->user->session_keyring); | 588 | cred->user->session_keyring); |
589 | |||
611 | if (ret < 0) | 590 | if (ret < 0) |
612 | goto error; | 591 | goto error; |
613 | goto reget_creds; | 592 | goto reget_creds; |
@@ -693,7 +672,7 @@ try_again: | |||
693 | /* check to see if we possess the key */ | 672 | /* check to see if we possess the key */ |
694 | skey_ref = search_process_keyrings(key->type, key, | 673 | skey_ref = search_process_keyrings(key->type, key, |
695 | lookup_user_key_possessed, | 674 | lookup_user_key_possessed, |
696 | current); | 675 | cred); |
697 | 676 | ||
698 | if (!IS_ERR(skey_ref)) { | 677 | if (!IS_ERR(skey_ref)) { |
699 | key_put(key); | 678 | key_put(key); |
@@ -725,7 +704,7 @@ try_again: | |||
725 | goto invalid_key; | 704 | goto invalid_key; |
726 | 705 | ||
727 | /* check the permissions */ | 706 | /* check the permissions */ |
728 | ret = key_task_permission(key_ref, t, perm); | 707 | ret = key_task_permission(key_ref, cred, perm); |
729 | if (ret < 0) | 708 | if (ret < 0) |
730 | goto invalid_key; | 709 | goto invalid_key; |
731 | 710 | ||
@@ -755,21 +734,33 @@ reget_creds: | |||
755 | */ | 734 | */ |
756 | long join_session_keyring(const char *name) | 735 | long join_session_keyring(const char *name) |
757 | { | 736 | { |
758 | struct task_struct *tsk = current; | 737 | const struct cred *old; |
759 | struct cred *cred = current->cred; | 738 | struct cred *new; |
760 | struct key *keyring; | 739 | struct key *keyring; |
761 | long ret; | 740 | long ret, serial; |
741 | |||
742 | /* only permit this if there's a single thread in the thread group - | ||
743 | * this avoids us having to adjust the creds on all threads and risking | ||
744 | * ENOMEM */ | ||
745 | if (!is_single_threaded(current)) | ||
746 | return -EMLINK; | ||
747 | |||
748 | new = prepare_creds(); | ||
749 | if (!new) | ||
750 | return -ENOMEM; | ||
751 | old = current_cred(); | ||
762 | 752 | ||
763 | /* if no name is provided, install an anonymous keyring */ | 753 | /* if no name is provided, install an anonymous keyring */ |
764 | if (!name) { | 754 | if (!name) { |
765 | ret = install_session_keyring(NULL); | 755 | ret = install_session_keyring_to_cred(new, NULL); |
766 | if (ret < 0) | 756 | if (ret < 0) |
767 | goto error; | 757 | goto error; |
768 | 758 | ||
769 | rcu_read_lock(); | 759 | serial = new->tgcred->session_keyring->serial; |
770 | ret = rcu_dereference(cred->tgcred->session_keyring)->serial; | 760 | ret = commit_creds(new); |
771 | rcu_read_unlock(); | 761 | if (ret == 0) |
772 | goto error; | 762 | ret = serial; |
763 | goto okay; | ||
773 | } | 764 | } |
774 | 765 | ||
775 | /* allow the user to join or create a named keyring */ | 766 | /* allow the user to join or create a named keyring */ |
@@ -779,29 +770,33 @@ long join_session_keyring(const char *name) | |||
779 | keyring = find_keyring_by_name(name, false); | 770 | keyring = find_keyring_by_name(name, false); |
780 | if (PTR_ERR(keyring) == -ENOKEY) { | 771 | if (PTR_ERR(keyring) == -ENOKEY) { |
781 | /* not found - try and create a new one */ | 772 | /* not found - try and create a new one */ |
782 | keyring = keyring_alloc(name, cred->uid, cred->gid, tsk, | 773 | keyring = keyring_alloc(name, old->uid, old->gid, old, |
783 | KEY_ALLOC_IN_QUOTA, NULL); | 774 | KEY_ALLOC_IN_QUOTA, NULL); |
784 | if (IS_ERR(keyring)) { | 775 | if (IS_ERR(keyring)) { |
785 | ret = PTR_ERR(keyring); | 776 | ret = PTR_ERR(keyring); |
786 | goto error2; | 777 | goto error2; |
787 | } | 778 | } |
788 | } | 779 | } else if (IS_ERR(keyring)) { |
789 | else if (IS_ERR(keyring)) { | ||
790 | ret = PTR_ERR(keyring); | 780 | ret = PTR_ERR(keyring); |
791 | goto error2; | 781 | goto error2; |
792 | } | 782 | } |
793 | 783 | ||
794 | /* we've got a keyring - now to install it */ | 784 | /* we've got a keyring - now to install it */ |
795 | ret = install_session_keyring(keyring); | 785 | ret = install_session_keyring_to_cred(new, keyring); |
796 | if (ret < 0) | 786 | if (ret < 0) |
797 | goto error2; | 787 | goto error2; |
798 | 788 | ||
789 | commit_creds(new); | ||
790 | mutex_unlock(&key_session_mutex); | ||
791 | |||
799 | ret = keyring->serial; | 792 | ret = keyring->serial; |
800 | key_put(keyring); | 793 | key_put(keyring); |
794 | okay: | ||
795 | return ret; | ||
801 | 796 | ||
802 | error2: | 797 | error2: |
803 | mutex_unlock(&key_session_mutex); | 798 | mutex_unlock(&key_session_mutex); |
804 | error: | 799 | error: |
800 | abort_creds(new); | ||
805 | return ret; | 801 | return ret; |
806 | 802 | } | |
807 | } /* end join_session_keyring() */ | ||
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 3d12558362df..0e04f72ef2d4 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -83,8 +83,10 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
83 | /* allocate a new session keyring */ | 83 | /* allocate a new session keyring */ |
84 | sprintf(desc, "_req.%u", key->serial); | 84 | sprintf(desc, "_req.%u", key->serial); |
85 | 85 | ||
86 | keyring = keyring_alloc(desc, current_fsuid(), current_fsgid(), current, | 86 | cred = get_current_cred(); |
87 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, | ||
87 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 88 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
89 | put_cred(cred); | ||
88 | if (IS_ERR(keyring)) { | 90 | if (IS_ERR(keyring)) { |
89 | ret = PTR_ERR(keyring); | 91 | ret = PTR_ERR(keyring); |
90 | goto error_alloc; | 92 | goto error_alloc; |
@@ -104,8 +106,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
104 | 106 | ||
105 | /* we specify the process's default keyrings */ | 107 | /* we specify the process's default keyrings */ |
106 | sprintf(keyring_str[0], "%d", | 108 | sprintf(keyring_str[0], "%d", |
107 | cred->thread_keyring ? | 109 | cred->thread_keyring ? cred->thread_keyring->serial : 0); |
108 | cred->thread_keyring->serial : 0); | ||
109 | 110 | ||
110 | prkey = 0; | 111 | prkey = 0; |
111 | if (cred->tgcred->process_keyring) | 112 | if (cred->tgcred->process_keyring) |
@@ -155,8 +156,8 @@ error_link: | |||
155 | key_put(keyring); | 156 | key_put(keyring); |
156 | 157 | ||
157 | error_alloc: | 158 | error_alloc: |
158 | kleave(" = %d", ret); | ||
159 | complete_request_key(cons, ret); | 159 | complete_request_key(cons, ret); |
160 | kleave(" = %d", ret); | ||
160 | return ret; | 161 | return ret; |
161 | } | 162 | } |
162 | 163 | ||
@@ -295,6 +296,7 @@ static int construct_alloc_key(struct key_type *type, | |||
295 | struct key_user *user, | 296 | struct key_user *user, |
296 | struct key **_key) | 297 | struct key **_key) |
297 | { | 298 | { |
299 | const struct cred *cred = current_cred(); | ||
298 | struct key *key; | 300 | struct key *key; |
299 | key_ref_t key_ref; | 301 | key_ref_t key_ref; |
300 | 302 | ||
@@ -302,9 +304,8 @@ static int construct_alloc_key(struct key_type *type, | |||
302 | 304 | ||
303 | mutex_lock(&user->cons_lock); | 305 | mutex_lock(&user->cons_lock); |
304 | 306 | ||
305 | key = key_alloc(type, description, | 307 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, |
306 | current_fsuid(), current_fsgid(), current, KEY_POS_ALL, | 308 | KEY_POS_ALL, flags); |
307 | flags); | ||
308 | if (IS_ERR(key)) | 309 | if (IS_ERR(key)) |
309 | goto alloc_failed; | 310 | goto alloc_failed; |
310 | 311 | ||
@@ -317,8 +318,7 @@ static int construct_alloc_key(struct key_type *type, | |||
317 | * waited for locks */ | 318 | * waited for locks */ |
318 | mutex_lock(&key_construction_mutex); | 319 | mutex_lock(&key_construction_mutex); |
319 | 320 | ||
320 | key_ref = search_process_keyrings(type, description, type->match, | 321 | key_ref = search_process_keyrings(type, description, type->match, cred); |
321 | current); | ||
322 | if (!IS_ERR(key_ref)) | 322 | if (!IS_ERR(key_ref)) |
323 | goto key_already_present; | 323 | goto key_already_present; |
324 | 324 | ||
@@ -363,6 +363,8 @@ static struct key *construct_key_and_link(struct key_type *type, | |||
363 | struct key *key; | 363 | struct key *key; |
364 | int ret; | 364 | int ret; |
365 | 365 | ||
366 | kenter(""); | ||
367 | |||
366 | user = key_user_lookup(current_fsuid()); | 368 | user = key_user_lookup(current_fsuid()); |
367 | if (!user) | 369 | if (!user) |
368 | return ERR_PTR(-ENOMEM); | 370 | return ERR_PTR(-ENOMEM); |
@@ -376,17 +378,21 @@ static struct key *construct_key_and_link(struct key_type *type, | |||
376 | if (ret == 0) { | 378 | if (ret == 0) { |
377 | ret = construct_key(key, callout_info, callout_len, aux, | 379 | ret = construct_key(key, callout_info, callout_len, aux, |
378 | dest_keyring); | 380 | dest_keyring); |
379 | if (ret < 0) | 381 | if (ret < 0) { |
382 | kdebug("cons failed"); | ||
380 | goto construction_failed; | 383 | goto construction_failed; |
384 | } | ||
381 | } | 385 | } |
382 | 386 | ||
383 | key_put(dest_keyring); | 387 | key_put(dest_keyring); |
388 | kleave(" = key %d", key_serial(key)); | ||
384 | return key; | 389 | return key; |
385 | 390 | ||
386 | construction_failed: | 391 | construction_failed: |
387 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); | 392 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); |
388 | key_put(key); | 393 | key_put(key); |
389 | key_put(dest_keyring); | 394 | key_put(dest_keyring); |
395 | kleave(" = %d", ret); | ||
390 | return ERR_PTR(ret); | 396 | return ERR_PTR(ret); |
391 | } | 397 | } |
392 | 398 | ||
@@ -405,6 +411,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
405 | struct key *dest_keyring, | 411 | struct key *dest_keyring, |
406 | unsigned long flags) | 412 | unsigned long flags) |
407 | { | 413 | { |
414 | const struct cred *cred = current_cred(); | ||
408 | struct key *key; | 415 | struct key *key; |
409 | key_ref_t key_ref; | 416 | key_ref_t key_ref; |
410 | 417 | ||
@@ -414,7 +421,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
414 | 421 | ||
415 | /* search all the process keyrings for a key */ | 422 | /* search all the process keyrings for a key */ |
416 | key_ref = search_process_keyrings(type, description, type->match, | 423 | key_ref = search_process_keyrings(type, description, type->match, |
417 | current); | 424 | cred); |
418 | 425 | ||
419 | if (!IS_ERR(key_ref)) { | 426 | if (!IS_ERR(key_ref)) { |
420 | key = key_ref_to_ptr(key_ref); | 427 | key = key_ref_to_ptr(key_ref); |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 2125579d5d73..86747151ee5b 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -105,9 +105,9 @@ static void request_key_auth_revoke(struct key *key) | |||
105 | 105 | ||
106 | kenter("{%d}", key->serial); | 106 | kenter("{%d}", key->serial); |
107 | 107 | ||
108 | if (rka->context) { | 108 | if (rka->cred) { |
109 | put_task_struct(rka->context); | 109 | put_cred(rka->cred); |
110 | rka->context = NULL; | 110 | rka->cred = NULL; |
111 | } | 111 | } |
112 | 112 | ||
113 | } /* end request_key_auth_revoke() */ | 113 | } /* end request_key_auth_revoke() */ |
@@ -122,9 +122,9 @@ static void request_key_auth_destroy(struct key *key) | |||
122 | 122 | ||
123 | kenter("{%d}", key->serial); | 123 | kenter("{%d}", key->serial); |
124 | 124 | ||
125 | if (rka->context) { | 125 | if (rka->cred) { |
126 | put_task_struct(rka->context); | 126 | put_cred(rka->cred); |
127 | rka->context = NULL; | 127 | rka->cred = NULL; |
128 | } | 128 | } |
129 | 129 | ||
130 | key_put(rka->target_key); | 130 | key_put(rka->target_key); |
@@ -143,6 +143,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, | |||
143 | size_t callout_len, struct key *dest_keyring) | 143 | size_t callout_len, struct key *dest_keyring) |
144 | { | 144 | { |
145 | struct request_key_auth *rka, *irka; | 145 | struct request_key_auth *rka, *irka; |
146 | const struct cred *cred = current->cred; | ||
146 | struct key *authkey = NULL; | 147 | struct key *authkey = NULL; |
147 | char desc[20]; | 148 | char desc[20]; |
148 | int ret; | 149 | int ret; |
@@ -164,28 +165,25 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, | |||
164 | 165 | ||
165 | /* see if the calling process is already servicing the key request of | 166 | /* see if the calling process is already servicing the key request of |
166 | * another process */ | 167 | * another process */ |
167 | if (current->cred->request_key_auth) { | 168 | if (cred->request_key_auth) { |
168 | /* it is - use that instantiation context here too */ | 169 | /* it is - use that instantiation context here too */ |
169 | down_read(¤t->cred->request_key_auth->sem); | 170 | down_read(&cred->request_key_auth->sem); |
170 | 171 | ||
171 | /* if the auth key has been revoked, then the key we're | 172 | /* if the auth key has been revoked, then the key we're |
172 | * servicing is already instantiated */ | 173 | * servicing is already instantiated */ |
173 | if (test_bit(KEY_FLAG_REVOKED, | 174 | if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags)) |
174 | ¤t->cred->request_key_auth->flags)) | ||
175 | goto auth_key_revoked; | 175 | goto auth_key_revoked; |
176 | 176 | ||
177 | irka = current->cred->request_key_auth->payload.data; | 177 | irka = cred->request_key_auth->payload.data; |
178 | rka->context = irka->context; | 178 | rka->cred = get_cred(irka->cred); |
179 | rka->pid = irka->pid; | 179 | rka->pid = irka->pid; |
180 | get_task_struct(rka->context); | ||
181 | 180 | ||
182 | up_read(¤t->cred->request_key_auth->sem); | 181 | up_read(&cred->request_key_auth->sem); |
183 | } | 182 | } |
184 | else { | 183 | else { |
185 | /* it isn't - use this process as the context */ | 184 | /* it isn't - use this process as the context */ |
186 | rka->context = current; | 185 | rka->cred = get_cred(cred); |
187 | rka->pid = current->pid; | 186 | rka->pid = current->pid; |
188 | get_task_struct(rka->context); | ||
189 | } | 187 | } |
190 | 188 | ||
191 | rka->target_key = key_get(target); | 189 | rka->target_key = key_get(target); |
@@ -197,7 +195,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, | |||
197 | sprintf(desc, "%x", target->serial); | 195 | sprintf(desc, "%x", target->serial); |
198 | 196 | ||
199 | authkey = key_alloc(&key_type_request_key_auth, desc, | 197 | authkey = key_alloc(&key_type_request_key_auth, desc, |
200 | current_fsuid(), current_fsgid(), current, | 198 | cred->fsuid, cred->fsgid, cred, |
201 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | | 199 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | |
202 | KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); | 200 | KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); |
203 | if (IS_ERR(authkey)) { | 201 | if (IS_ERR(authkey)) { |
@@ -205,16 +203,16 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, | |||
205 | goto error_alloc; | 203 | goto error_alloc; |
206 | } | 204 | } |
207 | 205 | ||
208 | /* construct and attach to the keyring */ | 206 | /* construct the auth key */ |
209 | ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL); | 207 | ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL); |
210 | if (ret < 0) | 208 | if (ret < 0) |
211 | goto error_inst; | 209 | goto error_inst; |
212 | 210 | ||
213 | kleave(" = {%d}", authkey->serial); | 211 | kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage)); |
214 | return authkey; | 212 | return authkey; |
215 | 213 | ||
216 | auth_key_revoked: | 214 | auth_key_revoked: |
217 | up_read(¤t->cred->request_key_auth->sem); | 215 | up_read(&cred->request_key_auth->sem); |
218 | kfree(rka->callout_info); | 216 | kfree(rka->callout_info); |
219 | kfree(rka); | 217 | kfree(rka); |
220 | kleave("= -EKEYREVOKED"); | 218 | kleave("= -EKEYREVOKED"); |
@@ -257,6 +255,7 @@ static int key_get_instantiation_authkey_match(const struct key *key, | |||
257 | */ | 255 | */ |
258 | struct key *key_get_instantiation_authkey(key_serial_t target_id) | 256 | struct key *key_get_instantiation_authkey(key_serial_t target_id) |
259 | { | 257 | { |
258 | const struct cred *cred = current_cred(); | ||
260 | struct key *authkey; | 259 | struct key *authkey; |
261 | key_ref_t authkey_ref; | 260 | key_ref_t authkey_ref; |
262 | 261 | ||
@@ -264,7 +263,7 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) | |||
264 | &key_type_request_key_auth, | 263 | &key_type_request_key_auth, |
265 | (void *) (unsigned long) target_id, | 264 | (void *) (unsigned long) target_id, |
266 | key_get_instantiation_authkey_match, | 265 | key_get_instantiation_authkey_match, |
267 | current); | 266 | cred); |
268 | 267 | ||
269 | if (IS_ERR(authkey_ref)) { | 268 | if (IS_ERR(authkey_ref)) { |
270 | authkey = ERR_CAST(authkey_ref); | 269 | authkey = ERR_CAST(authkey_ref); |
diff --git a/security/security.c b/security/security.c index f40a0a04c3c2..a55d739c6864 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -145,18 +145,13 @@ int security_capget(struct task_struct *target, | |||
145 | return security_ops->capget(target, effective, inheritable, permitted); | 145 | return security_ops->capget(target, effective, inheritable, permitted); |
146 | } | 146 | } |
147 | 147 | ||
148 | int security_capset_check(const kernel_cap_t *effective, | 148 | int security_capset(struct cred *new, const struct cred *old, |
149 | const kernel_cap_t *inheritable, | 149 | const kernel_cap_t *effective, |
150 | const kernel_cap_t *permitted) | 150 | const kernel_cap_t *inheritable, |
151 | const kernel_cap_t *permitted) | ||
151 | { | 152 | { |
152 | return security_ops->capset_check(effective, inheritable, permitted); | 153 | return security_ops->capset(new, old, |
153 | } | 154 | effective, inheritable, permitted); |
154 | |||
155 | void security_capset_set(const kernel_cap_t *effective, | ||
156 | const kernel_cap_t *inheritable, | ||
157 | const kernel_cap_t *permitted) | ||
158 | { | ||
159 | security_ops->capset_set(effective, inheritable, permitted); | ||
160 | } | 155 | } |
161 | 156 | ||
162 | int security_capable(struct task_struct *tsk, int cap) | 157 | int security_capable(struct task_struct *tsk, int cap) |
@@ -228,9 +223,9 @@ void security_bprm_free(struct linux_binprm *bprm) | |||
228 | security_ops->bprm_free_security(bprm); | 223 | security_ops->bprm_free_security(bprm); |
229 | } | 224 | } |
230 | 225 | ||
231 | void security_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | 226 | int security_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) |
232 | { | 227 | { |
233 | security_ops->bprm_apply_creds(bprm, unsafe); | 228 | return security_ops->bprm_apply_creds(bprm, unsafe); |
234 | } | 229 | } |
235 | 230 | ||
236 | void security_bprm_post_apply_creds(struct linux_binprm *bprm) | 231 | void security_bprm_post_apply_creds(struct linux_binprm *bprm) |
@@ -616,14 +611,19 @@ int security_task_create(unsigned long clone_flags) | |||
616 | return security_ops->task_create(clone_flags); | 611 | return security_ops->task_create(clone_flags); |
617 | } | 612 | } |
618 | 613 | ||
619 | int security_cred_alloc(struct cred *cred) | 614 | void security_cred_free(struct cred *cred) |
620 | { | 615 | { |
621 | return security_ops->cred_alloc_security(cred); | 616 | security_ops->cred_free(cred); |
622 | } | 617 | } |
623 | 618 | ||
624 | void security_cred_free(struct cred *cred) | 619 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) |
625 | { | 620 | { |
626 | security_ops->cred_free(cred); | 621 | return security_ops->cred_prepare(new, old, gfp); |
622 | } | ||
623 | |||
624 | void security_commit_creds(struct cred *new, const struct cred *old) | ||
625 | { | ||
626 | return security_ops->cred_commit(new, old); | ||
627 | } | 627 | } |
628 | 628 | ||
629 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 629 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) |
@@ -631,10 +631,10 @@ int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | |||
631 | return security_ops->task_setuid(id0, id1, id2, flags); | 631 | return security_ops->task_setuid(id0, id1, id2, flags); |
632 | } | 632 | } |
633 | 633 | ||
634 | int security_task_post_setuid(uid_t old_ruid, uid_t old_euid, | 634 | int security_task_fix_setuid(struct cred *new, const struct cred *old, |
635 | uid_t old_suid, int flags) | 635 | int flags) |
636 | { | 636 | { |
637 | return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, flags); | 637 | return security_ops->task_fix_setuid(new, old, flags); |
638 | } | 638 | } |
639 | 639 | ||
640 | int security_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) | 640 | int security_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) |
@@ -716,14 +716,9 @@ int security_task_wait(struct task_struct *p) | |||
716 | } | 716 | } |
717 | 717 | ||
718 | int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, | 718 | int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, |
719 | unsigned long arg4, unsigned long arg5, long *rc_p) | 719 | unsigned long arg4, unsigned long arg5) |
720 | { | ||
721 | return security_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p); | ||
722 | } | ||
723 | |||
724 | void security_task_reparent_to_init(struct task_struct *p) | ||
725 | { | 720 | { |
726 | security_ops->task_reparent_to_init(p); | 721 | return security_ops->task_prctl(option, arg2, arg3, arg4, arg5); |
727 | } | 722 | } |
728 | 723 | ||
729 | void security_task_to_inode(struct task_struct *p, struct inode *inode) | 724 | void security_task_to_inode(struct task_struct *p, struct inode *inode) |
@@ -1123,9 +1118,10 @@ EXPORT_SYMBOL(security_skb_classify_flow); | |||
1123 | 1118 | ||
1124 | #ifdef CONFIG_KEYS | 1119 | #ifdef CONFIG_KEYS |
1125 | 1120 | ||
1126 | int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long flags) | 1121 | int security_key_alloc(struct key *key, const struct cred *cred, |
1122 | unsigned long flags) | ||
1127 | { | 1123 | { |
1128 | return security_ops->key_alloc(key, tsk, flags); | 1124 | return security_ops->key_alloc(key, cred, flags); |
1129 | } | 1125 | } |
1130 | 1126 | ||
1131 | void security_key_free(struct key *key) | 1127 | void security_key_free(struct key *key) |
@@ -1134,9 +1130,9 @@ void security_key_free(struct key *key) | |||
1134 | } | 1130 | } |
1135 | 1131 | ||
1136 | int security_key_permission(key_ref_t key_ref, | 1132 | int security_key_permission(key_ref_t key_ref, |
1137 | struct task_struct *context, key_perm_t perm) | 1133 | const struct cred *cred, key_perm_t perm) |
1138 | { | 1134 | { |
1139 | return security_ops->key_permission(key_ref, context, perm); | 1135 | return security_ops->key_permission(key_ref, cred, perm); |
1140 | } | 1136 | } |
1141 | 1137 | ||
1142 | int security_key_getsecurity(struct key *key, char **_buffer) | 1138 | int security_key_getsecurity(struct key *key, char **_buffer) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f20cbd681ba6..c71bba78872f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -156,20 +156,20 @@ static int selinux_secmark_enabled(void) | |||
156 | return (atomic_read(&selinux_secmark_refcount) > 0); | 156 | return (atomic_read(&selinux_secmark_refcount) > 0); |
157 | } | 157 | } |
158 | 158 | ||
159 | /* Allocate and free functions for each kind of security blob. */ | 159 | /* |
160 | 160 | * initialise the security for the init task | |
161 | static int cred_alloc_security(struct cred *cred) | 161 | */ |
162 | static void cred_init_security(void) | ||
162 | { | 163 | { |
164 | struct cred *cred = (struct cred *) current->cred; | ||
163 | struct task_security_struct *tsec; | 165 | struct task_security_struct *tsec; |
164 | 166 | ||
165 | tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); | 167 | tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); |
166 | if (!tsec) | 168 | if (!tsec) |
167 | return -ENOMEM; | 169 | panic("SELinux: Failed to initialize initial task.\n"); |
168 | 170 | ||
169 | tsec->osid = tsec->sid = SECINITSID_UNLABELED; | 171 | tsec->osid = tsec->sid = SECINITSID_KERNEL; |
170 | cred->security = tsec; | 172 | cred->security = tsec; |
171 | |||
172 | return 0; | ||
173 | } | 173 | } |
174 | 174 | ||
175 | /* | 175 | /* |
@@ -1379,6 +1379,19 @@ static inline u32 signal_to_av(int sig) | |||
1379 | } | 1379 | } |
1380 | 1380 | ||
1381 | /* | 1381 | /* |
1382 | * Check permission between a pair of credentials | ||
1383 | * fork check, ptrace check, etc. | ||
1384 | */ | ||
1385 | static int cred_has_perm(const struct cred *actor, | ||
1386 | const struct cred *target, | ||
1387 | u32 perms) | ||
1388 | { | ||
1389 | u32 asid = cred_sid(actor), tsid = cred_sid(target); | ||
1390 | |||
1391 | return avc_has_perm(asid, tsid, SECCLASS_PROCESS, perms, NULL); | ||
1392 | } | ||
1393 | |||
1394 | /* | ||
1382 | * Check permission between a pair of tasks, e.g. signal checks, | 1395 | * Check permission between a pair of tasks, e.g. signal checks, |
1383 | * fork check, ptrace check, etc. | 1396 | * fork check, ptrace check, etc. |
1384 | * tsk1 is the actor and tsk2 is the target | 1397 | * tsk1 is the actor and tsk2 is the target |
@@ -1820,24 +1833,19 @@ static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, | |||
1820 | return secondary_ops->capget(target, effective, inheritable, permitted); | 1833 | return secondary_ops->capget(target, effective, inheritable, permitted); |
1821 | } | 1834 | } |
1822 | 1835 | ||
1823 | static int selinux_capset_check(const kernel_cap_t *effective, | 1836 | static int selinux_capset(struct cred *new, const struct cred *old, |
1824 | const kernel_cap_t *inheritable, | 1837 | const kernel_cap_t *effective, |
1825 | const kernel_cap_t *permitted) | 1838 | const kernel_cap_t *inheritable, |
1839 | const kernel_cap_t *permitted) | ||
1826 | { | 1840 | { |
1827 | int error; | 1841 | int error; |
1828 | 1842 | ||
1829 | error = secondary_ops->capset_check(effective, inheritable, permitted); | 1843 | error = secondary_ops->capset(new, old, |
1844 | effective, inheritable, permitted); | ||
1830 | if (error) | 1845 | if (error) |
1831 | return error; | 1846 | return error; |
1832 | 1847 | ||
1833 | return task_has_perm(current, current, PROCESS__SETCAP); | 1848 | return cred_has_perm(old, new, PROCESS__SETCAP); |
1834 | } | ||
1835 | |||
1836 | static void selinux_capset_set(const kernel_cap_t *effective, | ||
1837 | const kernel_cap_t *inheritable, | ||
1838 | const kernel_cap_t *permitted) | ||
1839 | { | ||
1840 | secondary_ops->capset_set(effective, inheritable, permitted); | ||
1841 | } | 1849 | } |
1842 | 1850 | ||
1843 | static int selinux_capable(struct task_struct *tsk, int cap, int audit) | 1851 | static int selinux_capable(struct task_struct *tsk, int cap, int audit) |
@@ -2244,16 +2252,23 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2244 | spin_unlock(&files->file_lock); | 2252 | spin_unlock(&files->file_lock); |
2245 | } | 2253 | } |
2246 | 2254 | ||
2247 | static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | 2255 | static int selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) |
2248 | { | 2256 | { |
2249 | struct task_security_struct *tsec; | 2257 | struct task_security_struct *tsec; |
2250 | struct bprm_security_struct *bsec; | 2258 | struct bprm_security_struct *bsec; |
2259 | struct cred *new; | ||
2251 | u32 sid; | 2260 | u32 sid; |
2252 | int rc; | 2261 | int rc; |
2253 | 2262 | ||
2254 | secondary_ops->bprm_apply_creds(bprm, unsafe); | 2263 | rc = secondary_ops->bprm_apply_creds(bprm, unsafe); |
2264 | if (rc < 0) | ||
2265 | return rc; | ||
2255 | 2266 | ||
2256 | tsec = current_security(); | 2267 | new = prepare_creds(); |
2268 | if (!new) | ||
2269 | return -ENOMEM; | ||
2270 | |||
2271 | tsec = new->security; | ||
2257 | 2272 | ||
2258 | bsec = bprm->security; | 2273 | bsec = bprm->security; |
2259 | sid = bsec->sid; | 2274 | sid = bsec->sid; |
@@ -2268,7 +2283,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | |||
2268 | PROCESS__SHARE, NULL); | 2283 | PROCESS__SHARE, NULL); |
2269 | if (rc) { | 2284 | if (rc) { |
2270 | bsec->unsafe = 1; | 2285 | bsec->unsafe = 1; |
2271 | return; | 2286 | goto out; |
2272 | } | 2287 | } |
2273 | } | 2288 | } |
2274 | 2289 | ||
@@ -2292,12 +2307,16 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | |||
2292 | PROCESS__PTRACE, NULL); | 2307 | PROCESS__PTRACE, NULL); |
2293 | if (rc) { | 2308 | if (rc) { |
2294 | bsec->unsafe = 1; | 2309 | bsec->unsafe = 1; |
2295 | return; | 2310 | goto out; |
2296 | } | 2311 | } |
2297 | } | 2312 | } |
2298 | } | 2313 | } |
2299 | tsec->sid = sid; | 2314 | tsec->sid = sid; |
2300 | } | 2315 | } |
2316 | |||
2317 | out: | ||
2318 | commit_creds(new); | ||
2319 | return 0; | ||
2301 | } | 2320 | } |
2302 | 2321 | ||
2303 | /* | 2322 | /* |
@@ -3021,6 +3040,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
3021 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 3040 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
3022 | { | 3041 | { |
3023 | const struct cred *cred = current_cred(); | 3042 | const struct cred *cred = current_cred(); |
3043 | int rc = 0; | ||
3024 | 3044 | ||
3025 | #ifndef CONFIG_PPC32 | 3045 | #ifndef CONFIG_PPC32 |
3026 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 3046 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { |
@@ -3029,9 +3049,9 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
3029 | * private file mapping that will also be writable. | 3049 | * private file mapping that will also be writable. |
3030 | * This has an additional check. | 3050 | * This has an additional check. |
3031 | */ | 3051 | */ |
3032 | int rc = task_has_perm(current, current, PROCESS__EXECMEM); | 3052 | rc = cred_has_perm(cred, cred, PROCESS__EXECMEM); |
3033 | if (rc) | 3053 | if (rc) |
3034 | return rc; | 3054 | goto error; |
3035 | } | 3055 | } |
3036 | #endif | 3056 | #endif |
3037 | 3057 | ||
@@ -3048,7 +3068,9 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
3048 | 3068 | ||
3049 | return file_has_perm(cred, file, av); | 3069 | return file_has_perm(cred, file, av); |
3050 | } | 3070 | } |
3051 | return 0; | 3071 | |
3072 | error: | ||
3073 | return rc; | ||
3052 | } | 3074 | } |
3053 | 3075 | ||
3054 | static int selinux_file_mmap(struct file *file, unsigned long reqprot, | 3076 | static int selinux_file_mmap(struct file *file, unsigned long reqprot, |
@@ -3090,8 +3112,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3090 | rc = 0; | 3112 | rc = 0; |
3091 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3113 | if (vma->vm_start >= vma->vm_mm->start_brk && |
3092 | vma->vm_end <= vma->vm_mm->brk) { | 3114 | vma->vm_end <= vma->vm_mm->brk) { |
3093 | rc = task_has_perm(current, current, | 3115 | rc = cred_has_perm(cred, cred, PROCESS__EXECHEAP); |
3094 | PROCESS__EXECHEAP); | ||
3095 | } else if (!vma->vm_file && | 3116 | } else if (!vma->vm_file && |
3096 | vma->vm_start <= vma->vm_mm->start_stack && | 3117 | vma->vm_start <= vma->vm_mm->start_stack && |
3097 | vma->vm_end >= vma->vm_mm->start_stack) { | 3118 | vma->vm_end >= vma->vm_mm->start_stack) { |
@@ -3104,8 +3125,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3104 | * modified content. This typically should only | 3125 | * modified content. This typically should only |
3105 | * occur for text relocations. | 3126 | * occur for text relocations. |
3106 | */ | 3127 | */ |
3107 | rc = file_has_perm(cred, vma->vm_file, | 3128 | rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD); |
3108 | FILE__EXECMOD); | ||
3109 | } | 3129 | } |
3110 | if (rc) | 3130 | if (rc) |
3111 | return rc; | 3131 | return rc; |
@@ -3211,6 +3231,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) | |||
3211 | struct file_security_struct *fsec; | 3231 | struct file_security_struct *fsec; |
3212 | struct inode *inode; | 3232 | struct inode *inode; |
3213 | struct inode_security_struct *isec; | 3233 | struct inode_security_struct *isec; |
3234 | |||
3214 | inode = file->f_path.dentry->d_inode; | 3235 | inode = file->f_path.dentry->d_inode; |
3215 | fsec = file->f_security; | 3236 | fsec = file->f_security; |
3216 | isec = inode->i_security; | 3237 | isec = inode->i_security; |
@@ -3247,38 +3268,41 @@ static int selinux_task_create(unsigned long clone_flags) | |||
3247 | return task_has_perm(current, current, PROCESS__FORK); | 3268 | return task_has_perm(current, current, PROCESS__FORK); |
3248 | } | 3269 | } |
3249 | 3270 | ||
3250 | static int selinux_cred_alloc_security(struct cred *cred) | 3271 | /* |
3272 | * detach and free the LSM part of a set of credentials | ||
3273 | */ | ||
3274 | static void selinux_cred_free(struct cred *cred) | ||
3251 | { | 3275 | { |
3252 | struct task_security_struct *tsec1, *tsec2; | 3276 | struct task_security_struct *tsec = cred->security; |
3253 | int rc; | 3277 | cred->security = NULL; |
3254 | 3278 | kfree(tsec); | |
3255 | tsec1 = current_security(); | 3279 | } |
3256 | 3280 | ||
3257 | rc = cred_alloc_security(cred); | 3281 | /* |
3258 | if (rc) | 3282 | * prepare a new set of credentials for modification |
3259 | return rc; | 3283 | */ |
3260 | tsec2 = cred->security; | 3284 | static int selinux_cred_prepare(struct cred *new, const struct cred *old, |
3285 | gfp_t gfp) | ||
3286 | { | ||
3287 | const struct task_security_struct *old_tsec; | ||
3288 | struct task_security_struct *tsec; | ||
3261 | 3289 | ||
3262 | tsec2->osid = tsec1->osid; | 3290 | old_tsec = old->security; |
3263 | tsec2->sid = tsec1->sid; | ||
3264 | 3291 | ||
3265 | /* Retain the exec, fs, key, and sock SIDs across fork */ | 3292 | tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp); |
3266 | tsec2->exec_sid = tsec1->exec_sid; | 3293 | if (!tsec) |
3267 | tsec2->create_sid = tsec1->create_sid; | 3294 | return -ENOMEM; |
3268 | tsec2->keycreate_sid = tsec1->keycreate_sid; | ||
3269 | tsec2->sockcreate_sid = tsec1->sockcreate_sid; | ||
3270 | 3295 | ||
3296 | new->security = tsec; | ||
3271 | return 0; | 3297 | return 0; |
3272 | } | 3298 | } |
3273 | 3299 | ||
3274 | /* | 3300 | /* |
3275 | * detach and free the LSM part of a set of credentials | 3301 | * commit new credentials |
3276 | */ | 3302 | */ |
3277 | static void selinux_cred_free(struct cred *cred) | 3303 | static void selinux_cred_commit(struct cred *new, const struct cred *old) |
3278 | { | 3304 | { |
3279 | struct task_security_struct *tsec = cred->security; | 3305 | secondary_ops->cred_commit(new, old); |
3280 | cred->security = NULL; | ||
3281 | kfree(tsec); | ||
3282 | } | 3306 | } |
3283 | 3307 | ||
3284 | static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 3308 | static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) |
@@ -3292,9 +3316,10 @@ static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | |||
3292 | return 0; | 3316 | return 0; |
3293 | } | 3317 | } |
3294 | 3318 | ||
3295 | static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 3319 | static int selinux_task_fix_setuid(struct cred *new, const struct cred *old, |
3320 | int flags) | ||
3296 | { | 3321 | { |
3297 | return secondary_ops->task_post_setuid(id0, id1, id2, flags); | 3322 | return secondary_ops->task_fix_setuid(new, old, flags); |
3298 | } | 3323 | } |
3299 | 3324 | ||
3300 | static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) | 3325 | static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) |
@@ -3368,7 +3393,7 @@ static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim | |||
3368 | /* Control the ability to change the hard limit (whether | 3393 | /* Control the ability to change the hard limit (whether |
3369 | lowering or raising it), so that the hard limit can | 3394 | lowering or raising it), so that the hard limit can |
3370 | later be used as a safe reset point for the soft limit | 3395 | later be used as a safe reset point for the soft limit |
3371 | upon context transitions. See selinux_bprm_apply_creds. */ | 3396 | upon context transitions. See selinux_bprm_committing_creds. */ |
3372 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 3397 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
3373 | return task_has_perm(current, current, PROCESS__SETRLIMIT); | 3398 | return task_has_perm(current, current, PROCESS__SETRLIMIT); |
3374 | 3399 | ||
@@ -3422,13 +3447,12 @@ static int selinux_task_prctl(int option, | |||
3422 | unsigned long arg2, | 3447 | unsigned long arg2, |
3423 | unsigned long arg3, | 3448 | unsigned long arg3, |
3424 | unsigned long arg4, | 3449 | unsigned long arg4, |
3425 | unsigned long arg5, | 3450 | unsigned long arg5) |
3426 | long *rc_p) | ||
3427 | { | 3451 | { |
3428 | /* The current prctl operations do not appear to require | 3452 | /* The current prctl operations do not appear to require |
3429 | any SELinux controls since they merely observe or modify | 3453 | any SELinux controls since they merely observe or modify |
3430 | the state of the current process. */ | 3454 | the state of the current process. */ |
3431 | return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p); | 3455 | return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5); |
3432 | } | 3456 | } |
3433 | 3457 | ||
3434 | static int selinux_task_wait(struct task_struct *p) | 3458 | static int selinux_task_wait(struct task_struct *p) |
@@ -3436,18 +3460,6 @@ static int selinux_task_wait(struct task_struct *p) | |||
3436 | return task_has_perm(p, current, PROCESS__SIGCHLD); | 3460 | return task_has_perm(p, current, PROCESS__SIGCHLD); |
3437 | } | 3461 | } |
3438 | 3462 | ||
3439 | static void selinux_task_reparent_to_init(struct task_struct *p) | ||
3440 | { | ||
3441 | struct task_security_struct *tsec; | ||
3442 | |||
3443 | secondary_ops->task_reparent_to_init(p); | ||
3444 | |||
3445 | tsec = p->cred->security; | ||
3446 | tsec->osid = tsec->sid; | ||
3447 | tsec->sid = SECINITSID_KERNEL; | ||
3448 | return; | ||
3449 | } | ||
3450 | |||
3451 | static void selinux_task_to_inode(struct task_struct *p, | 3463 | static void selinux_task_to_inode(struct task_struct *p, |
3452 | struct inode *inode) | 3464 | struct inode *inode) |
3453 | { | 3465 | { |
@@ -5325,7 +5337,8 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5325 | { | 5337 | { |
5326 | struct task_security_struct *tsec; | 5338 | struct task_security_struct *tsec; |
5327 | struct task_struct *tracer; | 5339 | struct task_struct *tracer; |
5328 | u32 sid = 0; | 5340 | struct cred *new; |
5341 | u32 sid = 0, ptsid; | ||
5329 | int error; | 5342 | int error; |
5330 | char *str = value; | 5343 | char *str = value; |
5331 | 5344 | ||
@@ -5372,86 +5385,75 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5372 | return error; | 5385 | return error; |
5373 | } | 5386 | } |
5374 | 5387 | ||
5388 | new = prepare_creds(); | ||
5389 | if (!new) | ||
5390 | return -ENOMEM; | ||
5391 | |||
5375 | /* Permission checking based on the specified context is | 5392 | /* Permission checking based on the specified context is |
5376 | performed during the actual operation (execve, | 5393 | performed during the actual operation (execve, |
5377 | open/mkdir/...), when we know the full context of the | 5394 | open/mkdir/...), when we know the full context of the |
5378 | operation. See selinux_bprm_set_security for the execve | 5395 | operation. See selinux_bprm_set_creds for the execve |
5379 | checks and may_create for the file creation checks. The | 5396 | checks and may_create for the file creation checks. The |
5380 | operation will then fail if the context is not permitted. */ | 5397 | operation will then fail if the context is not permitted. */ |
5381 | tsec = p->cred->security; | 5398 | tsec = new->security; |
5382 | if (!strcmp(name, "exec")) | 5399 | if (!strcmp(name, "exec")) { |
5383 | tsec->exec_sid = sid; | 5400 | tsec->exec_sid = sid; |
5384 | else if (!strcmp(name, "fscreate")) | 5401 | } else if (!strcmp(name, "fscreate")) { |
5385 | tsec->create_sid = sid; | 5402 | tsec->create_sid = sid; |
5386 | else if (!strcmp(name, "keycreate")) { | 5403 | } else if (!strcmp(name, "keycreate")) { |
5387 | error = may_create_key(sid, p); | 5404 | error = may_create_key(sid, p); |
5388 | if (error) | 5405 | if (error) |
5389 | return error; | 5406 | goto abort_change; |
5390 | tsec->keycreate_sid = sid; | 5407 | tsec->keycreate_sid = sid; |
5391 | } else if (!strcmp(name, "sockcreate")) | 5408 | } else if (!strcmp(name, "sockcreate")) { |
5392 | tsec->sockcreate_sid = sid; | 5409 | tsec->sockcreate_sid = sid; |
5393 | else if (!strcmp(name, "current")) { | 5410 | } else if (!strcmp(name, "current")) { |
5394 | struct av_decision avd; | 5411 | error = -EINVAL; |
5395 | |||
5396 | if (sid == 0) | 5412 | if (sid == 0) |
5397 | return -EINVAL; | 5413 | goto abort_change; |
5398 | /* | 5414 | |
5399 | * SELinux allows to change context in the following case only. | 5415 | /* Only allow single threaded processes to change context */ |
5400 | * - Single threaded processes. | 5416 | error = -EPERM; |
5401 | * - Multi threaded processes intend to change its context into | 5417 | if (!is_single_threaded(p)) { |
5402 | * more restricted domain (defined by TYPEBOUNDS statement). | 5418 | error = security_bounded_transition(tsec->sid, sid); |
5403 | */ | 5419 | if (error) |
5404 | if (atomic_read(&p->mm->mm_users) != 1) { | 5420 | goto abort_change; |
5405 | struct task_struct *g, *t; | ||
5406 | struct mm_struct *mm = p->mm; | ||
5407 | read_lock(&tasklist_lock); | ||
5408 | do_each_thread(g, t) { | ||
5409 | if (t->mm == mm && t != p) { | ||
5410 | read_unlock(&tasklist_lock); | ||
5411 | error = security_bounded_transition(tsec->sid, sid); | ||
5412 | if (!error) | ||
5413 | goto boundary_ok; | ||
5414 | |||
5415 | return error; | ||
5416 | } | ||
5417 | } while_each_thread(g, t); | ||
5418 | read_unlock(&tasklist_lock); | ||
5419 | } | 5421 | } |
5420 | boundary_ok: | ||
5421 | 5422 | ||
5422 | /* Check permissions for the transition. */ | 5423 | /* Check permissions for the transition. */ |
5423 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, | 5424 | error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, |
5424 | PROCESS__DYNTRANSITION, NULL); | 5425 | PROCESS__DYNTRANSITION, NULL); |
5425 | if (error) | 5426 | if (error) |
5426 | return error; | 5427 | goto abort_change; |
5427 | 5428 | ||
5428 | /* Check for ptracing, and update the task SID if ok. | 5429 | /* Check for ptracing, and update the task SID if ok. |
5429 | Otherwise, leave SID unchanged and fail. */ | 5430 | Otherwise, leave SID unchanged and fail. */ |
5431 | ptsid = 0; | ||
5430 | task_lock(p); | 5432 | task_lock(p); |
5431 | rcu_read_lock(); | ||
5432 | tracer = tracehook_tracer_task(p); | 5433 | tracer = tracehook_tracer_task(p); |
5433 | if (tracer != NULL) { | 5434 | if (tracer) |
5434 | u32 ptsid = task_sid(tracer); | 5435 | ptsid = task_sid(tracer); |
5435 | rcu_read_unlock(); | 5436 | task_unlock(p); |
5436 | error = avc_has_perm_noaudit(ptsid, sid, | 5437 | |
5437 | SECCLASS_PROCESS, | 5438 | if (tracer) { |
5438 | PROCESS__PTRACE, 0, &avd); | 5439 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, |
5439 | if (!error) | 5440 | PROCESS__PTRACE, NULL); |
5440 | tsec->sid = sid; | ||
5441 | task_unlock(p); | ||
5442 | avc_audit(ptsid, sid, SECCLASS_PROCESS, | ||
5443 | PROCESS__PTRACE, &avd, error, NULL); | ||
5444 | if (error) | 5441 | if (error) |
5445 | return error; | 5442 | goto abort_change; |
5446 | } else { | ||
5447 | rcu_read_unlock(); | ||
5448 | tsec->sid = sid; | ||
5449 | task_unlock(p); | ||
5450 | } | 5443 | } |
5451 | } else | ||
5452 | return -EINVAL; | ||
5453 | 5444 | ||
5445 | tsec->sid = sid; | ||
5446 | } else { | ||
5447 | error = -EINVAL; | ||
5448 | goto abort_change; | ||
5449 | } | ||
5450 | |||
5451 | commit_creds(new); | ||
5454 | return size; | 5452 | return size; |
5453 | |||
5454 | abort_change: | ||
5455 | abort_creds(new); | ||
5456 | return error; | ||
5455 | } | 5457 | } |
5456 | 5458 | ||
5457 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 5459 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
@@ -5471,23 +5473,21 @@ static void selinux_release_secctx(char *secdata, u32 seclen) | |||
5471 | 5473 | ||
5472 | #ifdef CONFIG_KEYS | 5474 | #ifdef CONFIG_KEYS |
5473 | 5475 | ||
5474 | static int selinux_key_alloc(struct key *k, struct task_struct *tsk, | 5476 | static int selinux_key_alloc(struct key *k, const struct cred *cred, |
5475 | unsigned long flags) | 5477 | unsigned long flags) |
5476 | { | 5478 | { |
5477 | const struct task_security_struct *__tsec; | 5479 | const struct task_security_struct *tsec; |
5478 | struct key_security_struct *ksec; | 5480 | struct key_security_struct *ksec; |
5479 | 5481 | ||
5480 | ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); | 5482 | ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); |
5481 | if (!ksec) | 5483 | if (!ksec) |
5482 | return -ENOMEM; | 5484 | return -ENOMEM; |
5483 | 5485 | ||
5484 | rcu_read_lock(); | 5486 | tsec = cred->security; |
5485 | __tsec = __task_cred(tsk)->security; | 5487 | if (tsec->keycreate_sid) |
5486 | if (__tsec->keycreate_sid) | 5488 | ksec->sid = tsec->keycreate_sid; |
5487 | ksec->sid = __tsec->keycreate_sid; | ||
5488 | else | 5489 | else |
5489 | ksec->sid = __tsec->sid; | 5490 | ksec->sid = tsec->sid; |
5490 | rcu_read_unlock(); | ||
5491 | 5491 | ||
5492 | k->security = ksec; | 5492 | k->security = ksec; |
5493 | return 0; | 5493 | return 0; |
@@ -5502,8 +5502,8 @@ static void selinux_key_free(struct key *k) | |||
5502 | } | 5502 | } |
5503 | 5503 | ||
5504 | static int selinux_key_permission(key_ref_t key_ref, | 5504 | static int selinux_key_permission(key_ref_t key_ref, |
5505 | struct task_struct *ctx, | 5505 | const struct cred *cred, |
5506 | key_perm_t perm) | 5506 | key_perm_t perm) |
5507 | { | 5507 | { |
5508 | struct key *key; | 5508 | struct key *key; |
5509 | struct key_security_struct *ksec; | 5509 | struct key_security_struct *ksec; |
@@ -5515,7 +5515,7 @@ static int selinux_key_permission(key_ref_t key_ref, | |||
5515 | if (perm == 0) | 5515 | if (perm == 0) |
5516 | return 0; | 5516 | return 0; |
5517 | 5517 | ||
5518 | sid = task_sid(ctx); | 5518 | sid = cred_sid(cred); |
5519 | 5519 | ||
5520 | key = key_ref_to_ptr(key_ref); | 5520 | key = key_ref_to_ptr(key_ref); |
5521 | ksec = key->security; | 5521 | ksec = key->security; |
@@ -5545,8 +5545,7 @@ static struct security_operations selinux_ops = { | |||
5545 | .ptrace_may_access = selinux_ptrace_may_access, | 5545 | .ptrace_may_access = selinux_ptrace_may_access, |
5546 | .ptrace_traceme = selinux_ptrace_traceme, | 5546 | .ptrace_traceme = selinux_ptrace_traceme, |
5547 | .capget = selinux_capget, | 5547 | .capget = selinux_capget, |
5548 | .capset_check = selinux_capset_check, | 5548 | .capset = selinux_capset, |
5549 | .capset_set = selinux_capset_set, | ||
5550 | .sysctl = selinux_sysctl, | 5549 | .sysctl = selinux_sysctl, |
5551 | .capable = selinux_capable, | 5550 | .capable = selinux_capable, |
5552 | .quotactl = selinux_quotactl, | 5551 | .quotactl = selinux_quotactl, |
@@ -5621,10 +5620,11 @@ static struct security_operations selinux_ops = { | |||
5621 | .dentry_open = selinux_dentry_open, | 5620 | .dentry_open = selinux_dentry_open, |
5622 | 5621 | ||
5623 | .task_create = selinux_task_create, | 5622 | .task_create = selinux_task_create, |
5624 | .cred_alloc_security = selinux_cred_alloc_security, | ||
5625 | .cred_free = selinux_cred_free, | 5623 | .cred_free = selinux_cred_free, |
5624 | .cred_prepare = selinux_cred_prepare, | ||
5625 | .cred_commit = selinux_cred_commit, | ||
5626 | .task_setuid = selinux_task_setuid, | 5626 | .task_setuid = selinux_task_setuid, |
5627 | .task_post_setuid = selinux_task_post_setuid, | 5627 | .task_fix_setuid = selinux_task_fix_setuid, |
5628 | .task_setgid = selinux_task_setgid, | 5628 | .task_setgid = selinux_task_setgid, |
5629 | .task_setpgid = selinux_task_setpgid, | 5629 | .task_setpgid = selinux_task_setpgid, |
5630 | .task_getpgid = selinux_task_getpgid, | 5630 | .task_getpgid = selinux_task_getpgid, |
@@ -5641,7 +5641,6 @@ static struct security_operations selinux_ops = { | |||
5641 | .task_kill = selinux_task_kill, | 5641 | .task_kill = selinux_task_kill, |
5642 | .task_wait = selinux_task_wait, | 5642 | .task_wait = selinux_task_wait, |
5643 | .task_prctl = selinux_task_prctl, | 5643 | .task_prctl = selinux_task_prctl, |
5644 | .task_reparent_to_init = selinux_task_reparent_to_init, | ||
5645 | .task_to_inode = selinux_task_to_inode, | 5644 | .task_to_inode = selinux_task_to_inode, |
5646 | 5645 | ||
5647 | .ipc_permission = selinux_ipc_permission, | 5646 | .ipc_permission = selinux_ipc_permission, |
@@ -5737,8 +5736,6 @@ static struct security_operations selinux_ops = { | |||
5737 | 5736 | ||
5738 | static __init int selinux_init(void) | 5737 | static __init int selinux_init(void) |
5739 | { | 5738 | { |
5740 | struct task_security_struct *tsec; | ||
5741 | |||
5742 | if (!security_module_enable(&selinux_ops)) { | 5739 | if (!security_module_enable(&selinux_ops)) { |
5743 | selinux_enabled = 0; | 5740 | selinux_enabled = 0; |
5744 | return 0; | 5741 | return 0; |
@@ -5752,10 +5749,7 @@ static __init int selinux_init(void) | |||
5752 | printk(KERN_INFO "SELinux: Initializing.\n"); | 5749 | printk(KERN_INFO "SELinux: Initializing.\n"); |
5753 | 5750 | ||
5754 | /* Set the security state for the initial task. */ | 5751 | /* Set the security state for the initial task. */ |
5755 | if (cred_alloc_security(current->cred)) | 5752 | cred_init_security(); |
5756 | panic("SELinux: Failed to initialize initial task.\n"); | ||
5757 | tsec = current->cred->security; | ||
5758 | tsec->osid = tsec->sid = SECINITSID_KERNEL; | ||
5759 | 5753 | ||
5760 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | 5754 | sel_inode_cache = kmem_cache_create("selinux_inode_security", |
5761 | sizeof(struct inode_security_struct), | 5755 | sizeof(struct inode_security_struct), |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 11167fd567b9..e952b397153d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -104,8 +104,7 @@ static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode) | |||
104 | if (rc != 0) | 104 | if (rc != 0) |
105 | return rc; | 105 | return rc; |
106 | 106 | ||
107 | rc = smk_access(current->cred->security, ctp->cred->security, | 107 | rc = smk_access(current_security(), task_security(ctp), MAY_READWRITE); |
108 | MAY_READWRITE); | ||
109 | if (rc != 0 && capable(CAP_MAC_OVERRIDE)) | 108 | if (rc != 0 && capable(CAP_MAC_OVERRIDE)) |
110 | return 0; | 109 | return 0; |
111 | return rc; | 110 | return rc; |
@@ -127,8 +126,7 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
127 | if (rc != 0) | 126 | if (rc != 0) |
128 | return rc; | 127 | return rc; |
129 | 128 | ||
130 | rc = smk_access(ptp->cred->security, current->cred->security, | 129 | rc = smk_access(task_security(ptp), current_security(), MAY_READWRITE); |
131 | MAY_READWRITE); | ||
132 | if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE)) | 130 | if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE)) |
133 | return 0; | 131 | return 0; |
134 | return rc; | 132 | return rc; |
@@ -977,22 +975,6 @@ static int smack_file_receive(struct file *file) | |||
977 | */ | 975 | */ |
978 | 976 | ||
979 | /** | 977 | /** |
980 | * smack_cred_alloc_security - "allocate" a task cred blob | ||
981 | * @cred: the task creds in need of a blob | ||
982 | * | ||
983 | * Smack isn't using copies of blobs. Everyone | ||
984 | * points to an immutable list. No alloc required. | ||
985 | * No data copy required. | ||
986 | * | ||
987 | * Always returns 0 | ||
988 | */ | ||
989 | static int smack_cred_alloc_security(struct cred *cred) | ||
990 | { | ||
991 | cred->security = current_security(); | ||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | /** | ||
996 | * smack_cred_free - "free" task-level security credentials | 978 | * smack_cred_free - "free" task-level security credentials |
997 | * @cred: the credentials in question | 979 | * @cred: the credentials in question |
998 | * | 980 | * |
@@ -1006,6 +988,30 @@ static void smack_cred_free(struct cred *cred) | |||
1006 | } | 988 | } |
1007 | 989 | ||
1008 | /** | 990 | /** |
991 | * smack_cred_prepare - prepare new set of credentials for modification | ||
992 | * @new: the new credentials | ||
993 | * @old: the original credentials | ||
994 | * @gfp: the atomicity of any memory allocations | ||
995 | * | ||
996 | * Prepare a new set of credentials for modification. | ||
997 | */ | ||
998 | static int smack_cred_prepare(struct cred *new, const struct cred *old, | ||
999 | gfp_t gfp) | ||
1000 | { | ||
1001 | new->security = old->security; | ||
1002 | return 0; | ||
1003 | } | ||
1004 | |||
1005 | /* | ||
1006 | * commit new credentials | ||
1007 | * @new: the new credentials | ||
1008 | * @old: the original credentials | ||
1009 | */ | ||
1010 | static void smack_cred_commit(struct cred *new, const struct cred *old) | ||
1011 | { | ||
1012 | } | ||
1013 | |||
1014 | /** | ||
1009 | * smack_task_setpgid - Smack check on setting pgid | 1015 | * smack_task_setpgid - Smack check on setting pgid |
1010 | * @p: the task object | 1016 | * @p: the task object |
1011 | * @pgid: unused | 1017 | * @pgid: unused |
@@ -2036,6 +2042,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
2036 | static int smack_setprocattr(struct task_struct *p, char *name, | 2042 | static int smack_setprocattr(struct task_struct *p, char *name, |
2037 | void *value, size_t size) | 2043 | void *value, size_t size) |
2038 | { | 2044 | { |
2045 | struct cred *new; | ||
2039 | char *newsmack; | 2046 | char *newsmack; |
2040 | 2047 | ||
2041 | /* | 2048 | /* |
@@ -2058,7 +2065,11 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2058 | if (newsmack == NULL) | 2065 | if (newsmack == NULL) |
2059 | return -EINVAL; | 2066 | return -EINVAL; |
2060 | 2067 | ||
2061 | p->cred->security = newsmack; | 2068 | new = prepare_creds(); |
2069 | if (!new) | ||
2070 | return -ENOMEM; | ||
2071 | new->security = newsmack; | ||
2072 | commit_creds(new); | ||
2062 | return size; | 2073 | return size; |
2063 | } | 2074 | } |
2064 | 2075 | ||
@@ -2354,17 +2365,17 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
2354 | /** | 2365 | /** |
2355 | * smack_key_alloc - Set the key security blob | 2366 | * smack_key_alloc - Set the key security blob |
2356 | * @key: object | 2367 | * @key: object |
2357 | * @tsk: the task associated with the key | 2368 | * @cred: the credentials to use |
2358 | * @flags: unused | 2369 | * @flags: unused |
2359 | * | 2370 | * |
2360 | * No allocation required | 2371 | * No allocation required |
2361 | * | 2372 | * |
2362 | * Returns 0 | 2373 | * Returns 0 |
2363 | */ | 2374 | */ |
2364 | static int smack_key_alloc(struct key *key, struct task_struct *tsk, | 2375 | static int smack_key_alloc(struct key *key, const struct cred *cred, |
2365 | unsigned long flags) | 2376 | unsigned long flags) |
2366 | { | 2377 | { |
2367 | key->security = tsk->cred->security; | 2378 | key->security = cred->security; |
2368 | return 0; | 2379 | return 0; |
2369 | } | 2380 | } |
2370 | 2381 | ||
@@ -2382,14 +2393,14 @@ static void smack_key_free(struct key *key) | |||
2382 | /* | 2393 | /* |
2383 | * smack_key_permission - Smack access on a key | 2394 | * smack_key_permission - Smack access on a key |
2384 | * @key_ref: gets to the object | 2395 | * @key_ref: gets to the object |
2385 | * @context: task involved | 2396 | * @cred: the credentials to use |
2386 | * @perm: unused | 2397 | * @perm: unused |
2387 | * | 2398 | * |
2388 | * Return 0 if the task has read and write to the object, | 2399 | * Return 0 if the task has read and write to the object, |
2389 | * an error code otherwise | 2400 | * an error code otherwise |
2390 | */ | 2401 | */ |
2391 | static int smack_key_permission(key_ref_t key_ref, | 2402 | static int smack_key_permission(key_ref_t key_ref, |
2392 | struct task_struct *context, key_perm_t perm) | 2403 | const struct cred *cred, key_perm_t perm) |
2393 | { | 2404 | { |
2394 | struct key *keyp; | 2405 | struct key *keyp; |
2395 | 2406 | ||
@@ -2405,11 +2416,10 @@ static int smack_key_permission(key_ref_t key_ref, | |||
2405 | /* | 2416 | /* |
2406 | * This should not occur | 2417 | * This should not occur |
2407 | */ | 2418 | */ |
2408 | if (context->cred->security == NULL) | 2419 | if (cred->security == NULL) |
2409 | return -EACCES; | 2420 | return -EACCES; |
2410 | 2421 | ||
2411 | return smk_access(context->cred->security, keyp->security, | 2422 | return smk_access(cred->security, keyp->security, MAY_READWRITE); |
2412 | MAY_READWRITE); | ||
2413 | } | 2423 | } |
2414 | #endif /* CONFIG_KEYS */ | 2424 | #endif /* CONFIG_KEYS */ |
2415 | 2425 | ||
@@ -2580,8 +2590,7 @@ struct security_operations smack_ops = { | |||
2580 | .ptrace_may_access = smack_ptrace_may_access, | 2590 | .ptrace_may_access = smack_ptrace_may_access, |
2581 | .ptrace_traceme = smack_ptrace_traceme, | 2591 | .ptrace_traceme = smack_ptrace_traceme, |
2582 | .capget = cap_capget, | 2592 | .capget = cap_capget, |
2583 | .capset_check = cap_capset_check, | 2593 | .capset = cap_capset, |
2584 | .capset_set = cap_capset_set, | ||
2585 | .capable = cap_capable, | 2594 | .capable = cap_capable, |
2586 | .syslog = smack_syslog, | 2595 | .syslog = smack_syslog, |
2587 | .settime = cap_settime, | 2596 | .settime = cap_settime, |
@@ -2630,9 +2639,10 @@ struct security_operations smack_ops = { | |||
2630 | .file_send_sigiotask = smack_file_send_sigiotask, | 2639 | .file_send_sigiotask = smack_file_send_sigiotask, |
2631 | .file_receive = smack_file_receive, | 2640 | .file_receive = smack_file_receive, |
2632 | 2641 | ||
2633 | .cred_alloc_security = smack_cred_alloc_security, | ||
2634 | .cred_free = smack_cred_free, | 2642 | .cred_free = smack_cred_free, |
2635 | .task_post_setuid = cap_task_post_setuid, | 2643 | .cred_prepare = smack_cred_prepare, |
2644 | .cred_commit = smack_cred_commit, | ||
2645 | .task_fix_setuid = cap_task_fix_setuid, | ||
2636 | .task_setpgid = smack_task_setpgid, | 2646 | .task_setpgid = smack_task_setpgid, |
2637 | .task_getpgid = smack_task_getpgid, | 2647 | .task_getpgid = smack_task_getpgid, |
2638 | .task_getsid = smack_task_getsid, | 2648 | .task_getsid = smack_task_getsid, |
@@ -2645,7 +2655,6 @@ struct security_operations smack_ops = { | |||
2645 | .task_movememory = smack_task_movememory, | 2655 | .task_movememory = smack_task_movememory, |
2646 | .task_kill = smack_task_kill, | 2656 | .task_kill = smack_task_kill, |
2647 | .task_wait = smack_task_wait, | 2657 | .task_wait = smack_task_wait, |
2648 | .task_reparent_to_init = cap_task_reparent_to_init, | ||
2649 | .task_to_inode = smack_task_to_inode, | 2658 | .task_to_inode = smack_task_to_inode, |
2650 | .task_prctl = cap_task_prctl, | 2659 | .task_prctl = cap_task_prctl, |
2651 | 2660 | ||
@@ -2721,6 +2730,8 @@ struct security_operations smack_ops = { | |||
2721 | */ | 2730 | */ |
2722 | static __init int smack_init(void) | 2731 | static __init int smack_init(void) |
2723 | { | 2732 | { |
2733 | struct cred *cred; | ||
2734 | |||
2724 | if (!security_module_enable(&smack_ops)) | 2735 | if (!security_module_enable(&smack_ops)) |
2725 | return 0; | 2736 | return 0; |
2726 | 2737 | ||
@@ -2729,7 +2740,8 @@ static __init int smack_init(void) | |||
2729 | /* | 2740 | /* |
2730 | * Set the security state for the initial task. | 2741 | * Set the security state for the initial task. |
2731 | */ | 2742 | */ |
2732 | current->cred->security = &smack_known_floor.smk_known; | 2743 | cred = (struct cred *) current->cred; |
2744 | cred->security = &smack_known_floor.smk_known; | ||
2733 | 2745 | ||
2734 | /* | 2746 | /* |
2735 | * Initialize locks | 2747 | * Initialize locks |