Quoting Andrew Morgan ([EMAIL PROTECTED]):
> Andrew Morgan wrote:
> > Serge E. Hallyn wrote:
> >>>  0. fix the implementation of cap_setpcap. It is supposed to mean 'this
> >>> process can raise capabilities, outside its permitted set, in _its own_
> >>> inheritable set'.
> 
> I believe the attached patch does this.
> 
> FWIW There is a mighty old (circa 1999) pam_cap tar.gz file here:
> 
>  http://www.kernel.org/pub/linux/libs/pam/pre/modules/pam_cap-0.1.tar.gz
> 
> I'll see what it takes to get this to all work together. :-)
> 
> Cheers
> 
> Andrew

> >From 54c13846946b86e4254bfd2b32d02f4a949760da Mon Sep 17 00:00:00 2001
> From: Andrew Morgan <[EMAIL PROTECTED]>
> Date: Sat, 4 Aug 2007 19:14:50 -0700
> Subject: [PATCH] Change the meaning of CAP_SETPCAP when filesystem support is 
> enabled.
> 
> 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 throught 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]>
> ---
>  kernel/capability.c   |    2 +-
>  security/capability.c |    8 ++++++++
>  security/commoncap.c  |   20 +++++++++++++++++---
>  3 files changed, 26 insertions(+), 4 deletions(-)
> 
> diff --git a/kernel/capability.c b/kernel/capability.c
> index c8d3c77..4f6166f 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]>
>   */ 
> 
> diff --git a/security/capability.c b/security/capability.c
> index 0db5fda..47ec7ca 100644
> --- a/security/capability.c
> +++ b/security/capability.c
> @@ -74,6 +74,14 @@ static int __init capability_init (void)
>               }
>               secondary = 1;
>       }
> +#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.
> +      */
> +     cap_bset = CAP_FULL_SET;

How about just defining CAP_BSET_INIT once in include/linux/capability.h
depending on CONFIG_SECURITY_FILE_CAPABILITIES, and at
kernel/capability.c changing 
        kernel_cap_t cap_bset = CAP_INIT_EFF_SET;
to
        kernel_cap_t cap_bset = CAP_BSET_INIT;
?

Rather than having it be set in two different places.

> +#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
>       printk (KERN_INFO "Capability LSM initialized%s\n",
>               secondary ? " as secondary" : "");
>       return 0;
> diff --git a/security/commoncap.c b/security/commoncap.c
> index 6349093..19efaed 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -78,11 +78,25 @@ int cap_capget (struct task_struct *target, kernel_cap_t 
> *effective,
>  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,
> +#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
> +     if (target != current) {
> +             /*
> +              * No support for remote process capability manipulation
> +              * with filesystem capability support.
> +              */
> +             return -EPERM;
> +     }
> +
> +     if ( (!cap_capable(current, CAP_SETPCAP))
> +          &&
> +#else /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */
> +     if (
> +#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */

Looks functionally correct, though I'd much rather see something like:

#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
static inline int cap_may_setcap(struct task_struct *t)
{
        /*
         * No support for remote process capability manipulation
         * with filesystem capability support.
         */
        return target == current;
}
static inline int cap_capable_setpcap(void)
{
        return cap_capable(current, CAP_SETPCAP);
}
#else
static inline int cap_may_setcap(struct task_struct *t) { return 1; }
static inline int cap_capable_setpcap(void) { return 1; };
#endif

int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,
                   kernel_cap_t *inheritable, kernel_cap_t *permitted)
{
        if (!cap_may_setcap(target))
                return -EPERM;
        if (!cap_capable_setpcap()) && !cap_issubset (*inheritable,
           cap_combine (target->cap_inheritable, current->cap_permitted))) {
                /* incapable of using this inheritable set */
                return -EPERM;
...


Any thoughts on whether, and how long, we would keep
CONFIG_SECURITY_FILE_CAPABILITIES around?  Just while it is still being
developed, or is this something we'd always want to offer to be compiled
out?

If we'll always keep it configurable, then I suppose the fscaps
functions could be moved to a new file...

thanks,
-serge

> +
> +             !cap_issubset (*inheritable,
>                          cap_combine (target->cap_inheritable,
>                                       current->cap_permitted))) {
> +             /* incapable of using this inheritable set */
>               return -EPERM;
>       }
> 
> -- 
> 1.5.1.3
> 

-
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

Reply via email to