github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/syscalls/linux/xattr.cc (about)

     1  // Copyright 2019 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include <errno.h>
    16  #include <fcntl.h>
    17  #include <limits.h>
    18  #include <sys/types.h>
    19  #include <sys/xattr.h>
    20  #include <unistd.h>
    21  
    22  #include <string>
    23  #include <vector>
    24  
    25  #include "gmock/gmock.h"
    26  #include "gtest/gtest.h"
    27  #include "absl/container/flat_hash_set.h"
    28  #include "test/syscalls/linux/file_base.h"
    29  #include "test/util/capability_util.h"
    30  #include "test/util/file_descriptor.h"
    31  #include "test/util/fs_util.h"
    32  #include "test/util/posix_error.h"
    33  #include "test/util/temp_path.h"
    34  #include "test/util/test_util.h"
    35  
    36  namespace gvisor {
    37  namespace testing {
    38  
    39  namespace {
    40  
    41  using ::gvisor::testing::IsTmpfs;
    42  
    43  class XattrTest : public FileTest {};
    44  
    45  TEST_F(XattrTest, XattrNonexistentFile) {
    46    const char* path = "/does/not/exist";
    47    const char* name = "user.test";
    48    EXPECT_THAT(setxattr(path, name, nullptr, 0, /*flags=*/0),
    49                SyscallFailsWithErrno(ENOENT));
    50    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallFailsWithErrno(ENOENT));
    51    EXPECT_THAT(listxattr(path, nullptr, 0), SyscallFailsWithErrno(ENOENT));
    52    EXPECT_THAT(removexattr(path, name), SyscallFailsWithErrno(ENOENT));
    53  }
    54  
    55  TEST_F(XattrTest, XattrNullName) {
    56    const char* path = test_file_name_.c_str();
    57  
    58    EXPECT_THAT(setxattr(path, nullptr, nullptr, 0, /*flags=*/0),
    59                SyscallFailsWithErrno(EFAULT));
    60    EXPECT_THAT(getxattr(path, nullptr, nullptr, 0),
    61                SyscallFailsWithErrno(EFAULT));
    62    EXPECT_THAT(removexattr(path, nullptr), SyscallFailsWithErrno(EFAULT));
    63  }
    64  
    65  TEST_F(XattrTest, XattrEmptyName) {
    66    const char* path = test_file_name_.c_str();
    67  
    68    EXPECT_THAT(setxattr(path, "", nullptr, 0, /*flags=*/0),
    69                SyscallFailsWithErrno(ERANGE));
    70    EXPECT_THAT(getxattr(path, "", nullptr, 0), SyscallFailsWithErrno(ERANGE));
    71    EXPECT_THAT(removexattr(path, ""), SyscallFailsWithErrno(ERANGE));
    72  }
    73  
    74  TEST_F(XattrTest, XattrLargeName) {
    75    const char* path = test_file_name_.c_str();
    76    std::string name = "user.";
    77    name += std::string(XATTR_NAME_MAX - name.length(), 'a');
    78  
    79    if (!IsRunningOnGvisor()) {
    80      // In gVisor, access to xattrs is controlled with an explicit list of
    81      // allowed names. This name isn't going to be configured to allow access, so
    82      // don't test it.
    83      EXPECT_THAT(setxattr(path, name.c_str(), nullptr, 0, /*flags=*/0),
    84                  SyscallSucceeds());
    85      EXPECT_THAT(getxattr(path, name.c_str(), nullptr, 0),
    86                  SyscallSucceedsWithValue(0));
    87    }
    88  
    89    name += "a";
    90    EXPECT_THAT(setxattr(path, name.c_str(), nullptr, 0, /*flags=*/0),
    91                SyscallFailsWithErrno(ERANGE));
    92    EXPECT_THAT(getxattr(path, name.c_str(), nullptr, 0),
    93                SyscallFailsWithErrno(ERANGE));
    94    EXPECT_THAT(removexattr(path, name.c_str()), SyscallFailsWithErrno(ERANGE));
    95  }
    96  
    97  TEST_F(XattrTest, XattrInvalidPrefix) {
    98    const char* path = test_file_name_.c_str();
    99    std::string name(XATTR_NAME_MAX, 'a');
   100    EXPECT_THAT(setxattr(path, name.c_str(), nullptr, 0, /*flags=*/0),
   101                SyscallFailsWithErrno(EOPNOTSUPP));
   102    EXPECT_THAT(getxattr(path, name.c_str(), nullptr, 0),
   103                SyscallFailsWithErrno(EOPNOTSUPP));
   104    EXPECT_THAT(removexattr(path, name.c_str()),
   105                SyscallFailsWithErrno(EOPNOTSUPP));
   106  }
   107  
   108  // Do not allow save/restore cycles after making the test file read-only, as
   109  // the restore will fail to open it with r/w permissions.
   110  TEST_F(XattrTest, XattrReadOnly) {
   111    // Drop capabilities that allow us to override file and directory permissions.
   112    AutoCapability cap1(CAP_DAC_OVERRIDE, false);
   113    AutoCapability cap2(CAP_DAC_READ_SEARCH, false);
   114  
   115    const char* path = test_file_name_.c_str();
   116    const char name[] = "user.test";
   117    char val = 'a';
   118    size_t size = sizeof(val);
   119  
   120    EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0), SyscallSucceeds());
   121  
   122    DisableSave ds;
   123    ASSERT_NO_ERRNO(testing::Chmod(test_file_name_, S_IRUSR));
   124  
   125    EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0),
   126                SyscallFailsWithErrno(EACCES));
   127    EXPECT_THAT(removexattr(path, name), SyscallFailsWithErrno(EACCES));
   128  
   129    char buf = '-';
   130    EXPECT_THAT(getxattr(path, name, &buf, size), SyscallSucceedsWithValue(size));
   131    EXPECT_EQ(buf, val);
   132  
   133    char list[sizeof(name)];
   134    EXPECT_THAT(listxattr(path, list, sizeof(list)),
   135                SyscallSucceedsWithValue(sizeof(name)));
   136    EXPECT_STREQ(list, name);
   137  }
   138  
   139  // Do not allow save/restore cycles after making the test file write-only, as
   140  // the restore will fail to open it with r/w permissions.
   141  TEST_F(XattrTest, XattrWriteOnly) {
   142    // Drop capabilities that allow us to override file and directory permissions.
   143    AutoCapability cap1(CAP_DAC_OVERRIDE, false);
   144    AutoCapability cap2(CAP_DAC_READ_SEARCH, false);
   145  
   146    DisableSave ds;
   147    ASSERT_NO_ERRNO(testing::Chmod(test_file_name_, S_IWUSR));
   148  
   149    const char* path = test_file_name_.c_str();
   150    const char name[] = "user.test";
   151    char val = 'a';
   152    size_t size = sizeof(val);
   153  
   154    EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0), SyscallSucceeds());
   155  
   156    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallFailsWithErrno(EACCES));
   157  
   158    // listxattr will succeed even without read permissions.
   159    char list[sizeof(name)];
   160    EXPECT_THAT(listxattr(path, list, sizeof(list)),
   161                SyscallSucceedsWithValue(sizeof(name)));
   162    EXPECT_STREQ(list, name);
   163  
   164    EXPECT_THAT(removexattr(path, name), SyscallSucceeds());
   165  }
   166  
   167  TEST_F(XattrTest, XattrTrustedWithNonadmin) {
   168    // TODO(b/148380782): Support setxattr and getxattr with "trusted" prefix.
   169    SKIP_IF(IsRunningOnGvisor());
   170    SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
   171  
   172    const char* path = test_file_name_.c_str();
   173    const char name[] = "trusted.abc";
   174    EXPECT_THAT(setxattr(path, name, nullptr, 0, /*flags=*/0),
   175                SyscallFailsWithErrno(EPERM));
   176    EXPECT_THAT(removexattr(path, name), SyscallFailsWithErrno(EPERM));
   177    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallFailsWithErrno(ENODATA));
   178  }
   179  
   180  TEST_F(XattrTest, XattrOnDirectory) {
   181    TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   182    const char name[] = "user.test";
   183    EXPECT_THAT(setxattr(dir.path().c_str(), name, nullptr, 0, /*flags=*/0),
   184                SyscallSucceeds());
   185    EXPECT_THAT(getxattr(dir.path().c_str(), name, nullptr, 0),
   186                SyscallSucceedsWithValue(0));
   187  
   188    char list[sizeof(name)];
   189    EXPECT_THAT(listxattr(dir.path().c_str(), list, sizeof(list)),
   190                SyscallSucceedsWithValue(sizeof(name)));
   191    EXPECT_STREQ(list, name);
   192  
   193    EXPECT_THAT(removexattr(dir.path().c_str(), name), SyscallSucceeds());
   194  }
   195  
   196  TEST_F(XattrTest, XattrOnSymlink) {
   197    TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   198    TempPath link = ASSERT_NO_ERRNO_AND_VALUE(
   199        TempPath::CreateSymlinkTo(dir.path(), test_file_name_));
   200    const char name[] = "user.test";
   201    EXPECT_THAT(setxattr(link.path().c_str(), name, nullptr, 0, /*flags=*/0),
   202                SyscallSucceeds());
   203    EXPECT_THAT(getxattr(link.path().c_str(), name, nullptr, 0),
   204                SyscallSucceedsWithValue(0));
   205  
   206    char list[sizeof(name)];
   207    EXPECT_THAT(listxattr(link.path().c_str(), list, sizeof(list)),
   208                SyscallSucceedsWithValue(sizeof(name)));
   209    EXPECT_STREQ(list, name);
   210  
   211    EXPECT_THAT(removexattr(link.path().c_str(), name), SyscallSucceeds());
   212  }
   213  
   214  TEST_F(XattrTest, XattrOnInvalidFileTypes) {
   215    const char name[] = "user.test";
   216  
   217    char char_device[] = "/dev/zero";
   218    EXPECT_THAT(setxattr(char_device, name, nullptr, 0, /*flags=*/0),
   219                SyscallFailsWithErrno(EPERM));
   220    EXPECT_THAT(getxattr(char_device, name, nullptr, 0),
   221                SyscallFailsWithErrno(ENODATA));
   222    EXPECT_THAT(listxattr(char_device, nullptr, 0), SyscallSucceedsWithValue(0));
   223  
   224    // Use tmpfs, where creation of named pipes is supported.
   225    const std::string fifo = NewTempAbsPathInDir("/dev/shm");
   226    const char* path = fifo.c_str();
   227    EXPECT_THAT(mknod(path, S_IFIFO | S_IRUSR | S_IWUSR, 0), SyscallSucceeds());
   228    EXPECT_THAT(setxattr(path, name, nullptr, 0, /*flags=*/0),
   229                SyscallFailsWithErrno(EPERM));
   230    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallFailsWithErrno(ENODATA));
   231    EXPECT_THAT(listxattr(path, nullptr, 0), SyscallSucceedsWithValue(0));
   232    EXPECT_THAT(removexattr(path, name), SyscallFailsWithErrno(EPERM));
   233  }
   234  
   235  TEST_F(XattrTest, SetXattrSizeSmallerThanValue) {
   236    const char* path = test_file_name_.c_str();
   237    const char name[] = "user.test";
   238    std::vector<char> val = {'a', 'a'};
   239    size_t size = 1;
   240    EXPECT_THAT(setxattr(path, name, val.data(), size, /*flags=*/0),
   241                SyscallSucceeds());
   242  
   243    std::vector<char> buf = {'-', '-'};
   244    std::vector<char> expected_buf = {'a', '-'};
   245    EXPECT_THAT(getxattr(path, name, buf.data(), buf.size()),
   246                SyscallSucceedsWithValue(size));
   247    EXPECT_EQ(buf, expected_buf);
   248  }
   249  
   250  TEST_F(XattrTest, SetXattrZeroSize) {
   251    const char* path = test_file_name_.c_str();
   252    const char name[] = "user.test";
   253    char val = 'a';
   254    EXPECT_THAT(setxattr(path, name, &val, 0, /*flags=*/0), SyscallSucceeds());
   255  
   256    char buf = '-';
   257    EXPECT_THAT(getxattr(path, name, &buf, XATTR_SIZE_MAX),
   258                SyscallSucceedsWithValue(0));
   259    EXPECT_EQ(buf, '-');
   260  }
   261  
   262  TEST_F(XattrTest, SetXattrSizeTooLarge) {
   263    const char* path = test_file_name_.c_str();
   264    const char name[] = "user.test";
   265  
   266    // Note that each particular fs implementation may stipulate a lower size
   267    // limit, in which case we actually may fail (e.g. error with ENOSPC) for
   268    // some sizes under XATTR_SIZE_MAX.
   269    size_t size = XATTR_SIZE_MAX + 1;
   270    std::vector<char> val(size);
   271    EXPECT_THAT(setxattr(path, name, val.data(), size, /*flags=*/0),
   272                SyscallFailsWithErrno(E2BIG));
   273  
   274    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallFailsWithErrno(ENODATA));
   275  }
   276  
   277  TEST_F(XattrTest, SetXattrNullValueAndNonzeroSize) {
   278    const char* path = test_file_name_.c_str();
   279    const char name[] = "user.test";
   280    EXPECT_THAT(setxattr(path, name, nullptr, 1, /*flags=*/0),
   281                SyscallFailsWithErrno(EFAULT));
   282  
   283    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallFailsWithErrno(ENODATA));
   284  }
   285  
   286  TEST_F(XattrTest, SetXattrNullValueAndZeroSize) {
   287    const char* path = test_file_name_.c_str();
   288    const char name[] = "user.test";
   289    EXPECT_THAT(setxattr(path, name, nullptr, 0, /*flags=*/0), SyscallSucceeds());
   290  
   291    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallSucceedsWithValue(0));
   292  }
   293  
   294  TEST_F(XattrTest, SetXattrValueTooLargeButOKSize) {
   295    const char* path = test_file_name_.c_str();
   296    const char name[] = "user.test";
   297    std::vector<char> val(XATTR_SIZE_MAX + 1);
   298    std::fill(val.begin(), val.end(), 'a');
   299    size_t size = 1;
   300    EXPECT_THAT(setxattr(path, name, val.data(), size, /*flags=*/0),
   301                SyscallSucceeds());
   302  
   303    std::vector<char> buf = {'-', '-'};
   304    std::vector<char> expected_buf = {'a', '-'};
   305    EXPECT_THAT(getxattr(path, name, buf.data(), size),
   306                SyscallSucceedsWithValue(size));
   307    EXPECT_EQ(buf, expected_buf);
   308  }
   309  
   310  TEST_F(XattrTest, SetXattrReplaceWithSmaller) {
   311    const char* path = test_file_name_.c_str();
   312    const char name[] = "user.test";
   313    std::vector<char> val = {'a', 'a'};
   314    EXPECT_THAT(setxattr(path, name, val.data(), 2, /*flags=*/0),
   315                SyscallSucceeds());
   316    EXPECT_THAT(setxattr(path, name, val.data(), 1, /*flags=*/0),
   317                SyscallSucceeds());
   318  
   319    std::vector<char> buf = {'-', '-'};
   320    std::vector<char> expected_buf = {'a', '-'};
   321    EXPECT_THAT(getxattr(path, name, buf.data(), 2), SyscallSucceedsWithValue(1));
   322    EXPECT_EQ(buf, expected_buf);
   323  }
   324  
   325  TEST_F(XattrTest, SetXattrReplaceWithLarger) {
   326    const char* path = test_file_name_.c_str();
   327    const char name[] = "user.test";
   328    std::vector<char> val = {'a', 'a'};
   329    EXPECT_THAT(setxattr(path, name, val.data(), 1, /*flags=*/0),
   330                SyscallSucceeds());
   331    EXPECT_THAT(setxattr(path, name, val.data(), 2, /*flags=*/0),
   332                SyscallSucceeds());
   333  
   334    std::vector<char> buf = {'-', '-'};
   335    EXPECT_THAT(getxattr(path, name, buf.data(), 2), SyscallSucceedsWithValue(2));
   336    EXPECT_EQ(buf, val);
   337  }
   338  
   339  TEST_F(XattrTest, SetXattrCreateFlag) {
   340    const char* path = test_file_name_.c_str();
   341    const char name[] = "user.test";
   342    EXPECT_THAT(setxattr(path, name, nullptr, 0, XATTR_CREATE),
   343                SyscallSucceeds());
   344    EXPECT_THAT(setxattr(path, name, nullptr, 0, XATTR_CREATE),
   345                SyscallFailsWithErrno(EEXIST));
   346  
   347    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallSucceedsWithValue(0));
   348  }
   349  
   350  TEST_F(XattrTest, SetXattrReplaceFlag) {
   351    const char* path = test_file_name_.c_str();
   352    const char name[] = "user.test";
   353    EXPECT_THAT(setxattr(path, name, nullptr, 0, XATTR_REPLACE),
   354                SyscallFailsWithErrno(ENODATA));
   355    EXPECT_THAT(setxattr(path, name, nullptr, 0, /*flags=*/0), SyscallSucceeds());
   356    EXPECT_THAT(setxattr(path, name, nullptr, 0, XATTR_REPLACE),
   357                SyscallSucceeds());
   358  
   359    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallSucceedsWithValue(0));
   360  }
   361  
   362  TEST_F(XattrTest, SetXattrInvalidFlags) {
   363    const char* path = test_file_name_.c_str();
   364    int invalid_flags = 0xff;
   365    EXPECT_THAT(setxattr(path, nullptr, nullptr, 0, invalid_flags),
   366                SyscallFailsWithErrno(EINVAL));
   367  }
   368  
   369  TEST_F(XattrTest, GetXattr) {
   370    const char* path = test_file_name_.c_str();
   371    const char name[] = "user.test";
   372    int val = 1234;
   373    size_t size = sizeof(val);
   374    EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0), SyscallSucceeds());
   375  
   376    int buf = 0;
   377    EXPECT_THAT(getxattr(path, name, &buf, size), SyscallSucceedsWithValue(size));
   378    EXPECT_EQ(buf, val);
   379  }
   380  
   381  TEST_F(XattrTest, GetXattrSizeSmallerThanValue) {
   382    const char* path = test_file_name_.c_str();
   383    const char name[] = "user.test";
   384    std::vector<char> val = {'a', 'a'};
   385    size_t size = val.size();
   386    EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0), SyscallSucceeds());
   387  
   388    char buf = '-';
   389    EXPECT_THAT(getxattr(path, name, &buf, 1), SyscallFailsWithErrno(ERANGE));
   390    EXPECT_EQ(buf, '-');
   391  }
   392  
   393  TEST_F(XattrTest, GetXattrSizeLargerThanValue) {
   394    const char* path = test_file_name_.c_str();
   395    const char name[] = "user.test";
   396    char val = 'a';
   397    EXPECT_THAT(setxattr(path, name, &val, 1, /*flags=*/0), SyscallSucceeds());
   398  
   399    std::vector<char> buf(XATTR_SIZE_MAX);
   400    std::fill(buf.begin(), buf.end(), '-');
   401    std::vector<char> expected_buf = buf;
   402    expected_buf[0] = 'a';
   403    EXPECT_THAT(getxattr(path, name, buf.data(), buf.size()),
   404                SyscallSucceedsWithValue(1));
   405    EXPECT_EQ(buf, expected_buf);
   406  }
   407  
   408  TEST_F(XattrTest, GetXattrZeroSize) {
   409    const char* path = test_file_name_.c_str();
   410    const char name[] = "user.test";
   411    char val = 'a';
   412    EXPECT_THAT(setxattr(path, name, &val, sizeof(val), /*flags=*/0),
   413                SyscallSucceeds());
   414  
   415    char buf = '-';
   416    EXPECT_THAT(getxattr(path, name, &buf, 0),
   417                SyscallSucceedsWithValue(sizeof(val)));
   418    EXPECT_EQ(buf, '-');
   419  }
   420  
   421  TEST_F(XattrTest, GetXattrSizeTooLarge) {
   422    const char* path = test_file_name_.c_str();
   423    const char name[] = "user.test";
   424    char val = 'a';
   425    EXPECT_THAT(setxattr(path, name, &val, sizeof(val), /*flags=*/0),
   426                SyscallSucceeds());
   427  
   428    std::vector<char> buf(XATTR_SIZE_MAX + 1);
   429    std::fill(buf.begin(), buf.end(), '-');
   430    std::vector<char> expected_buf = buf;
   431    expected_buf[0] = 'a';
   432    EXPECT_THAT(getxattr(path, name, buf.data(), buf.size()),
   433                SyscallSucceedsWithValue(sizeof(val)));
   434    EXPECT_EQ(buf, expected_buf);
   435  }
   436  
   437  TEST_F(XattrTest, GetXattrNullValue) {
   438    const char* path = test_file_name_.c_str();
   439    const char name[] = "user.test";
   440    char val = 'a';
   441    size_t size = sizeof(val);
   442    EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0), SyscallSucceeds());
   443  
   444    EXPECT_THAT(getxattr(path, name, nullptr, size),
   445                SyscallFailsWithErrno(EFAULT));
   446  }
   447  
   448  TEST_F(XattrTest, GetXattrNullValueAndZeroSize) {
   449    const char* path = test_file_name_.c_str();
   450    const char name[] = "user.test";
   451    char val = 'a';
   452    size_t size = sizeof(val);
   453    // Set value with zero size.
   454    EXPECT_THAT(setxattr(path, name, &val, 0, /*flags=*/0), SyscallSucceeds());
   455    // Get value with nonzero size.
   456    EXPECT_THAT(getxattr(path, name, nullptr, size), SyscallSucceedsWithValue(0));
   457  
   458    // Set value with nonzero size.
   459    EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0), SyscallSucceeds());
   460    // Get value with zero size.
   461    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallSucceedsWithValue(size));
   462  }
   463  
   464  TEST_F(XattrTest, GetXattrNonexistentName) {
   465    const char* path = test_file_name_.c_str();
   466    const char name[] = "user.test";
   467    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallFailsWithErrno(ENODATA));
   468  }
   469  
   470  TEST_F(XattrTest, ListXattr) {
   471    const char* path = test_file_name_.c_str();
   472    const std::string name = "user.test";
   473    const std::string name2 = "user.test2";
   474    const std::string name3 = "user.test3";
   475    EXPECT_THAT(setxattr(path, name.c_str(), nullptr, 0, /*flags=*/0),
   476                SyscallSucceeds());
   477    EXPECT_THAT(setxattr(path, name2.c_str(), nullptr, 0, /*flags=*/0),
   478                SyscallSucceeds());
   479    EXPECT_THAT(setxattr(path, name3.c_str(), nullptr, 0, /*flags=*/0),
   480                SyscallSucceeds());
   481  
   482    std::vector<char> list(name.size() + 1 + name2.size() + 1 + name3.size() + 1);
   483    char* buf = list.data();
   484    EXPECT_THAT(listxattr(path, buf, XATTR_SIZE_MAX),
   485                SyscallSucceedsWithValue(list.size()));
   486  
   487    absl::flat_hash_set<std::string> got = {};
   488    for (char* p = buf; p < buf + list.size(); p += strlen(p) + 1) {
   489      got.insert(std::string{p});
   490    }
   491  
   492    absl::flat_hash_set<std::string> expected = {name, name2, name3};
   493    EXPECT_EQ(got, expected);
   494  }
   495  
   496  TEST_F(XattrTest, ListXattrNoXattrs) {
   497    const char* path = test_file_name_.c_str();
   498  
   499    std::vector<char> list, expected;
   500    EXPECT_THAT(listxattr(path, list.data(), sizeof(list)),
   501                SyscallSucceedsWithValue(0));
   502    EXPECT_EQ(list, expected);
   503  
   504    // ListXattr should succeed if there are no attributes, even if the buffer
   505    // passed in is a nullptr.
   506    EXPECT_THAT(listxattr(path, nullptr, sizeof(list)),
   507                SyscallSucceedsWithValue(0));
   508  }
   509  
   510  TEST_F(XattrTest, ListXattrNullBuffer) {
   511    const char* path = test_file_name_.c_str();
   512    const char name[] = "user.test";
   513    EXPECT_THAT(setxattr(path, name, nullptr, 0, /*flags=*/0), SyscallSucceeds());
   514  
   515    EXPECT_THAT(listxattr(path, nullptr, sizeof(name)),
   516                SyscallFailsWithErrno(EFAULT));
   517  }
   518  
   519  TEST_F(XattrTest, ListXattrSizeTooSmall) {
   520    const char* path = test_file_name_.c_str();
   521    const char name[] = "user.test";
   522    EXPECT_THAT(setxattr(path, name, nullptr, 0, /*flags=*/0), SyscallSucceeds());
   523  
   524    char list[sizeof(name) - 1];
   525    EXPECT_THAT(listxattr(path, list, sizeof(list)),
   526                SyscallFailsWithErrno(ERANGE));
   527  }
   528  
   529  TEST_F(XattrTest, ListXattrZeroSize) {
   530    const char* path = test_file_name_.c_str();
   531    const char name[] = "user.test";
   532    EXPECT_THAT(setxattr(path, name, nullptr, 0, /*flags=*/0), SyscallSucceeds());
   533    EXPECT_THAT(listxattr(path, nullptr, 0),
   534                SyscallSucceedsWithValue(sizeof(name)));
   535  }
   536  
   537  TEST_F(XattrTest, RemoveXattr) {
   538    const char* path = test_file_name_.c_str();
   539    const char name[] = "user.test";
   540    EXPECT_THAT(setxattr(path, name, nullptr, 0, /*flags=*/0), SyscallSucceeds());
   541    EXPECT_THAT(removexattr(path, name), SyscallSucceeds());
   542    EXPECT_THAT(getxattr(path, name, nullptr, 0), SyscallFailsWithErrno(ENODATA));
   543  }
   544  
   545  TEST_F(XattrTest, RemoveXattrNonexistentName) {
   546    const char* path = test_file_name_.c_str();
   547    const char name[] = "user.test";
   548    EXPECT_THAT(removexattr(path, name), SyscallFailsWithErrno(ENODATA));
   549  }
   550  
   551  TEST_F(XattrTest, LXattrOnSymlink) {
   552    const char name[] = "user.test";
   553    TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   554    TempPath link = ASSERT_NO_ERRNO_AND_VALUE(
   555        TempPath::CreateSymlinkTo(dir.path(), test_file_name_));
   556  
   557    EXPECT_THAT(lsetxattr(link.path().c_str(), name, nullptr, 0, 0),
   558                SyscallFailsWithErrno(EPERM));
   559    EXPECT_THAT(lgetxattr(link.path().c_str(), name, nullptr, 0),
   560                SyscallFailsWithErrno(ENODATA));
   561    EXPECT_THAT(llistxattr(link.path().c_str(), nullptr, 0),
   562                SyscallSucceedsWithValue(0));
   563    EXPECT_THAT(lremovexattr(link.path().c_str(), name),
   564                SyscallFailsWithErrno(EPERM));
   565  }
   566  
   567  TEST_F(XattrTest, LXattrOnNonsymlink) {
   568    const char* path = test_file_name_.c_str();
   569    const char name[] = "user.test";
   570    int val = 1234;
   571    size_t size = sizeof(val);
   572    EXPECT_THAT(lsetxattr(path, name, &val, size, /*flags=*/0),
   573                SyscallSucceeds());
   574  
   575    int buf = 0;
   576    EXPECT_THAT(lgetxattr(path, name, &buf, size),
   577                SyscallSucceedsWithValue(size));
   578    EXPECT_EQ(buf, val);
   579  
   580    char list[sizeof(name)];
   581    EXPECT_THAT(llistxattr(path, list, sizeof(list)),
   582                SyscallSucceedsWithValue(sizeof(name)));
   583    EXPECT_STREQ(list, name);
   584  
   585    EXPECT_THAT(lremovexattr(path, name), SyscallSucceeds());
   586  }
   587  
   588  TEST_F(XattrTest, XattrWithFD) {
   589    const FileDescriptor fd =
   590        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_.c_str(), 0));
   591    const char name[] = "user.test";
   592    int val = 1234;
   593    size_t size = sizeof(val);
   594    EXPECT_THAT(fsetxattr(fd.get(), name, &val, size, /*flags=*/0),
   595                SyscallSucceeds());
   596  
   597    int buf = 0;
   598    EXPECT_THAT(fgetxattr(fd.get(), name, &buf, size),
   599                SyscallSucceedsWithValue(size));
   600    EXPECT_EQ(buf, val);
   601  
   602    char list[sizeof(name)];
   603    EXPECT_THAT(flistxattr(fd.get(), list, sizeof(list)),
   604                SyscallSucceedsWithValue(sizeof(name)));
   605    EXPECT_STREQ(list, name);
   606  
   607    EXPECT_THAT(fremovexattr(fd.get(), name), SyscallSucceeds());
   608  }
   609  
   610  TEST_F(XattrTest, XattrWithOPath) {
   611    SKIP_IF(IsRunningWithVFS1());
   612    const FileDescriptor fd =
   613        ASSERT_NO_ERRNO_AND_VALUE(Open(test_file_name_.c_str(), O_PATH));
   614    const char name[] = "user.test";
   615    int val = 1234;
   616    size_t size = sizeof(val);
   617    EXPECT_THAT(fsetxattr(fd.get(), name, &val, size, /*flags=*/0),
   618                SyscallFailsWithErrno(EBADF));
   619  
   620    int buf;
   621    EXPECT_THAT(fgetxattr(fd.get(), name, &buf, size),
   622                SyscallFailsWithErrno(EBADF));
   623  
   624    char list[sizeof(name)];
   625    EXPECT_THAT(flistxattr(fd.get(), list, sizeof(list)),
   626                SyscallFailsWithErrno(EBADF));
   627  
   628    EXPECT_THAT(fremovexattr(fd.get(), name), SyscallFailsWithErrno(EBADF));
   629  }
   630  
   631  TEST_F(XattrTest, TrustedNamespaceWithCapSysAdmin) {
   632    // Trusted namespace not supported in VFS1.
   633    SKIP_IF(IsRunningWithVFS1());
   634  
   635    // TODO(b/166162845): Only gVisor tmpfs currently supports trusted namespace.
   636    SKIP_IF(IsRunningOnGvisor() &&
   637            !ASSERT_NO_ERRNO_AND_VALUE(IsTmpfs(test_file_name_)));
   638  
   639    const char* path = test_file_name_.c_str();
   640    const char name[] = "trusted.test";
   641  
   642    // Writing to the trusted.* xattr namespace requires CAP_SYS_ADMIN in the root
   643    // user namespace. There's no easy way to check that, other than trying the
   644    // operation and seeing what happens. We'll call removexattr because it's
   645    // simplest.
   646    if (removexattr(path, name) < 0) {
   647      SKIP_IF(errno == EPERM);
   648      FAIL() << "unexpected errno from removexattr: " << errno;
   649    }
   650  
   651    // Set.
   652    char val = 'a';
   653    size_t size = sizeof(val);
   654    EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0), SyscallSucceeds());
   655  
   656    // Get.
   657    char got = '\0';
   658    EXPECT_THAT(getxattr(path, name, &got, size), SyscallSucceedsWithValue(size));
   659    EXPECT_EQ(val, got);
   660  
   661    // List.
   662    char list[sizeof(name)];
   663    EXPECT_THAT(listxattr(path, list, sizeof(list)),
   664                SyscallSucceedsWithValue(sizeof(name)));
   665    EXPECT_STREQ(list, name);
   666  
   667    // Remove.
   668    EXPECT_THAT(removexattr(path, name), SyscallSucceeds());
   669  
   670    // Get should now return ENODATA.
   671    EXPECT_THAT(getxattr(path, name, &got, size), SyscallFailsWithErrno(ENODATA));
   672  }
   673  
   674  TEST_F(XattrTest, TrustedNamespaceWithoutCapSysAdmin) {
   675    // Trusted namespace not supported in VFS1.
   676    SKIP_IF(IsRunningWithVFS1());
   677  
   678    // TODO(b/66162845): Only gVisor tmpfs currently supports trusted namespace.
   679    SKIP_IF(IsRunningOnGvisor() &&
   680            !ASSERT_NO_ERRNO_AND_VALUE(IsTmpfs(test_file_name_)));
   681  
   682    // Drop CAP_SYS_ADMIN if we have it.
   683    AutoCapability cap(CAP_SYS_ADMIN, false);
   684  
   685    const char* path = test_file_name_.c_str();
   686    const char name[] = "trusted.test";
   687  
   688    // Set fails.
   689    char val = 'a';
   690    size_t size = sizeof(val);
   691    EXPECT_THAT(setxattr(path, name, &val, size, /*flags=*/0),
   692                SyscallFailsWithErrno(EPERM));
   693  
   694    // Get fails.
   695    char got = '\0';
   696    EXPECT_THAT(getxattr(path, name, &got, size), SyscallFailsWithErrno(ENODATA));
   697  
   698    // List still works, but returns no items.
   699    char list[sizeof(name)];
   700    EXPECT_THAT(listxattr(path, list, sizeof(list)), SyscallSucceedsWithValue(0));
   701  
   702    // Remove fails.
   703    EXPECT_THAT(removexattr(path, name), SyscallFailsWithErrno(EPERM));
   704  }
   705  
   706  }  // namespace
   707  
   708  }  // namespace testing
   709  }  // namespace gvisor