aboutsummaryrefslogtreecommitdiffstats
path: root/security/commoncap.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/commoncap.c')
-rw-r--r--security/commoncap.c103
1 files changed, 94 insertions, 9 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 852905789caf..e8c3f5e46705 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -24,11 +24,8 @@
24#include <linux/hugetlb.h> 24#include <linux/hugetlb.h>
25#include <linux/mount.h> 25#include <linux/mount.h>
26#include <linux/sched.h> 26#include <linux/sched.h>
27 27#include <linux/prctl.h>
28/* Global security state */ 28#include <linux/securebits.h>
29
30unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
31EXPORT_SYMBOL(securebits);
32 29
33int cap_netlink_send(struct sock *sk, struct sk_buff *skb) 30int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
34{ 31{
@@ -368,7 +365,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
368 365
369 /* AUD: Audit candidate if current->cap_effective is set */ 366 /* AUD: Audit candidate if current->cap_effective is set */
370 367
371 current->keep_capabilities = 0; 368 current->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
372} 369}
373 370
374int cap_bprm_secureexec (struct linux_binprm *bprm) 371int cap_bprm_secureexec (struct linux_binprm *bprm)
@@ -448,7 +445,7 @@ static inline void cap_emulate_setxuid (int old_ruid, int old_euid,
448{ 445{
449 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) && 446 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
450 (current->uid != 0 && current->euid != 0 && current->suid != 0) && 447 (current->uid != 0 && current->euid != 0 && current->suid != 0) &&
451 !current->keep_capabilities) { 448 !issecure(SECURE_KEEP_CAPS)) {
452 cap_clear (current->cap_permitted); 449 cap_clear (current->cap_permitted);
453 cap_clear (current->cap_effective); 450 cap_clear (current->cap_effective);
454 } 451 }
@@ -547,7 +544,7 @@ int cap_task_setnice (struct task_struct *p, int nice)
547 * this task could get inconsistent info. There can be no 544 * this task could get inconsistent info. There can be no
548 * racing writer bc a task can only change its own caps. 545 * racing writer bc a task can only change its own caps.
549 */ 546 */
550long cap_prctl_drop(unsigned long cap) 547static long cap_prctl_drop(unsigned long cap)
551{ 548{
552 if (!capable(CAP_SETPCAP)) 549 if (!capable(CAP_SETPCAP))
553 return -EPERM; 550 return -EPERM;
@@ -556,6 +553,7 @@ long cap_prctl_drop(unsigned long cap)
556 cap_lower(current->cap_bset, cap); 553 cap_lower(current->cap_bset, cap);
557 return 0; 554 return 0;
558} 555}
556
559#else 557#else
560int cap_task_setscheduler (struct task_struct *p, int policy, 558int cap_task_setscheduler (struct task_struct *p, int policy,
561 struct sched_param *lp) 559 struct sched_param *lp)
@@ -572,12 +570,99 @@ int cap_task_setnice (struct task_struct *p, int nice)
572} 570}
573#endif 571#endif
574 572
573int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
574 unsigned long arg4, unsigned long arg5, long *rc_p)
575{
576 long error = 0;
577
578 switch (option) {
579 case PR_CAPBSET_READ:
580 if (!cap_valid(arg2))
581 error = -EINVAL;
582 else
583 error = !!cap_raised(current->cap_bset, arg2);
584 break;
585#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
586 case PR_CAPBSET_DROP:
587 error = cap_prctl_drop(arg2);
588 break;
589
590 /*
591 * The next four prctl's remain to assist with transitioning a
592 * system from legacy UID=0 based privilege (when filesystem
593 * capabilities are not in use) to a system using filesystem
594 * capabilities only - as the POSIX.1e draft intended.
595 *
596 * Note:
597 *
598 * PR_SET_SECUREBITS =
599 * issecure_mask(SECURE_KEEP_CAPS_LOCKED)
600 * | issecure_mask(SECURE_NOROOT)
601 * | issecure_mask(SECURE_NOROOT_LOCKED)
602 * | issecure_mask(SECURE_NO_SETUID_FIXUP)
603 * | issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED)
604 *
605 * will ensure that the current process and all of its
606 * children will be locked into a pure
607 * capability-based-privilege environment.
608 */
609 case PR_SET_SECUREBITS:
610 if ((((current->securebits & SECURE_ALL_LOCKS) >> 1)
611 & (current->securebits ^ arg2)) /*[1]*/
612 || ((current->securebits & SECURE_ALL_LOCKS
613 & ~arg2)) /*[2]*/
614 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
615 || (cap_capable(current, CAP_SETPCAP) != 0)) { /*[4]*/
616 /*
617 * [1] no changing of bits that are locked
618 * [2] no unlocking of locks
619 * [3] no setting of unsupported bits
620 * [4] doing anything requires privilege (go read about
621 * the "sendmail capabilities bug")
622 */
623 error = -EPERM; /* cannot change a locked bit */
624 } else {
625 current->securebits = arg2;
626 }
627 break;
628 case PR_GET_SECUREBITS:
629 error = current->securebits;
630 break;
631
632#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
633
634 case PR_GET_KEEPCAPS:
635 if (issecure(SECURE_KEEP_CAPS))
636 error = 1;
637 break;
638 case PR_SET_KEEPCAPS:
639 if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */
640 error = -EINVAL;
641 else if (issecure(SECURE_KEEP_CAPS_LOCKED))
642 error = -EPERM;
643 else if (arg2)
644 current->securebits |= issecure_mask(SECURE_KEEP_CAPS);
645 else
646 current->securebits &=
647 ~issecure_mask(SECURE_KEEP_CAPS);
648 break;
649
650 default:
651 /* No functionality available - continue with default */
652 return 0;
653 }
654
655 /* Functionality provided */
656 *rc_p = error;
657 return 1;
658}
659
575void cap_task_reparent_to_init (struct task_struct *p) 660void cap_task_reparent_to_init (struct task_struct *p)
576{ 661{
577 cap_set_init_eff(p->cap_effective); 662 cap_set_init_eff(p->cap_effective);
578 cap_clear(p->cap_inheritable); 663 cap_clear(p->cap_inheritable);
579 cap_set_full(p->cap_permitted); 664 cap_set_full(p->cap_permitted);
580 p->keep_capabilities = 0; 665 p->securebits = SECUREBITS_DEFAULT;
581 return; 666 return;
582} 667}
583 668