summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls/linux
diff options
context:
space:
mode:
authorMichael Pratt <mpratt@google.com>2019-06-05 13:59:01 -0700
committerShentubot <shentubot@google.com>2019-06-05 14:00:13 -0700
commitd3ed9baac0dc967eaf6d3e3f986cafe60604121a (patch)
tree47121539775297207ba205b60b136c9093d5d393 /test/syscalls/linux
parentcecb71dc37a77d8e4e88cdfada92a37a72c67602 (diff)
Implement dumpability tracking and checks
We don't actually support core dumps, but some applications want to get/set dumpability, which still has an effect in procfs. Lack of support for set-uid binaries or fs creds simplifies things a bit. As-is, processes started via CreateProcess (i.e., init and sentryctl exec) have normal dumpability. I'm a bit torn on whether sentryctl exec tasks should be dumpable, but at least since they have no parent normal UID/GID checks should protect them. PiperOrigin-RevId: 251712714
Diffstat (limited to 'test/syscalls/linux')
-rw-r--r--test/syscalls/linux/BUILD1
-rw-r--r--test/syscalls/linux/prctl.cc34
-rw-r--r--test/syscalls/linux/proc.cc57
3 files changed, 92 insertions, 0 deletions
diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD
index ba9fd6d1f..7633ab162 100644
--- a/test/syscalls/linux/BUILD
+++ b/test/syscalls/linux/BUILD
@@ -1317,6 +1317,7 @@ cc_binary(
linkstatic = 1,
deps = [
"//test/util:capability_util",
+ "//test/util:cleanup",
"//test/util:multiprocess_util",
"//test/util:posix_error",
"//test/util:test_util",
diff --git a/test/syscalls/linux/prctl.cc b/test/syscalls/linux/prctl.cc
index bce42dc74..bd1779557 100644
--- a/test/syscalls/linux/prctl.cc
+++ b/test/syscalls/linux/prctl.cc
@@ -17,10 +17,12 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+
#include <string>
#include "gtest/gtest.h"
#include "test/util/capability_util.h"
+#include "test/util/cleanup.h"
#include "test/util/multiprocess_util.h"
#include "test/util/posix_error.h"
#include "test/util/test_util.h"
@@ -35,6 +37,16 @@ namespace testing {
namespace {
+#ifndef SUID_DUMP_DISABLE
+#define SUID_DUMP_DISABLE 0
+#endif /* SUID_DUMP_DISABLE */
+#ifndef SUID_DUMP_USER
+#define SUID_DUMP_USER 1
+#endif /* SUID_DUMP_USER */
+#ifndef SUID_DUMP_ROOT
+#define SUID_DUMP_ROOT 2
+#endif /* SUID_DUMP_ROOT */
+
TEST(PrctlTest, NameInitialized) {
const size_t name_length = 20;
char name[name_length] = {};
@@ -178,6 +190,28 @@ TEST(PrctlTest, InvalidPrSetMM) {
ASSERT_THAT(prctl(PR_SET_MM, 0, 0, 0, 0), SyscallFailsWithErrno(EPERM));
}
+// Sanity check that dumpability is remembered.
+TEST(PrctlTest, SetGetDumpability) {
+ int before;
+ ASSERT_THAT(before = prctl(PR_GET_DUMPABLE), SyscallSucceeds());
+ auto cleanup = Cleanup([before] {
+ ASSERT_THAT(prctl(PR_SET_DUMPABLE, before), SyscallSucceeds());
+ });
+
+ EXPECT_THAT(prctl(PR_SET_DUMPABLE, SUID_DUMP_DISABLE), SyscallSucceeds());
+ EXPECT_THAT(prctl(PR_GET_DUMPABLE),
+ SyscallSucceedsWithValue(SUID_DUMP_DISABLE));
+
+ EXPECT_THAT(prctl(PR_SET_DUMPABLE, SUID_DUMP_USER), SyscallSucceeds());
+ EXPECT_THAT(prctl(PR_GET_DUMPABLE), SyscallSucceedsWithValue(SUID_DUMP_USER));
+}
+
+// SUID_DUMP_ROOT cannot be set via PR_SET_DUMPABLE.
+TEST(PrctlTest, RootDumpability) {
+ EXPECT_THAT(prctl(PR_SET_DUMPABLE, SUID_DUMP_ROOT),
+ SyscallFailsWithErrno(EINVAL));
+}
+
} // namespace
} // namespace testing
diff --git a/test/syscalls/linux/proc.cc b/test/syscalls/linux/proc.cc
index ede6fb860..924b98e3a 100644
--- a/test/syscalls/linux/proc.cc
+++ b/test/syscalls/linux/proc.cc
@@ -69,9 +69,11 @@
// way to get it tested on both gVisor, PTrace and Linux.
using ::testing::AllOf;
+using ::testing::AnyOf;
using ::testing::ContainerEq;
using ::testing::Contains;
using ::testing::ContainsRegex;
+using ::testing::Eq;
using ::testing::Gt;
using ::testing::HasSubstr;
using ::testing::IsSupersetOf;
@@ -86,6 +88,16 @@ namespace gvisor {
namespace testing {
namespace {
+#ifndef SUID_DUMP_DISABLE
+#define SUID_DUMP_DISABLE 0
+#endif /* SUID_DUMP_DISABLE */
+#ifndef SUID_DUMP_USER
+#define SUID_DUMP_USER 1
+#endif /* SUID_DUMP_USER */
+#ifndef SUID_DUMP_ROOT
+#define SUID_DUMP_ROOT 2
+#endif /* SUID_DUMP_ROOT */
+
// O_LARGEFILE as defined by Linux. glibc tries to be clever by setting it to 0
// because "it isn't needed", even though Linux can return it via F_GETFL.
constexpr int kOLargeFile = 00100000;
@@ -1896,6 +1908,51 @@ void CheckDuplicatesRecursively(std::string path) {
TEST(Proc, NoDuplicates) { CheckDuplicatesRecursively("/proc"); }
+// Most /proc/PID files are owned by the task user with SUID_DUMP_USER.
+TEST(ProcPid, UserDumpableOwner) {
+ int before;
+ ASSERT_THAT(before = prctl(PR_GET_DUMPABLE), SyscallSucceeds());
+ auto cleanup = Cleanup([before] {
+ ASSERT_THAT(prctl(PR_SET_DUMPABLE, before), SyscallSucceeds());
+ });
+
+ EXPECT_THAT(prctl(PR_SET_DUMPABLE, SUID_DUMP_USER), SyscallSucceeds());
+
+ // This applies to the task directory itself and files inside.
+ struct stat st;
+ ASSERT_THAT(stat("/proc/self/", &st), SyscallSucceeds());
+ EXPECT_EQ(st.st_uid, geteuid());
+ EXPECT_EQ(st.st_gid, getegid());
+
+ ASSERT_THAT(stat("/proc/self/stat", &st), SyscallSucceeds());
+ EXPECT_EQ(st.st_uid, geteuid());
+ EXPECT_EQ(st.st_gid, getegid());
+}
+
+// /proc/PID files are owned by root with SUID_DUMP_DISABLE.
+TEST(ProcPid, RootDumpableOwner) {
+ int before;
+ ASSERT_THAT(before = prctl(PR_GET_DUMPABLE), SyscallSucceeds());
+ auto cleanup = Cleanup([before] {
+ ASSERT_THAT(prctl(PR_SET_DUMPABLE, before), SyscallSucceeds());
+ });
+
+ EXPECT_THAT(prctl(PR_SET_DUMPABLE, SUID_DUMP_DISABLE), SyscallSucceeds());
+
+ // This *does not* applies to the task directory itself (or other 0555
+ // directories), but does to files inside.
+ struct stat st;
+ ASSERT_THAT(stat("/proc/self/", &st), SyscallSucceeds());
+ EXPECT_EQ(st.st_uid, geteuid());
+ EXPECT_EQ(st.st_gid, getegid());
+
+ // This file is owned by root. Also allow nobody in case this test is running
+ // in a userns without root mapped.
+ ASSERT_THAT(stat("/proc/self/stat", &st), SyscallSucceeds());
+ EXPECT_THAT(st.st_uid, AnyOf(Eq(0), Eq(65534)));
+ EXPECT_THAT(st.st_gid, AnyOf(Eq(0), Eq(65534)));
+}
+
} // namespace
} // namespace testing
} // namespace gvisor