Index: docs/capng_lock.3 =================================================================== --- a/docs/capng_lock.3 (revision 55) +++ b/docs/capng_lock.3 (working copy) @@ -8,12 +8,13 @@ .SH "DESCRIPTION" -capng_lock will take steps to prevent children of the current process to regain full privileges if the uid is 0. This should be called while possessing the CAP_SETPCAP capability in the kernel. This function will do the following if permitted by the kernel: Set the NOROOT option on for PR_SET_SECUREBITS, set the NOROOT_LOCKED option to on for PR_SET_SECUREBITS, set the PR_NO_SETUID_FIXUP option on for PR_SET_SECUREBITS, and set the PR_NO_SETUID_FIXUP_LOCKED option on for PR_SET_SECUREBITS. +capng_lock will take steps to prevent children of the current process from gaining privileges by executing setuid programs. This should be called while possessing the CAP_SETPCAP capability in the kernel. +This function will do the following if permitted by the kernel: If the kernel supports PR_SET_NO_NEW_PRIVS, it will use it. Otherwise it will set the NOROOT option on for PR_SET_SECUREBITS, set the NOROOT_LOCKED option to on for PR_SET_SECUREBITS, set the PR_NO_SETUID_FIXUP option on for PR_SET_SECUREBITS, and set the PR_NO_SETUID_FIXUP_LOCKED option on for PR_SET_SECUREBITS. If both fail, it will return an error. .SH "RETURN VALUE" -This returns 0 on success and a negative number on failure. -1 means a failure setting any of the PR_SET_SECUREBITS options. +This returns 0 on success and a negative number on failure. -1 means a failure to use PR_SET_NO_NEW_PRIVS and a failure setting any of the PR_SET_SECUREBITS options. .SH "SEE ALSO" Index: src/cap-ng.c =================================================================== --- a/src/cap-ng.c (revision 55) +++ b/src/cap-ng.c (working copy) @@ -49,6 +49,7 @@ * 2.6.24 kernel XATTR_NAME_CAPS * 2.6.25 kernel PR_CAPBSET_DROP, CAPABILITY_VERSION_2 * 2.6.26 kernel PR_SET_SECUREBITS, SECURE_*_LOCKED, VERSION_3 + * 3.5 kernel PR_SET_NO_NEW_PRIVS */ /* External syscall prototypes */ @@ -126,6 +127,14 @@ #define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */ #endif +/* prctl values that we use */ +#ifndef PR_SET_SECUREBITS +#define PR_SET_SECUREBITS 28 +#endif +#ifndef PR_SET_NO_NEW_PRIVS +#define PR_SET_NO_NEW_PRIVS 38 +#endif + // States: new, allocated, initted, updated, applied typedef enum { CAPNG_NEW, CAPNG_ERROR, CAPNG_ALLOCATED, CAPNG_INIT, CAPNG_UPDATED, CAPNG_APPLIED } capng_states_t; @@ -703,15 +712,22 @@ int capng_lock(void) { -#ifdef PR_SET_SECUREBITS - int rc = prctl(PR_SET_SECUREBITS, - 1 << SECURE_NOROOT | - 1 << SECURE_NOROOT_LOCKED | - 1 << SECURE_NO_SETUID_FIXUP | - 1 << SECURE_NO_SETUID_FIXUP_LOCKED, 0, 0, 0); + int rc; + + // On Linux 3.5 and up, we can directly prevent ourselves and + // our descendents from gaining privileges. + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0) + return 0; + + // This kernel is too old or otherwise doesn't support + // PR_SET_NO_NEW_PRIVS. Fall back to using securebits. + rc = prctl(PR_SET_SECUREBITS, + 1 << SECURE_NOROOT | + 1 << SECURE_NOROOT_LOCKED | + 1 << SECURE_NO_SETUID_FIXUP | + 1 << SECURE_NO_SETUID_FIXUP_LOCKED, 0, 0, 0); if (rc) return -1; -#endif return 0; }