gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/keys.cc (about) 1 // Copyright 2018 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 <asm-generic/errno.h> 16 #include <linux/keyctl.h> 17 #include <signal.h> 18 #include <sys/socket.h> 19 #include <sys/time.h> 20 #include <sys/types.h> 21 #include <time.h> 22 23 #include <cerrno> 24 #include <cstdint> 25 #include <iostream> 26 #include <limits> 27 #include <string> 28 29 #include "gmock/gmock.h" 30 #include "gtest/gtest.h" 31 #include "absl/random/random.h" 32 #include "absl/strings/match.h" 33 #include "absl/strings/numbers.h" 34 #include "absl/strings/str_format.h" 35 #include "absl/strings/str_split.h" 36 #include "absl/strings/string_view.h" 37 #include "absl/synchronization/mutex.h" 38 #include "test/util/posix_error.h" 39 #include "test/util/thread_util.h" 40 41 #define KEY_POS_VIEW 0x01000000 42 #define KEY_POS_READ 0x02000000 43 #define KEY_POS_WRITE 0x04000000 44 #define KEY_POS_SEARCH 0x08000000 45 #define KEY_POS_LINK 0x10000000 46 #define KEY_POS_SETATTR 0x20000000 47 48 #define KEY_USR_VIEW 0x00010000 49 #define KEY_USR_READ 0x00020000 50 #define KEY_USR_WRITE 0x00040000 51 #define KEY_USR_SEARCH 0x00080000 52 #define KEY_USR_LINK 0x00100000 53 #define KEY_USR_SETATTR 0x00200000 54 55 #define KEY_GRP_VIEW 0x00000100 56 #define KEY_GRP_READ 0x00000200 57 #define KEY_GRP_WRITE 0x00000400 58 #define KEY_GRP_SEARCH 0x00000800 59 #define KEY_GRP_LINK 0x00001000 60 #define KEY_GRP_SETATTR 0x00002000 61 62 #define KEY_OTH_VIEW 0x00000001 63 #define KEY_OTH_READ 0x00000002 64 #define KEY_OTH_WRITE 0x00000004 65 #define KEY_OTH_SEARCH 0x00000008 66 #define KEY_OTH_LINK 0x00000010 67 #define KEY_OTH_SETATTR 0x00000020 68 69 namespace gvisor { 70 namespace testing { 71 namespace { 72 73 // keyctl is a cosmetic wrapper for the keyctl(2) system call. 74 static inline PosixErrorOr<int64_t> keyctl(int operation, uint64_t arg2, 75 uint64_t arg3, uint64_t arg4, 76 uint64_t arg5) { 77 int64_t ret = syscall(__NR_keyctl, operation, arg2, arg3, arg4, arg5); 78 if (ret == -1) { 79 return PosixError( 80 errno, absl::StrFormat("keyctl(%d, %d, %d, %d, %d) failed", operation, 81 arg2, arg3, arg4, arg5)); 82 } 83 return ret; 84 } 85 86 static inline PosixErrorOr<int64_t> keyctl(int operation) { 87 return keyctl(operation, 0, 0, 0, 0); 88 } 89 90 static inline PosixErrorOr<int64_t> keyctl(int operation, uint64_t arg2) { 91 return keyctl(operation, arg2, 0, 0, 0); 92 } 93 94 static inline PosixErrorOr<int64_t> keyctl(int operation, uint64_t arg2, 95 uint64_t arg3) { 96 return keyctl(operation, arg2, arg3, 0, 0); 97 } 98 99 // DescribedKey is the description of a key. 100 struct DescribedKey { 101 int64_t key_id; 102 std::string full_desc; 103 std::string type; 104 uint64_t uid; 105 uint64_t gid; 106 uint64_t perm; 107 std::string description; 108 }; 109 110 std::string DescribedKeyString(const DescribedKey& described_key) { 111 std::string process_perms = "??????"; 112 uint64_t perms = described_key.perm; 113 process_perms[0] = (perms & KEY_POS_VIEW) == 0 ? '-' : 'v'; // view 114 process_perms[1] = (perms & KEY_POS_READ) == 0 ? '-' : 'r'; // read 115 process_perms[2] = (perms & KEY_POS_WRITE) == 0 ? '-' : 'w'; // write 116 process_perms[3] = (perms & KEY_POS_SEARCH) == 0 ? '-' : 's'; // search 117 process_perms[4] = (perms & KEY_POS_LINK) == 0 ? '-' : 'l'; // link 118 process_perms[5] = (perms & KEY_POS_SETATTR) == 0 ? '-' : 'a'; // setattr 119 std::string user_perms = "??????"; 120 user_perms[0] = (perms & KEY_USR_VIEW) == 0 ? '-' : 'v'; // view 121 user_perms[1] = (perms & KEY_USR_READ) == 0 ? '-' : 'r'; // read 122 user_perms[2] = (perms & KEY_USR_WRITE) == 0 ? '-' : 'w'; // write 123 user_perms[3] = (perms & KEY_USR_SEARCH) == 0 ? '-' : 's'; // search 124 user_perms[4] = (perms & KEY_USR_LINK) == 0 ? '-' : 'l'; // link 125 user_perms[5] = (perms & KEY_USR_SETATTR) == 0 ? '-' : 'a'; // setattr 126 std::string group_perms = "??????"; 127 group_perms[0] = (perms & KEY_GRP_VIEW) == 0 ? '-' : 'v'; // view 128 group_perms[1] = (perms & KEY_GRP_READ) == 0 ? '-' : 'r'; // read 129 group_perms[2] = (perms & KEY_GRP_WRITE) == 0 ? '-' : 'w'; // write 130 group_perms[3] = (perms & KEY_GRP_SEARCH) == 0 ? '-' : 's'; // search 131 group_perms[4] = (perms & KEY_GRP_LINK) == 0 ? '-' : 'l'; // link 132 group_perms[5] = (perms & KEY_GRP_SETATTR) == 0 ? '-' : 'a'; // setattr 133 std::string other_perms = "??????"; 134 other_perms[0] = (perms & KEY_OTH_VIEW) == 0 ? '-' : 'v'; // view 135 other_perms[1] = (perms & KEY_OTH_READ) == 0 ? '-' : 'r'; // read 136 other_perms[2] = (perms & KEY_OTH_WRITE) == 0 ? '-' : 'w'; // write 137 other_perms[3] = (perms & KEY_OTH_SEARCH) == 0 ? '-' : 's'; // search 138 other_perms[4] = (perms & KEY_OTH_LINK) == 0 ? '-' : 'l'; // link 139 other_perms[5] = (perms & KEY_OTH_SETATTR) == 0 ? '-' : 'a'; // setattr 140 141 return absl::StrFormat( 142 "id=%d type=%s uid=%d gid=%d perms=0x%x " 143 "[process=%s,user=%s,group=%s,other=%s] desc=%s", 144 described_key.key_id, described_key.type, described_key.uid, 145 described_key.gid, described_key.perm, process_perms, user_perms, 146 group_perms, other_perms, described_key.description); 147 } 148 149 bool operator==(const DescribedKey& lhs, const DescribedKey& rhs) { 150 if (lhs.key_id != rhs.key_id) { 151 return false; 152 } 153 if (lhs.type != rhs.type) { 154 return false; 155 } 156 if (lhs.uid != rhs.uid) { 157 return false; 158 } 159 if (lhs.gid != rhs.gid) { 160 return false; 161 } 162 if (lhs.perm != rhs.perm) { 163 return false; 164 } 165 if (lhs.description != rhs.description) { 166 return false; 167 } 168 return true; 169 } 170 171 bool operator!=(const DescribedKey& lhs, const DescribedKey& rhs) { 172 return !(lhs == rhs); 173 } 174 175 PosixErrorOr<DescribedKey> DescribeKey(int64_t key_id) { 176 ASSIGN_OR_RETURN_ERRNO(int64_t resolved_id, 177 keyctl(KEYCTL_GET_KEYRING_ID, key_id)); 178 if (resolved_id <= 0) { 179 if (key_id == KEY_SPEC_SESSION_KEYRING) { 180 return PosixError( 181 -1, absl::StrFormat("Could not resolve session keyring (errno=%d)", 182 errno)); 183 } 184 return PosixError( 185 -1, absl::StrFormat("Could not resolve key id %d (errno=%d)", key_id, 186 errno)); 187 } 188 DescribedKey described_key; 189 described_key.key_id = resolved_id; 190 char described_key_buf[1024]; 191 ASSIGN_OR_RETURN_ERRNO( 192 int64_t buf_bytes, 193 keyctl(KEYCTL_DESCRIBE, key_id, (uint64_t)(described_key_buf), 1024, 0)); 194 if (buf_bytes <= 0) { 195 if (key_id == KEY_SPEC_SESSION_KEYRING) { 196 return PosixError(-1, "Could not describe session keyring"); 197 } 198 return PosixError(-1, absl::StrFormat("Could not describe key %d", key_id)); 199 } 200 // Remove one byte from the key size because the returned length 201 // includes the \0 at the end of the buffer. 202 described_key.full_desc = std::string(described_key_buf, buf_bytes - 1); 203 int i = 0; 204 for (absl::string_view element : 205 absl::StrSplit(described_key.full_desc, ';')) { 206 switch (i) { 207 case 0: 208 described_key.type = element; 209 break; 210 case 1: 211 if (!absl::SimpleAtoi(element, &described_key.uid)) { 212 return PosixError(-1, absl::StrFormat("Could not parse uid from: %s", 213 described_key.full_desc)); 214 } 215 break; 216 case 2: 217 if (!absl::SimpleAtoi(element, &described_key.gid)) { 218 return PosixError(-1, absl::StrFormat("Could not parse gid from: %s", 219 described_key.full_desc)); 220 } 221 break; 222 case 3: 223 described_key.perm = std::stoull(std::string(element), nullptr, 16); 224 break; 225 case 4: 226 described_key.description = std::string(element); 227 break; 228 default: 229 return PosixError( 230 -1, 231 absl::StrFormat( 232 "Key string had more than the expected number of elements: %s", 233 described_key.full_desc)); 234 } 235 i++; 236 } 237 return described_key; 238 } 239 240 TEST(KeysTest, GetCurrentSessionKeyring) { 241 DescribedKey key = 242 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 243 std::cerr << "Session key: " << DescribedKeyString(key) << std::endl; 244 EXPECT_TRUE(absl::StartsWith(key.description, "_ses")) 245 << "Unexpected name for session keyring"; 246 } 247 248 TEST(KeysTest, GetCurrentSessionKeyringViaID) { 249 DescribedKey key_via_special_id = 250 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 251 std::cerr << "Session key (retrieved via KEY_SPEC_SESSION_KEYRING): " 252 << DescribedKeyString(key_via_special_id) << std::endl; 253 DescribedKey key_via_actual_id = 254 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(key_via_special_id.key_id)); 255 std::cerr << "Session key (retrieved via explicit ID " 256 << key_via_special_id.key_id 257 << "): " << DescribedKeyString(key_via_special_id) << std::endl; 258 EXPECT_EQ(key_via_special_id, key_via_actual_id); 259 } 260 261 TEST(KeysTest, GetKeyringThatDoesNotExist) { 262 // We don't know which keyring IDs do exist, so we just iterate until we find 263 // one that doesn't exist. Surely we'll find one eventually. 264 char described_key_buf[1024]; 265 uint32_t key_id; 266 bool found_non_existent_key = false; 267 for (int i = 0; i < 100; ++i) { 268 key_id = absl::Uniform<uint32_t>(absl::InsecureBitGen(), 0, 269 std::numeric_limits<uint32_t>::max()); 270 PosixErrorOr<int64_t> buf_bytes = 271 keyctl(KEYCTL_DESCRIBE, key_id, (uint64_t)(described_key_buf), 1024, 0); 272 if (!buf_bytes.ok() && errno == ENOKEY) { 273 found_non_existent_key = true; 274 break; 275 } 276 } 277 EXPECT_TRUE(found_non_existent_key) << "Did not find any non-existent key ID"; 278 } 279 280 TEST(KeysTest, DescribeKeyWithNullBuffer) { 281 DescribedKey session_key = 282 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 283 int64_t desc_length = ASSERT_NO_ERRNO_AND_VALUE( 284 keyctl(KEYCTL_DESCRIBE, KEY_SPEC_SESSION_KEYRING, 0)); 285 EXPECT_EQ(desc_length, session_key.full_desc.length() + 1); 286 } 287 288 TEST(KeysTest, DescribeKeyWithTooSmallBuffer) { 289 DescribedKey session_key = 290 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 291 char described_key_buf[4]; 292 ASSERT_LT(4, session_key.full_desc.length()); 293 int64_t desc_length = ASSERT_NO_ERRNO_AND_VALUE( 294 keyctl(KEYCTL_DESCRIBE, KEY_SPEC_SESSION_KEYRING, 295 (uint64_t)(described_key_buf), 0, 0)); 296 EXPECT_EQ(desc_length, session_key.full_desc.length() + 1); 297 } 298 299 TEST(KeysTest, ChildThreadInheritsSessionKeyring) { 300 DescribedKey parent_key = 301 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 302 std::cerr << "Parent session keyring before spawning child thread: " 303 << DescribedKeyString(parent_key) << std::endl; 304 DescribedKey child_key; 305 ScopedThread([&] { 306 child_key = 307 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 308 std::cerr << "Child session keyring: " << DescribedKeyString(child_key) 309 << std::endl; 310 }).Join(); 311 EXPECT_EQ(parent_key, child_key) 312 << "Child session keyring did not match parent session keyring: child=" 313 << DescribedKeyString(child_key) 314 << " vs parent=" << DescribedKeyString(parent_key); 315 } 316 317 TEST(KeysTest, ChildThreadInheritsSessionKeyringCreatedAfterChildIsBorn) { 318 DescribedKey first_parent_key; 319 DescribedKey second_parent_key; 320 DescribedKey child_key; 321 ScopedThread([&] { 322 int64_t session_keyring_id = 323 ASSERT_NO_ERRNO_AND_VALUE(keyctl(KEYCTL_JOIN_SESSION_KEYRING)); 324 ASSERT_GT(session_keyring_id, 0) 325 << "Failed to join session keyring: " << errno; 326 first_parent_key = 327 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 328 std::cerr << "Parent session keyring before spawning child: " 329 << DescribedKeyString(first_parent_key) << std::endl; 330 ScopedThread([&] { 331 absl::Mutex mu; 332 bool child_ready = false; 333 bool parent_keyring_created = false; 334 ScopedThread child([&] { 335 absl::MutexLock child_ml(&mu); 336 child_ready = true; 337 std::cerr << "Child is spawned and waiting for parent." << std::endl; 338 mu.Await(absl::Condition(&parent_keyring_created)); 339 child_key = 340 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 341 std::cerr << "Child session keyring: " << DescribedKeyString(child_key) 342 << std::endl; 343 }); 344 [&] { 345 absl::MutexLock parent_ml(&mu); 346 mu.Await(absl::Condition(&child_ready)); 347 int64_t session_keyring_id = 348 ASSERT_NO_ERRNO_AND_VALUE(keyctl(KEYCTL_JOIN_SESSION_KEYRING)); 349 ASSERT_GT(session_keyring_id, 0) 350 << "Failed to join session keyring: " << errno; 351 second_parent_key = 352 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 353 std::cerr << "Parent session keyring after spawning child: " 354 << DescribedKeyString(second_parent_key) << std::endl; 355 parent_keyring_created = true; 356 }(); 357 child.Join(); 358 }).Join(); 359 }).Join(); 360 ASSERT_NE(first_parent_key, second_parent_key); 361 ASSERT_EQ(first_parent_key, child_key); 362 } 363 364 TEST(KeysTest, JoinNewNamedSessionKeyring) { 365 constexpr absl::string_view kKeyringName = "my_little_keyring"; 366 DescribedKey child_key; 367 ScopedThread([&] { 368 ASSERT_NO_ERRNO( 369 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 370 child_key = 371 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 372 std::cerr << "Child session keyring after joining new session keyring: " 373 << DescribedKeyString(child_key) << std::endl; 374 }).Join(); 375 EXPECT_EQ(child_key.description, kKeyringName); 376 } 377 378 TEST(KeysTest, ChildJoinsNewSessionKeyring) { 379 DescribedKey parent_key_before = 380 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 381 std::cerr << "Parent session keyring before spawning child thread: " 382 << DescribedKeyString(parent_key_before) << std::endl; 383 DescribedKey child_key; 384 ScopedThread([&] { 385 int64_t session_keyring_id = 386 ASSERT_NO_ERRNO_AND_VALUE(keyctl(KEYCTL_JOIN_SESSION_KEYRING)); 387 ASSERT_GT(session_keyring_id, 0) 388 << "Failed to join session keyring: " << errno; 389 child_key = 390 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 391 std::cerr << "Child session keyring after joining new session keyring: " 392 << DescribedKeyString(child_key) << std::endl; 393 ASSERT_EQ(child_key.key_id, session_keyring_id); 394 }).Join(); 395 DescribedKey parent_key_after = 396 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 397 std::cerr << "Parent session keyring after child finished: " 398 << DescribedKeyString(parent_key_after) << std::endl; 399 EXPECT_EQ(parent_key_before, parent_key_after) 400 << "Parent session keyring changed after child did its thing: " 401 << DescribedKeyString(parent_key_after) << " vs " 402 << DescribedKeyString(parent_key_before); 403 EXPECT_NE(parent_key_before, child_key) 404 << "Child session keyring did not change after joining new session " 405 "keyring: " 406 << DescribedKeyString(child_key); 407 } 408 409 TEST(KeysTest, ExistingNamedSessionKeyringIsNew) { 410 constexpr absl::string_view kKeyringName = "my_little_keyring"; 411 DescribedKey parent_key; 412 DescribedKey first_child_key; 413 DescribedKey second_child_initial_key; 414 DescribedKey second_child_existing_key; 415 ScopedThread([&] { 416 ASSERT_NO_ERRNO(keyctl(KEYCTL_JOIN_SESSION_KEYRING)); 417 parent_key = 418 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 419 absl::Mutex mu; 420 bool first_child_created_keyring = false; 421 ScopedThread first_child([&] { 422 absl::MutexLock ml(&mu); 423 ASSERT_NO_ERRNO( 424 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 425 first_child_key = 426 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 427 std::cerr << "First child's session keyring: " 428 << DescribedKeyString(first_child_key) << std::endl; 429 first_child_created_keyring = true; 430 }); 431 ScopedThread([&] { 432 absl::MutexLock ml(&mu); 433 second_child_initial_key = 434 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 435 std::cerr << "Session child's initial session keyring: " 436 << DescribedKeyString(second_child_initial_key) << std::endl; 437 mu.Await(absl::Condition(&first_child_created_keyring)); 438 ASSERT_NO_ERRNO( 439 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 440 second_child_existing_key = 441 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 442 std::cerr << "Session child's second session keyring: " 443 << DescribedKeyString(second_child_existing_key) << std::endl; 444 }).Join(); 445 first_child.Join(); 446 }).Join(); 447 EXPECT_EQ(parent_key, second_child_initial_key); 448 EXPECT_EQ(first_child_key.description, kKeyringName); 449 EXPECT_NE(parent_key, first_child_key); 450 EXPECT_NE(first_child_key, second_child_existing_key); 451 EXPECT_EQ(first_child_key.description, second_child_existing_key.description); 452 EXPECT_NE(first_child_key.key_id, second_child_existing_key.key_id); 453 } 454 455 TEST(KeysTest, SetAndRetrieveKeyPermissions) { 456 DescribedKey before_key; 457 DescribedKey after_key; 458 DescribedKey deeper_key; 459 uint64_t new_perms = 0; 460 ScopedThread([&] { 461 ASSERT_NO_ERRNO(keyctl(KEYCTL_JOIN_SESSION_KEYRING)); 462 before_key = 463 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 464 std::cerr << "Child session keyring after joining new session keyring: " 465 << DescribedKeyString(before_key) << std::endl; 466 new_perms = (before_key.perm | KEY_USR_SEARCH) & 0xffffffff; 467 ASSERT_NO_ERRNO( 468 keyctl(KEYCTL_SETPERM, KEY_SPEC_SESSION_KEYRING, new_perms)); 469 after_key = 470 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 471 std::cerr 472 << "Child session keyring after changing session keyring permissions: " 473 << DescribedKeyString(after_key) << std::endl; 474 ScopedThread([&] { 475 deeper_key = 476 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 477 std::cerr << "Second-level child session keyring: " 478 << DescribedKeyString(deeper_key) << std::endl; 479 }).Join(); 480 }).Join(); 481 EXPECT_NE(new_perms, 0) << "New permissions are empty"; 482 EXPECT_NE(before_key.perm, new_perms) 483 << "Permissions were not actually requested to change, please update " 484 "permissions mask"; 485 EXPECT_EQ(after_key.perm, new_perms) 486 << "Permissions were not updated correctly"; 487 EXPECT_EQ(after_key, deeper_key) << "Permissions were not inherited"; 488 } 489 490 TEST(KeysTest, JoinExistingNamedKeyringFromParent) { 491 constexpr absl::string_view kKeyringName = "my_little_keyring"; 492 constexpr absl::string_view kOtherKeyringName = "my_other_keyring"; 493 DescribedKey first_level_key; 494 DescribedKey second_level_key; 495 DescribedKey third_level_key; 496 ScopedThread([&] { 497 ASSERT_NO_ERRNO( 498 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 499 DescribedKey before_perms_key = 500 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 501 uint64_t perms = (before_perms_key.perm | 0x80008) & 0xffffffff; 502 ASSERT_NO_ERRNO(keyctl(KEYCTL_SETPERM, before_perms_key.key_id, perms)); 503 first_level_key = 504 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 505 std::cerr << "First-level child keyring: " 506 << DescribedKeyString(first_level_key) << std::endl; 507 ScopedThread([&] { 508 ASSERT_NO_ERRNO(keyctl(KEYCTL_JOIN_SESSION_KEYRING, 509 (uint64_t)(kOtherKeyringName.data()))); 510 second_level_key = 511 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 512 std::cerr << "Second-level child keyring: " 513 << DescribedKeyString(second_level_key) << std::endl; 514 ScopedThread([&] { 515 ASSERT_NO_ERRNO(keyctl(KEYCTL_JOIN_SESSION_KEYRING, 516 (uint64_t)(kKeyringName.data()))); 517 third_level_key = 518 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 519 std::cerr << "Third-level child keyring: " 520 << DescribedKeyString(third_level_key) << std::endl; 521 }).Join(); 522 }).Join(); 523 }).Join(); 524 // The key_id is different per process, so don't compare that. 525 // We use the permissions field to verify that the keyring is the same 526 // between the first and the third level, to show that the same keyring 527 // is being looked up. 528 // However, the second level didn't look up the same keyring, so its 529 // permissions should be different. 530 EXPECT_EQ(first_level_key.perm, third_level_key.perm); 531 EXPECT_NE(first_level_key.perm, second_level_key.perm); 532 } 533 534 TEST(KeysTest, DefaultKeyPermissions) { 535 constexpr absl::string_view kKeyringName = "named_session_keyring"; 536 DescribedKey default_named_session_key; 537 DescribedKey default_unnamed_session_key; 538 ScopedThread([&] { 539 ASSERT_NO_ERRNO( 540 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 541 default_named_session_key = 542 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 543 }).Join(); 544 ScopedThread([&] { 545 ASSERT_NO_ERRNO(keyctl(KEYCTL_JOIN_SESSION_KEYRING)); 546 default_unnamed_session_key = 547 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 548 }).Join(); 549 std::cerr << "Default named session keyring: " 550 << DescribedKeyString(default_named_session_key) << std::endl; 551 std::cerr << "Default unnamed session keyring: " 552 << DescribedKeyString(default_unnamed_session_key) << std::endl; 553 // Possessor permissions: 554 uint64_t key_pos_all = KEY_POS_VIEW | KEY_POS_READ | KEY_POS_WRITE | 555 KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; 556 EXPECT_EQ(default_unnamed_session_key.perm & key_pos_all, key_pos_all); 557 EXPECT_EQ(default_named_session_key.perm & key_pos_all, key_pos_all); 558 559 // User permissions: 560 // These differ depending on whether the keyring is named or not. 561 EXPECT_EQ(default_unnamed_session_key.perm & KEY_USR_VIEW, KEY_USR_VIEW); 562 EXPECT_EQ(default_unnamed_session_key.perm & KEY_USR_READ, KEY_USR_READ); 563 EXPECT_EQ(default_unnamed_session_key.perm & KEY_USR_WRITE, 0); 564 EXPECT_EQ(default_unnamed_session_key.perm & KEY_USR_SEARCH, 0); 565 EXPECT_EQ(default_unnamed_session_key.perm & KEY_USR_LINK, 0); 566 EXPECT_EQ(default_unnamed_session_key.perm & KEY_USR_SETATTR, 0); 567 EXPECT_EQ(default_unnamed_session_key.perm | KEY_USR_LINK, 568 default_named_session_key.perm); 569 570 // Group permissions: 571 uint64_t key_group_all = KEY_GRP_VIEW | KEY_GRP_READ | KEY_GRP_WRITE | 572 KEY_GRP_SEARCH | KEY_GRP_LINK | KEY_GRP_SETATTR; 573 EXPECT_EQ(default_unnamed_session_key.perm & key_group_all, 0); 574 EXPECT_EQ(default_named_session_key.perm & key_group_all, 0); 575 576 // Other permissions: 577 uint64_t key_other_all = KEY_OTH_VIEW | KEY_OTH_READ | KEY_OTH_WRITE | 578 KEY_OTH_SEARCH | KEY_OTH_LINK | KEY_OTH_SETATTR; 579 EXPECT_EQ(default_unnamed_session_key.perm & key_other_all, 0); 580 EXPECT_EQ(default_named_session_key.perm & key_other_all, 0); 581 } 582 583 TEST(KeysTest, EnforceKeyPermissions) { 584 ScopedThread([&] { 585 constexpr absl::string_view kKeyringName = "my_little_keyring"; 586 ASSERT_NO_ERRNO( 587 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 588 DescribedKey key = 589 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 590 ASSERT_NO_ERRNO(keyctl(KEYCTL_SETPERM, key.key_id, 0 /* No permissions */)); 591 EXPECT_THAT(keyctl(KEYCTL_DESCRIBE, KEY_SPEC_SESSION_KEYRING), 592 PosixErrorIs(EACCES)) 593 << "Session keyring can be described"; 594 EXPECT_THAT(keyctl(KEYCTL_DESCRIBE, key.key_id), PosixErrorIs(EACCES)) 595 << "Session keyring can be described by ID"; 596 ASSERT_THAT(keyctl(KEYCTL_SETPERM, key.key_id, 0), PosixErrorIs(EACCES)) 597 << "Session keyring perms can be changed after locking them down"; 598 ScopedThread([&] { 599 EXPECT_THAT(keyctl(KEYCTL_DESCRIBE, KEY_SPEC_SESSION_KEYRING), 600 PosixErrorIs(EACCES)) 601 << "Session keyring can be described in child"; 602 EXPECT_THAT(keyctl(KEYCTL_DESCRIBE, key.key_id), PosixErrorIs(EACCES)) 603 << "Session keyring can be described by ID in child"; 604 ASSERT_THAT(keyctl(KEYCTL_SETPERM, key.key_id, 0), PosixErrorIs(EACCES)) 605 << "Session keyring perms can be changed after locking them down in " 606 "parent"; 607 }).Join(); 608 }).Join(); 609 } 610 611 // JoiningNonSearchableNamedKeyring verifies what happens when joining an 612 // existing named keyring without the search permission. 613 TEST(KeysTest, JoiningNonSearchableNamedKeyring) { 614 constexpr absl::string_view kKeyringName = "my_little_keyring"; 615 DescribedKey first_key; 616 DescribedKey second_key; 617 ScopedThread([&] { 618 ASSERT_NO_ERRNO( 619 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 620 first_key = 621 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 622 std::cerr << "First child keyring: " << DescribedKeyString(first_key) 623 << std::endl; 624 uint64_t non_searchable_perms = 625 first_key.perm & 626 ~(KEY_POS_SEARCH | KEY_USR_SEARCH | KEY_GRP_SEARCH | KEY_OTH_SEARCH); 627 ASSERT_NO_ERRNO( 628 keyctl(KEYCTL_SETPERM, KEY_SPEC_SESSION_KEYRING, non_searchable_perms)); 629 ScopedThread([&] { 630 // The man page says this should fail with EACCES, but Linux actually 631 // creates a new keyring with the same name instead. 632 ASSERT_NO_ERRNO( 633 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 634 second_key = 635 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 636 std::cerr << "Second child keyring: " << DescribedKeyString(first_key) 637 << std::endl; 638 }).Join(); 639 }).Join(); 640 ASSERT_NE(first_key.key_id, second_key.key_id); 641 } 642 643 // JoiningSearchableNamedKeyring verifies what happens when joining an 644 // existing named keyring with the search permission. 645 TEST(KeysTest, JoiningSearchableNamedKeyring) { 646 constexpr absl::string_view kKeyringName = "my_little_keyring"; 647 DescribedKey searchable_key; 648 DescribedKey second_key; 649 ScopedThread([&] { 650 ASSERT_NO_ERRNO( 651 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 652 DescribedKey initial_key = 653 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 654 std::cerr << "Initial session keyring: " << DescribedKeyString(initial_key) 655 << std::endl; 656 uint64_t searchable_perms = initial_key.perm | KEY_USR_SEARCH; 657 ASSERT_NO_ERRNO( 658 keyctl(KEYCTL_SETPERM, KEY_SPEC_SESSION_KEYRING, searchable_perms)); 659 searchable_key = 660 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 661 std::cerr << "Searchable session keyring: " 662 << DescribedKeyString(searchable_key) << std::endl; 663 ScopedThread([&] { 664 ASSERT_NO_ERRNO( 665 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 666 second_key = 667 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 668 std::cerr << "Second keyring: " << DescribedKeyString(second_key) 669 << std::endl; 670 }).Join(); 671 }).Join(); 672 EXPECT_EQ(searchable_key.key_id, second_key.key_id); 673 } 674 675 TEST(KeysTest, SearchableKeyringIsSharedAcrossThreads) { 676 constexpr absl::string_view kKeyringName = "my_little_keyring"; 677 DescribedKey parent_key; 678 DescribedKey first_child_final_key; 679 DescribedKey second_child_final_key; 680 ScopedThread([&] { 681 ASSERT_NO_ERRNO(keyctl(KEYCTL_JOIN_SESSION_KEYRING)); 682 parent_key = 683 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 684 std::cerr << "Parent session keyring: " << DescribedKeyString(parent_key) 685 << std::endl; 686 absl::Mutex mu; 687 688 // We're going to do a complicated dance. 689 // Each of the following booleans is used to gate on the steps described 690 // above it. 691 692 // - Spawn two threads, have them wait on each other until they are both 693 // actually running code. 694 bool first_child_ready = false; 695 bool second_child_ready = false; 696 697 // - Have the first thread create a named keyring. 698 // - Have the first thread change this keyring to be searchable by user. 699 bool first_child_created_keyring = false; 700 701 // - Have the second thread join it by name. 702 // - Have the second thread flip a bit in its permission field: 703 // KEY_GRP_LINK 704 bool second_child_modified_keyring = false; 705 706 // - Have the first thread re-read the permissions of its keyring. 707 // - Have the first thread flip another bit in the permission field: 708 // KEY_OTH_LINK 709 bool first_child_modified_keyring = false; 710 711 // - Have the second thread re-read the permissions of its keyring. 712 // - Verify that the final keys from both threads match and have both bits 713 // flipped. 714 715 ScopedThread first_child([&] { 716 absl::MutexLock ml(&mu); 717 first_child_ready = true; 718 mu.Await(absl::Condition(&second_child_ready)); 719 ASSERT_NO_ERRNO( 720 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 721 DescribedKey initial_key = 722 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 723 std::cerr << "First child: initial session keyring: " 724 << DescribedKeyString(initial_key) << std::endl; 725 uint64_t searchable_perms = initial_key.perm | KEY_USR_SEARCH; 726 ASSERT_NO_ERRNO( 727 keyctl(KEYCTL_SETPERM, KEY_SPEC_SESSION_KEYRING, searchable_perms)); 728 DescribedKey searchable_key = 729 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 730 std::cerr << "First child: searchable session keyring: " 731 << DescribedKeyString(searchable_key) << std::endl; 732 first_child_created_keyring = true; 733 mu.Await(absl::Condition(&second_child_modified_keyring)); 734 DescribedKey modified_key = 735 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 736 std::cerr 737 << "First child: session keyring after second thread modified it: " 738 << DescribedKeyString(modified_key) << std::endl; 739 uint64_t new_perms = modified_key.perm | KEY_OTH_LINK; 740 ASSERT_NO_ERRNO( 741 keyctl(KEYCTL_SETPERM, KEY_SPEC_SESSION_KEYRING, new_perms)); 742 first_child_final_key = 743 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 744 std::cerr << "First child: final session keyring: " 745 << DescribedKeyString(first_child_final_key) << std::endl; 746 first_child_modified_keyring = true; 747 }); 748 ScopedThread second_child([&] { 749 absl::MutexLock ml(&mu); 750 second_child_ready = true; 751 mu.Await(absl::Condition(&first_child_ready)); 752 mu.Await(absl::Condition(&first_child_created_keyring)); 753 ASSERT_NO_ERRNO( 754 keyctl(KEYCTL_JOIN_SESSION_KEYRING, (uint64_t)(kKeyringName.data()))); 755 DescribedKey initial_key = 756 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 757 std::cerr << "Second child: initial session keyring: " 758 << DescribedKeyString(initial_key) << std::endl; 759 uint64_t new_perms = initial_key.perm | KEY_GRP_LINK; 760 ASSERT_NO_ERRNO( 761 keyctl(KEYCTL_SETPERM, KEY_SPEC_SESSION_KEYRING, new_perms)); 762 DescribedKey modified_key = 763 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 764 std::cerr 765 << "Second child: session keyring after modifying its permissions: " 766 << DescribedKeyString(modified_key) << std::endl; 767 second_child_modified_keyring = true; 768 mu.Await(absl::Condition(&first_child_modified_keyring)); 769 second_child_final_key = 770 ASSERT_NO_ERRNO_AND_VALUE(DescribeKey(KEY_SPEC_SESSION_KEYRING)); 771 std::cerr << "Second child: final session keyring: " 772 << DescribedKeyString(second_child_final_key) << std::endl; 773 }); 774 first_child.Join(); 775 second_child.Join(); 776 }).Join(); 777 EXPECT_NE(parent_key, first_child_final_key); 778 EXPECT_NE(parent_key, second_child_final_key); 779 EXPECT_NE(parent_key.perm, first_child_final_key.perm); 780 EXPECT_EQ(first_child_final_key.key_id, second_child_final_key.key_id); 781 for (const uint64_t bit : 782 {KEY_USR_LINK, KEY_USR_SEARCH, KEY_GRP_LINK, KEY_OTH_LINK}) { 783 EXPECT_EQ(parent_key.perm & bit, 0) << "Bit " << bit << " in parent key"; 784 EXPECT_EQ(first_child_final_key.perm & bit, bit) 785 << "Bit " << bit << " in first child key"; 786 EXPECT_EQ(second_child_final_key.perm & bit, bit) 787 << "Bit " << bit << " in second child key"; 788 } 789 EXPECT_EQ(first_child_final_key.perm, second_child_final_key.perm); 790 } 791 792 } // namespace 793 } // namespace testing 794 } // namespace gvisor