summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls
diff options
context:
space:
mode:
authorNicolas Lacasse <nlacasse@google.com>2020-08-26 10:03:46 -0700
committerAndrei Vagin <avagin@gmail.com>2020-09-09 17:53:10 -0700
commit2a322c451e0a04df55d8fa4ea6e055da39231efa (patch)
tree0c4a80d1db58c46d15c8569359356d387e9db67a /test/syscalls
parent5116c7be8d64934980937113870a8fbc82b14ea0 (diff)
tmpfs: Allow xattrs in the trusted namespace if creds has CAP_SYS_ADMIN.
This is needed to support the overlay opaque attribute. PiperOrigin-RevId: 328552985
Diffstat (limited to 'test/syscalls')
-rw-r--r--test/syscalls/linux/memfd.cc17
-rw-r--r--test/syscalls/linux/xattr.cc74
2 files changed, 75 insertions, 16 deletions
diff --git a/test/syscalls/linux/memfd.cc b/test/syscalls/linux/memfd.cc
index f8b7f7938..4a450742b 100644
--- a/test/syscalls/linux/memfd.cc
+++ b/test/syscalls/linux/memfd.cc
@@ -14,12 +14,10 @@
#include <errno.h>
#include <fcntl.h>
-#include <linux/magic.h>
#include <linux/memfd.h>
#include <linux/unistd.h>
#include <string.h>
#include <sys/mman.h>
-#include <sys/statfs.h>
#include <sys/syscall.h>
#include <vector>
@@ -53,6 +51,7 @@ namespace {
#define F_SEAL_GROW 0x0004
#define F_SEAL_WRITE 0x0008
+using ::gvisor::testing::IsTmpfs;
using ::testing::StartsWith;
const std::string kMemfdName = "some-memfd";
@@ -444,20 +443,6 @@ TEST(MemfdTest, SealsAreInodeLevelProperties) {
EXPECT_THAT(ftruncate(memfd3.get(), kPageSize), SyscallFailsWithErrno(EPERM));
}
-PosixErrorOr<bool> IsTmpfs(const std::string& path) {
- struct statfs stat;
- if (statfs(path.c_str(), &stat)) {
- if (errno == ENOENT) {
- // Nothing at path, don't raise this as an error. Instead, just report no
- // tmpfs at path.
- return false;
- }
- return PosixError(errno,
- absl::StrFormat("statfs(\"%s\", %#p)", path, &stat));
- }
- return stat.f_type == TMPFS_MAGIC;
-}
-
// Tmpfs files also support seals, but are created with F_SEAL_SEAL.
TEST(MemfdTest, TmpfsFilesHaveSealSeal) {
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(IsTmpfs("/tmp")));
diff --git a/test/syscalls/linux/xattr.cc b/test/syscalls/linux/xattr.cc
index cbcf08451..5510a87a0 100644
--- a/test/syscalls/linux/xattr.cc
+++ b/test/syscalls/linux/xattr.cc
@@ -28,6 +28,7 @@
#include "test/syscalls/linux/file_base.h"
#include "test/util/capability_util.h"
#include "test/util/file_descriptor.h"
+#include "test/util/fs_util.h"
#include "test/util/posix_error.h"
#include "test/util/temp_path.h"
#include "test/util/test_util.h"
@@ -37,6 +38,8 @@ namespace testing {
namespace {
+using ::gvisor::testing::IsTmpfs;
+
class XattrTest : public FileTest {};
TEST_F(XattrTest, XattrNonexistentFile) {
@@ -604,6 +607,77 @@ TEST_F(XattrTest, XattrWithFD) {
EXPECT_THAT(fremovexattr(fd.get(), name), SyscallSucceeds());
}
+TEST_F(XattrTest, TrustedNamespaceWithCapSysAdmin) {
+ // Trusted namespace not supported in VFS1.
+ SKIP_IF(IsRunningWithVFS1());
+
+ // TODO(b/66162845): Only gVisor tmpfs currently supports trusted namespace.
+ SKIP_IF(IsRunningOnGvisor() &&
+ !ASSERT_NO_ERRNO_AND_VALUE(IsTmpfs(test_file_name_)));
+
+ // Setting/Getting in the trusted namespace requires CAP_SYS_ADMIN.
+ SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
+
+ const char* path = test_file_name_.c_str();
+ const char name[] = "trusted.test";
+
+ // Set.
+ char val = 'a';
+ size_t size = sizeof(val);
+ EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0), SyscallSucceeds());
+
+ // Get.
+ char got = '\0';
+ EXPECT_THAT(getxattr(path, name, &got, size), SyscallSucceedsWithValue(size));
+ EXPECT_EQ(val, got);
+
+ // List.
+ char list[sizeof(name)];
+ EXPECT_THAT(listxattr(path, list, sizeof(list)),
+ SyscallSucceedsWithValue(sizeof(name)));
+ EXPECT_STREQ(list, name);
+
+ // Remove.
+ EXPECT_THAT(removexattr(path, name), SyscallSucceeds());
+
+ // Get should now return ENODATA.
+ EXPECT_THAT(getxattr(path, name, &got, size), SyscallFailsWithErrno(ENODATA));
+}
+
+TEST_F(XattrTest, TrustedNamespaceWithoutCapSysAdmin) {
+ // Trusted namespace not supported in VFS1.
+ SKIP_IF(IsRunningWithVFS1());
+
+ // TODO(b/66162845): Only gVisor tmpfs currently supports trusted namespace.
+ SKIP_IF(IsRunningOnGvisor() &&
+ !ASSERT_NO_ERRNO_AND_VALUE(IsTmpfs(test_file_name_)));
+
+ // Drop CAP_SYS_ADMIN if we have it.
+ if (ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN))) {
+ EXPECT_NO_ERRNO(SetCapability(CAP_SYS_ADMIN, false));
+ }
+
+ const char* path = test_file_name_.c_str();
+ const char name[] = "trusted.test";
+
+ // Set fails.
+ char val = 'a';
+ size_t size = sizeof(val);
+ EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0),
+ SyscallFailsWithErrno(EPERM));
+
+ // Get fails.
+ char got = '\0';
+ EXPECT_THAT(getxattr(path, name, &got, size), SyscallFailsWithErrno(ENODATA));
+
+ // List still works, but returns no items.
+ char list[sizeof(name)];
+ EXPECT_THAT(listxattr(path, list, sizeof(list)), SyscallSucceedsWithValue(0));
+
+ // Remove fails.
+ EXPECT_THAT(removexattr(path, name), SyscallFailsWithErrno(EPERM));
+}
+
} // namespace
} // namespace testing