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