github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/util/verity_util.cc (about)

     1  // Copyright 2021 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 "test/util/verity_util.h"
    16  
    17  #include "test/util/fs_util.h"
    18  #include "test/util/mount_util.h"
    19  #include "test/util/temp_path.h"
    20  
    21  namespace gvisor {
    22  namespace testing {
    23  
    24  std::string BytesToHexString(uint8_t bytes[], int size) {
    25    std::stringstream ss;
    26    ss << std::hex;
    27    for (int i = 0; i < size; ++i) {
    28      ss << std::setw(2) << std::setfill('0') << static_cast<int>(bytes[i]);
    29    }
    30    return ss.str();
    31  }
    32  
    33  std::string MerklePath(absl::string_view path) {
    34    return JoinPath(Dirname(path),
    35                    std::string(kMerklePrefix) + std::string(Basename(path)));
    36  }
    37  
    38  std::string MerkleRootPath(absl::string_view path) {
    39    return JoinPath(Dirname(path),
    40                    std::string(kMerkleRootPrefix) + std::string(Basename(path)));
    41  }
    42  
    43  PosixError FlipRandomBit(int fd, int size) {
    44    // Generate a random offset in the file.
    45    srand(time(nullptr));
    46    unsigned int seed = 0;
    47    int random_offset = rand_r(&seed) % size;
    48  
    49    // Read a random byte and flip a bit in it.
    50    char buf[1];
    51    RETURN_ERROR_IF_SYSCALL_FAIL(PreadFd(fd, buf, 1, random_offset));
    52    buf[0] ^= 1;
    53    RETURN_ERROR_IF_SYSCALL_FAIL(PwriteFd(fd, buf, 1, random_offset));
    54    return NoError();
    55  }
    56  
    57  PosixErrorOr<std::string> MountVerity(std::string tmpfs_dir,
    58                                        std::string filename) {
    59    // Mount a verity fs on the existing tmpfs mount.
    60    std::string mount_opts = "lower_path=" + tmpfs_dir;
    61    ASSIGN_OR_RETURN_ERRNO(TempPath verity_dir, TempPath::CreateDir());
    62    RETURN_ERROR_IF_SYSCALL_FAIL(
    63        mount("", verity_dir.path().c_str(), "verity", 0, mount_opts.c_str()));
    64  
    65    // Enable both the file and the directory.
    66    ASSIGN_OR_RETURN_ERRNO(
    67        auto fd, Open(JoinPath(verity_dir.path(), filename), O_RDONLY, 0777));
    68    RETURN_ERROR_IF_SYSCALL_FAIL(ioctl(fd.get(), FS_IOC_ENABLE_VERITY));
    69    ASSIGN_OR_RETURN_ERRNO(auto dir_fd, Open(verity_dir.path(), O_RDONLY, 0777));
    70    RETURN_ERROR_IF_SYSCALL_FAIL(ioctl(dir_fd.get(), FS_IOC_ENABLE_VERITY));
    71  
    72    // Measure the root hash.
    73    uint8_t digest_array[sizeof(struct fsverity_digest) + kMaxDigestSize] = {0};
    74    struct fsverity_digest* digest =
    75        reinterpret_cast<struct fsverity_digest*>(digest_array);
    76    digest->digest_size = kMaxDigestSize;
    77    RETURN_ERROR_IF_SYSCALL_FAIL(
    78        ioctl(dir_fd.get(), FS_IOC_MEASURE_VERITY, digest));
    79  
    80    // Mount a verity fs with specified root hash.
    81    mount_opts +=
    82        ",root_hash=" + BytesToHexString(digest->digest, digest->digest_size);
    83    ASSIGN_OR_RETURN_ERRNO(TempPath verity_with_hash_dir, TempPath::CreateDir());
    84    RETURN_ERROR_IF_SYSCALL_FAIL(mount("", verity_with_hash_dir.path().c_str(),
    85                                       "verity", 0, mount_opts.c_str()));
    86    // Verity directories should not be deleted. Release the TempPath objects to
    87    // prevent those directories from being deleted by the destructor.
    88    verity_dir.release();
    89    return verity_with_hash_dir.release();
    90  }
    91  
    92  }  // namespace testing
    93  }  // namespace gvisor