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