From ba1f77d6504f74c1fad44119e1b2f912ce5aae23 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Tue, 6 Dec 2016 15:17:59 -0800 Subject: [PATCH] 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 --- tests/sys_prctl_test.cpp | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/sys_prctl_test.cpp b/tests/sys_prctl_test.cpp index 205db86b0..1d80dbc1a 100644 --- a/tests/sys_prctl_test.cpp +++ b/tests/sys_prctl_test.cpp @@ -15,7 +15,9 @@ */ #include +#include #include +#include #include #include #include @@ -64,3 +66,51 @@ TEST(sys_prctl, bug_20017123) { 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 +}