Fix use of SECURE_ALL_BITS/SECURE_ALL_LOCKS.
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.
Also add a compile-time assert to make sure we identify these changes
sooner going forward.
Bug: 27632733
Change-Id: I6cf9c56fec222347575bd0d1147287aac6572e67
diff --git a/Android.mk b/Android.mk
index 82f4c29..9be2907 100644
--- a/Android.mk
+++ b/Android.mk
@@ -24,9 +24,7 @@
syscall_filter.c \
util.c
-# TODO(b/27632733): Re-enable including the system's <linux/securebits.h>.
-#minijailCommonCFlags := -DHAVE_SECUREBITS_H -Wall -Werror
-minijailCommonCFlags := -Wall -Werror
+minijailCommonCFlags := -DHAVE_SECUREBITS_H -Wall -Werror
minijailCommonLibraries := libcap
# Android devices running kernel version < 3.8 are not required to
diff --git a/libminijail.c b/libminijail.c
index 2927b62..fcfee1e 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -43,13 +43,28 @@
#include "util.h"
#ifdef HAVE_SECUREBITS_H
-#include <linux/securebits.h>
+# include <linux/securebits.h>
#else
-#define SECURE_ALL_BITS 0x15
-#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
+# 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)
+
+/*
+ * Assert the value of SECURE_ALL_BITS at compile-time.
+ * Brillo 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__
+_Static_assert(SECURE_ALL_BITS == 0x55, "SECURE_ALL_BITS == 0x55.");
#endif
-/* Until these are reliably available in linux/prctl.h */
+/* Until these are reliably available in linux/prctl.h. */
#ifndef PR_SET_SECCOMP
# define PR_SET_SECCOMP 22
#endif
@@ -1444,8 +1459,25 @@
*/
if (prctl(PR_SET_KEEPCAPS, 1))
pdie("prctl(PR_SET_KEEPCAPS)");
- if (prctl
- (PR_SET_SECUREBITS, SECURE_ALL_BITS | SECURE_ALL_LOCKS))
+
+ /*
+ * 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.
+ */
+ 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);
+ }
+ }
+ if (securebits_ret < 0)
pdie("prctl(PR_SET_SECUREBITS)");
}