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