Anomalous output from getpcaps(1) for process with all capabilities
Serge E. Hallyn
serge at hallyn.com
Mon Dec 23 19:14:21 UTC 2019
On Sun, Dec 22, 2019 at 10:00:06AM -0800, Andrew G. Morgan wrote:
> I can take a look, but I'm not really convinced this isn't going to
> cause me grief at some point in the future when the kernel adds
> support for another capability and all' does not equal all. I've done
> some digging and I thought it was worth writing up.
>
> Today, the kernel treats 'all' (as it is defined by libcap today)
> differently for file and process capabilities. I suspect this is
> contributing to expectations about what all means, because all as
> defined today is effectively useless, and somewhere in the kernel
> we've worked around it for filecaps when we shouldn't have.
>
> Explanation of kernel bug (no use of 'all' here):
>
> 1) placing, say, bit-63 (undef today) and bit-0 (cap_chown) on the
> permitted (fP) vector of a file, yields a file that can execute - it
> gets pP=cap_chown.
>
> cd libcap/progs ; make ; cp capsh pcapsh ; sudo setcap
> 63,cap_setpcap,cap_chown=p pcapsh
>
> ./pcapsh --print
>
> 2) dropping cap_chown from the bounding set causes this same file to
> not run (insufficient privilege) because the file has been setup to
> require cap_chown, but can't have it so (by design) we deny execution
> altogether -- this fails:
>
> ./pcapsh --drop=cap_chown --print == --print
>
> To be consistent, (1) should fail because bit-63 is being dropped by
> the bounding set at execution time. That is, a binary that requires
> some future definition for capability #63 to run successfully should
> fail on a kernel that does not support it today. This but was
> introduced with this kernel commit:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/security/commoncap.c?id=7d8b6c63751cfbbe5eef81a48c22978b3407a3ad
>
> Ironically, the commit message declares the fact that (4) now passes
> is the fix. The real fix is to think about what we mean by 'all'.
Yes, I get the feeling you're right.
It'd be nice to simply say "you can only enable the caps you know
about, bit by bit." The problem is, we have distributions, and we
have containers, and demanding that all filecap-enabled binaries be
fixed up every time you switch to a new kernel with more or fewer
capabilities is unworkable.
One thing we could do is declare that bit nbits-1 (63 in 64 bit caps)
means "all caps that the kernel knows about." If 63 and any other
caps are enabled, then -EINVAL. If/when we switch to 128 bit caps,
then bit 63 becomes a valid cap there, and 127 is 'all'.
Of course that's not at all backward compatible, so would have to be
done in a new capability version.
-serge
More information about the Linux-security-module-archive
mailing list