Quoting Andrew Morgan ([EMAIL PROTECTED]):
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Andrew Morgan wrote:
> > Andrew Morgan wrote:
> >> Serge E. Hallyn wrote:
> >>> (Sorry, I should have ran shorter tests to get these results a little
> >>> quicker...)
> >>> Unfortunately these can't be moved here. If you have
> >>> SECURITY=y
> >>> SECURITY_CAPABILITIES=n
> >>> then commoncap is not compiled, and
> >>> security/dummy.c wants securebits
>
> OK. I believe this (finally) does it. :-)
>
> Cheers
>
> Andrew
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.2.6 (GNU/Linux)
>
> iD8DBQFGxzFTQheEq9QabfIRAsJeAJ91MC/tJrtsJpg+vZf7sdPrTXCOTwCeOln6
> 74oG9QD9TWy3F5ne2p2Npa4=
> =ZKAK
> -----END PGP SIGNATURE-----
> >From d1904e8f5f28e00957cae25255b1690be8413c77 Mon Sep 17 00:00:00 2001
> From: Andrew Morgan <[EMAIL PROTECTED]>
> Date: Wed, 15 Aug 2007 07:27:29 -0700
> Subject: [PATCH] File capabilities implementation of CAP_SETPCAP
>
> The non-filesystem capability meaning of CAP_SETPCAP is that a
> process, p1, can change the capabilities of another process, p2. This
> is not the meaning that was intended for this capability at all, and
> this implementation came about purely because, without filesystem
> capabilities, there was no way to use capabilities without one process
> bestowing them on another.
>
> Since we now have a filesystem support for capabilities we can fix the
> implementation of CAP_SETPCAP.
>
> The most significant thing about this change is that, with it in
> effect, no process can set the capabilities of another process.
>
> The capabilities of a program are set via the capability convolution
> rules:
>
> pI(post-exec) = pI(pre-exec)
> pP(post-exec) = (X(aka cap_bset) & fP) | (pI(post-exec) & fI)
> pE(post-exec) = fE ? pP(post-exec) : 0
>
> at exec() time. As such, the only influence the pre-exec() program can
> have on the post-exec() program's capabilities are through the pI
> capability set.
>
> The correct implementation for CAP_SETPCAP (and that enabled by this
> patch) is that it can be used to add extra pI capabilities to the
> current process - to be picked up by subsequent exec()s when the above
> convolution rules are applied.
>
> Here is how it works:
>
> Let's say we have a process, p. It has capability sets, pE, pP and pI.
> Generally, p, can change the value of its own pI to pI' where
>
> (pI' & ~pI) & ~pP = 0.
>
> That is, the only new things in pI' that were not present in pI need to
> be present in pP.
>
> The role of CAP_SETPCAP is basically to permit changes to pI beyond
> the above:
>
> if (pE & CAP_SETPCAP) {
> pI' = anything; /* ie., even (pI' & ~pI) & ~pP != 0 */
> }
>
> This capability is useful for things like login, which (say, via
> pam_cap) might want to raise certain inheritable capabilities for use
> by the children of the logged-in user's shell, but those capabilities
> are not useful to or needed by the login program itself.
>
> One such use might be to limit who can run ping. You set the
> capabilities of the 'ping' program to be "= cap_net_raw+i", and then
> only shells that have (pI & CAP_NET_RAW) will be able to run
> it. Without CAP_SETPCAP implemented as described above, login(pam_cap)
> would have to also have (pP & CAP_NET_RAW) in order to raise this
> capability and pass it on through the inheritable set.
>
> Signed-off-by: Andrew Morgan <[EMAIL PROTECTED]>
> ---
> include/linux/capability.h | 4 ---
> include/linux/security.h | 7 +++++
> kernel/capability.c | 8 +-----
> kernel/sysctl.c | 8 ++++-
> kernel/sysctl_check.c | 5 +++
> security/commoncap.c | 59 ++++++++++++++++++++++++++++++++++++++++---
> security/dummy.c | 16 +++++------
> 7 files changed, 80 insertions(+), 27 deletions(-)
>
> diff --git a/include/linux/capability.h b/include/linux/capability.h
> index 8961e7f..7a8d7ad 100644
> --- a/include/linux/capability.h
> +++ b/include/linux/capability.h
> @@ -310,10 +310,6 @@ typedef __u32 kernel_cap_t;
> #define CAP_SETFCAP 31
>
> #ifdef __KERNEL__
> -/*
> - * Bounding set
> - */
> -extern kernel_cap_t cap_bset;
>
> /*
> * Internal kernel functions only
> diff --git a/include/linux/security.h b/include/linux/security.h
> index e38230f..b673fd2 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -34,6 +34,13 @@
> #include <linux/xfrm.h>
> #include <net/flow.h>
>
> +/*
> + * Bounding set
> + */
> +extern kernel_cap_t cap_bset;
> +
> +extern unsigned securebits;
> +
> struct ctl_table;
>
> /*
> diff --git a/kernel/capability.c b/kernel/capability.c
> index 8c4773c..55aa5f0 100644
> --- a/kernel/capability.c
> +++ b/kernel/capability.c
> @@ -3,7 +3,7 @@
> *
> * Copyright (C) 1997 Andrew Main <[EMAIL PROTECTED]>
> *
> - * Integrated into 2.1.97+, Andrew G. Morgan <[EMAIL PROTECTED]>
> + * Integrated into 2.1.97+, Andrew G. Morgan <[EMAIL PROTECTED]>
> * 30 May 2002: Cleanup, Robert M. Love <[EMAIL PROTECTED]>
> */
>
> @@ -15,12 +15,6 @@
> #include <linux/pid_namespace.h>
> #include <asm/uaccess.h>
>
> -unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
> -kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
> -
> -EXPORT_SYMBOL(securebits);
> -EXPORT_SYMBOL(cap_bset);
> -
> /*
> * This lock protects task->cap_* for all tasks including current.
> * Locking rule: acquire this prior to tasklist_lock.
> diff --git a/kernel/sysctl.c b/kernel/sysctl.c
> index 8ced8cc..cf0b136 100644
> --- a/kernel/sysctl.c
> +++ b/kernel/sysctl.c
> @@ -25,7 +25,7 @@
> #include <linux/swap-prefetch.h>
> #include <linux/sysctl.h>
> #include <linux/proc_fs.h>
> -#include <linux/capability.h>
> +#include <linux/security.h>
> #include <linux/ctype.h>
> #include <linux/utsname.h>
> #include <linux/smp_lock.h>
> @@ -370,6 +370,7 @@ static struct ctl_table kern_table[] = {
> .proc_handler = &proc_dointvec_taint,
> },
> #endif
> +#ifdef CONFIG_SECURITY_CAPABILITIES
> {
> .procname = "cap-bound",
> .data = &cap_bset,
> @@ -377,6 +378,7 @@ static struct ctl_table kern_table[] = {
> .mode = 0600,
> .proc_handler = &proc_dointvec_bset,
> },
> +#endif /* def CONFIG_SECURITY_CAPABILITIES */
> #ifdef CONFIG_BLK_DEV_INITRD
> {
> .ctl_name = KERN_REALROOTDEV,
> @@ -1899,10 +1901,11 @@ static int do_proc_dointvec_bset_conv(int *negp,
> unsigned long *lvalp,
> return 0;
> }
>
> +#ifdef CONFIG_SECURITY_CAPABILITIES
> /*
> * init may raise the set.
> */
> -
> +
> int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
> void __user *buffer, size_t *lenp, loff_t *ppos)
> {
> @@ -1916,6 +1919,7 @@ int proc_dointvec_bset(struct ctl_table *table, int
> write, struct file *filp,
> return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
> do_proc_dointvec_bset_conv,&op);
> }
> +#endif /* def CONFIG_SECURITY_CAPABILITIES */
>
> /*
> * Taint values can only be increased
> diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
> index 930a514..7aa581b 100644
> --- a/kernel/sysctl_check.c
> +++ b/kernel/sysctl_check.c
> @@ -37,7 +37,10 @@ static struct trans_ctl_table trans_kern_table[] = {
> { KERN_NODENAME, "hostname" },
> { KERN_DOMAINNAME, "domainname" },
>
> +#ifdef CONFIG_SECURITY_CAPABILITIES
> { KERN_CAP_BSET, "cap-bound" },
> +#endif /* def CONFIG_SECURITY_CAPABILITIES */
> +
> { KERN_PANIC, "panic" },
> { KERN_REALROOTDEV, "real-root-dev" },
>
> @@ -1510,7 +1513,9 @@ int sysctl_check_table(struct ctl_table *table)
> (table->strategy == sysctl_ms_jiffies) ||
> (table->proc_handler == proc_dostring) ||
> (table->proc_handler == proc_dointvec) ||
> +#ifdef CONFIG_SECURITY_CAPABILITIES
> (table->proc_handler == proc_dointvec_bset) ||
> +#endif /* def CONFIG_SECURITY_CAPABILITIES */
> (table->proc_handler == proc_dointvec_minmax) ||
> (table->proc_handler == proc_dointvec_jiffies) ||
> (table->proc_handler ==
> proc_dointvec_userhz_jiffies) ||
> diff --git a/security/commoncap.c b/security/commoncap.c
> index 7816cdc..ef4beaa 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -25,6 +25,25 @@
> #include <linux/mount.h>
> #include <linux/sched.h>
>
> +#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
> +/*
> + * Because of the reduced scope of CAP_SETPCAP when filesystem
> + * capabilities are in effect, it is safe to allow this capability to
> + * be available in the default configuration.
> + */
> +# define CAP_INIT_BSET CAP_FULL_SET
> +#else /* ie. ndef CONFIG_SECURITY_FILE_CAPABILITIES */
> +# define CAP_INIT_BSET CAP_INIT_EFF_SET
> +#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
> +
> +kernel_cap_t cap_bset = CAP_INIT_BSET; /* systemwide capability bound */
> +EXPORT_SYMBOL(cap_bset);
> +
> +/* Global security state */
> +
> +unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
> +EXPORT_SYMBOL(securebits);
> +
> int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
> {
> NETLINK_CB(skb).eff_cap = current->cap_effective;
> @@ -76,14 +95,44 @@ int cap_capget (struct task_struct *target, kernel_cap_t
> *effective,
> return 0;
> }
>
> +#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
> +
> +static inline int cap_block_setpcap(struct task_struct *target)
> +{
> + /*
> + * No support for remote process capability manipulation with
> + * filesystem capability support.
> + */
> + return (target != current);
> +}
> +
> +static inline int cap_inh_is_capped(void)
> +{
> + /*
> + * return 1 if changes to the inheritable set are limited
> + * to the old permitted set.
> + */
> + return !cap_capable(current, CAP_SETPCAP);
> +}
> +
> +#else /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */
> +
> +static inline int cap_block_setpcap(struct task_struct *t) { return 0; }
> +static inline int cap_inh_is_capped(void) { return 1; }
> +
> +#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
> +
> int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,
> kernel_cap_t *inheritable, kernel_cap_t *permitted)
> {
> - /* Derived from kernel/capability.c:sys_capset. */
> - /* verify restrictions on target's new Inheritable set */
> - if (!cap_issubset (*inheritable,
> - cap_combine (target->cap_inheritable,
> - current->cap_permitted))) {
> + if (cap_block_setpcap(target)) {
> + return -EPERM;
> + }
> + if (cap_inh_is_capped()
> + && !cap_issubset(*inheritable,
> + cap_combine(target->cap_inheritable,
> + current->cap_permitted))) {
> + /* incapable of using this inheritable set */
> return -EPERM;
> }
>
> diff --git a/security/dummy.c b/security/dummy.c
> index 5839faa..80142a9 100644
> --- a/security/dummy.c
> +++ b/security/dummy.c
> @@ -37,15 +37,13 @@ static int dummy_capget (struct task_struct *target,
> kernel_cap_t * effective,
> kernel_cap_t * inheritable, kernel_cap_t * permitted)
> {
> *effective = *inheritable = *permitted = 0;
> - if (!issecure(SECURE_NOROOT)) {
> - if (target->euid == 0) {
> - *permitted |= (~0 & ~CAP_FS_MASK);
> - *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) &
> ~CAP_FS_MASK);
> - }
> - if (target->fsuid == 0) {
> - *permitted |= CAP_FS_MASK;
> - *effective |= CAP_FS_MASK;
> - }
> + if (target->euid == 0) {
> + *permitted |= (~0 & ~CAP_FS_MASK);
> + *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK);
> + }
> + if (target->fsuid == 0) {
> + *permitted |= CAP_FS_MASK;
> + *effective |= CAP_FS_MASK;
> }
> return 0;
> }
> --
> 1.5.1.3
This passed ltp with all sorts of kernel configs.
Signed-off-by: Serge E. Hallyn <[EMAIL PROTECTED]>
thanks,
-serge
-
To unsubscribe from this list: send the line "unsubscribe
linux-security-module" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html