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