Add test for ambient caps
PR_CAP_AMBIENT landed in 4.3 and has been backported to earlier kernels
in kernel/common.
Test: bionic-unit-test --gtest_filter=sys_prctl.pr_cap_ambient
Change-Id: I632f6316ef1a4eb636d2bf7e07d541e400567ef4
Signed-off-by: Greg Hackmann <ghackmann@google.com>
diff --git a/tests/sys_prctl_test.cpp b/tests/sys_prctl_test.cpp
index 205db86..1d80dbc 100644
--- a/tests/sys_prctl_test.cpp
+++ b/tests/sys_prctl_test.cpp
@@ -15,7 +15,9 @@
*/
#include <inttypes.h>
+#include <limits.h>
#include <stdio.h>
+#include <sys/capability.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <unistd.h>
@@ -64,3 +66,51 @@
GTEST_LOG_(INFO) << "This test does nothing as it tests an Android specific kernel feature.";
#endif
}
+
+TEST(sys_prctl, pr_cap_ambient) {
+// PR_CAP_AMBIENT was introduced in v4.3. Android devices should always
+// have a backport, but we can't guarantee it's available on the host.
+#if defined(__ANDROID__) || defined(PR_CAP_AMBIENT)
+ const std::string caps_sha =
+ "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/"
+ "?id=58319057b7847667f0c9585b9de0e8932b0fdb08";
+ const std::string caps_typo_sha =
+ "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/"
+ "?id=b7f76ea2ef6739ee484a165ffbac98deb855d3d3";
+
+ auto err = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
+ EXPECT_EQ(0, err);
+ // EINVAL -> unrecognized prctl option
+ ASSERT_NE(EINVAL, errno) << "kernel missing required commits:\n"
+ << caps_sha << "\n"
+ << caps_typo_sha << "\n";
+
+ // Unprivileged processes shouldn't be able to raise CAP_SYS_ADMIN,
+ // but they can check or lower it
+ err = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_SYS_ADMIN, 0, 0);
+ EXPECT_EQ(-1, err);
+ EXPECT_EQ(EPERM, errno);
+
+ err = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_SYS_ADMIN, 0, 0);
+ EXPECT_EQ(0, err);
+
+ err = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, CAP_SYS_ADMIN, 0, 0);
+ EXPECT_EQ(0, err);
+
+ // ULONG_MAX isn't a legal cap
+ err = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, ULONG_MAX, 0, 0);
+ EXPECT_EQ(-1, err);
+ EXPECT_EQ(EINVAL, errno);
+
+ err = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, ULONG_MAX, 0, 0);
+ EXPECT_EQ(-1, err);
+ EXPECT_EQ(EINVAL, errno);
+
+ err = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, ULONG_MAX, 0, 0);
+ EXPECT_EQ(-1, err);
+ EXPECT_EQ(EINVAL, errno);
+#else
+ GTEST_LOG_(INFO)
+ << "Skipping test that requires host support for PR_CAP_AMBIENT.";
+#endif
+}