Implement initial ambient capabilities support.
Credit to Brian McGillion for the initial implementation (in
https://android-review.googlesource.com/#/c/302756/).
Current support allows callers to also set ambient capabilities when
using regular capabilities. A follow-up CL will clean up the preloading
situation wrt ambient capabilities.
Bug: 32066154
Test: Use 'drop_privs' executable, check that it gets ambient caps.
Change-Id: If493fb5886fe9798436a749b7ebdbc04f00000b6
diff --git a/system.c b/system.c
index 05d0c47..49f8915 100644
--- a/system.c
+++ b/system.c
@@ -35,40 +35,33 @@
#define SECURE_ALL_BITS 0x55
#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
#endif
-/* For kernels < 4.3. */
-#define OLD_SECURE_ALL_BITS 0x15
-#define OLD_SECURE_ALL_LOCKS (OLD_SECURE_ALL_BITS << 1)
+
+#define SECURE_BITS_NO_AMBIENT 0x15
+#define SECURE_LOCKS_NO_AMBIENT (SECURE_BITS_NO_AMBIENT << 1)
/*
* Assert the value of SECURE_ALL_BITS at compile-time.
- * Brillo devices are currently compiled against 4.4 kernel headers. Kernel 4.3
+ * Android devices are currently compiled against 4.4 kernel headers. Kernel 4.3
* added a new securebit.
* When a new securebit is added, the new SECURE_ALL_BITS mask will return EPERM
* when used on older kernels. The compile-time assert will catch this situation
* at compile time.
*/
-#ifdef __BRILLO__
+#if defined(__ANDROID__)
_Static_assert(SECURE_ALL_BITS == 0x55, "SECURE_ALL_BITS == 0x55.");
#endif
int lock_securebits(void)
{
/*
- * Kernels 4.3+ define a new securebit (SECURE_NO_CAP_AMBIENT_RAISE),
- * so using the SECURE_ALL_BITS and SECURE_ALL_LOCKS masks from
- * newer kernel headers will return EPERM on older kernels. Detect this,
- * and retry with the right mask for older (2.6.26-4.2) kernels.
+ * Ambient capabilities can only be raised if they're already present
+ * in the permitted *and* inheritable set. Therefore, we don't really
+ * need to lock the NO_CAP_AMBIENT_RAISE securebit, since we are already
+ * configuring the permitted and inheritable set.
*/
int securebits_ret =
- prctl(PR_SET_SECUREBITS, SECURE_ALL_BITS | SECURE_ALL_LOCKS);
- if (securebits_ret < 0) {
- if (errno == EPERM) {
- /* Possibly running on kernel < 4.3. */
- securebits_ret =
- prctl(PR_SET_SECUREBITS,
- OLD_SECURE_ALL_BITS | OLD_SECURE_ALL_LOCKS);
- }
- }
+ prctl(PR_SET_SECUREBITS,
+ SECURE_BITS_NO_AMBIENT | SECURE_LOCKS_NO_AMBIENT);
if (securebits_ret < 0) {
pwarn("prctl(PR_SET_SECUREBITS) failed");
return -1;
@@ -144,6 +137,12 @@
return last_valid_cap;
}
+int cap_ambient_supported(void)
+{
+ return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >=
+ 0;
+}
+
int config_net_loopback(void)
{
const char ifname[] = "lo";