Vulnerability Development mailing list archives

Re: Ports 0-1023?


From: Kevin Easton <s3159795 () student anu edu au>
Date: Sun, 7 Jul 2002 00:07:05 +1000



On Fri Jul 05 2002, Brian Hatch (vuln-dev () ifokr org) wrote:

POSIX capabilities do compartmentalize permissions to 'does this 
process have capability X' instead of 'is this process running 
as uid/euid root'. However in the Linux kernel, the capabilities 
calls all look like this: 

        if ( port < 1024 && !capable(CAP_BIND_NET_SERVICE) ) { 
                /* complain */ 
        } 

But the capable call is defined as: 

        int capable(int capability) { 
                if ( euid==0 || uid==0 ) return 1 
        }

(That's all pseudo code, not the actual code.) 

So although capabilites are built into the kernel, the base check 
is still just using {e}uid==0. 


Well actually the capable call (in kernel 2.2.21 at any rate) is defined
in sched.h thus:

extern inline int capable(int cap)
{
#if 1 /* ok now */
        if (cap_raised(current->cap_effective, cap))
#else
        if (cap_is_fs_cap(cap) ? current->fsuid == 0 : current->euid == 0)
#endif
        {
                current->flags |= PF_SUPERPRIV;
                return 1;
        }
        return 0;
}

... so the code that is actually used is cap_raised(), which is defined in
capability.h as:

#define cap_raised(c, flag)  (cap_t(c) & CAP_TO_MASK(flag))

ie, the cap_effective mask of the current task structure is checked against
the requested capability.  The capability checking code is all good to go - 
it only requires a creative way of selectively setting cap_effective to work.
I think rather than a proliferation of filesystem "setcap" bits for
executables, it's likely that a program would remain setuid root, but 
drop all unneeded capabilities as it's first task when run (ie, ping would
drop all capabilities except CAP_NET_RAW).

        - Kevin.


Current thread: