Add verity ioctl test for mount with root hash
PiperOrigin-RevId: 368779532
This commit is contained in:
parent
14b7d775c9
commit
c980fe573d
|
@ -12,8 +12,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "test/util/capability_util.h"
|
||||
|
@ -49,8 +53,9 @@ struct fsverity_digest {
|
|||
__u8 digest[];
|
||||
};
|
||||
|
||||
const int fsverity_max_digest_size = 64;
|
||||
const int fsverity_default_digest_size = 32;
|
||||
constexpr int kMaxDigestSize = 64;
|
||||
constexpr int kDefaultDigestSize = 32;
|
||||
constexpr char kContents[] = "foobarbaz";
|
||||
|
||||
class IoctlTest : public ::testing::Test {
|
||||
protected:
|
||||
|
@ -65,7 +70,6 @@ class IoctlTest : public ::testing::Test {
|
|||
SyscallSucceeds());
|
||||
|
||||
// Create a new file in the tmpfs mount.
|
||||
constexpr char kContents[] = "foobarbaz";
|
||||
file_ = ASSERT_NO_ERRNO_AND_VALUE(
|
||||
TempPath::CreateFileWith(tmpfs_dir_.path(), kContents, 0777));
|
||||
filename_ = Basename(file_.path());
|
||||
|
@ -76,17 +80,26 @@ class IoctlTest : public ::testing::Test {
|
|||
std::string filename_;
|
||||
};
|
||||
|
||||
// Provide a function to convert bytes to hex string, since
|
||||
// absl::BytesToHexString does not seem to be compatible with golang
|
||||
// hex.DecodeString used in verity due to zero-padding.
|
||||
std::string BytesToHexString(uint8_t bytes[], int size) {
|
||||
std::stringstream ss;
|
||||
ss << std::hex;
|
||||
for (int i = 0; i < size; ++i) {
|
||||
ss << std::setw(2) << std::setfill('0') << static_cast<int>(bytes[i]);
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
TEST_F(IoctlTest, Enable) {
|
||||
// mount a verity fs on the existing tmpfs mount.
|
||||
// Mount a verity fs on the existing tmpfs mount.
|
||||
std::string mount_opts = "lower_path=" + tmpfs_dir_.path();
|
||||
auto const verity_dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
|
||||
ASSERT_THAT(
|
||||
mount("", verity_dir.path().c_str(), "verity", 0, mount_opts.c_str()),
|
||||
SyscallSucceeds());
|
||||
|
||||
printf("verity path: %s, filename: %s\n", verity_dir.path().c_str(),
|
||||
filename_.c_str());
|
||||
fflush(nullptr);
|
||||
// Confirm that the verity flag is absent.
|
||||
int flag = 0;
|
||||
auto const fd = ASSERT_NO_ERRNO_AND_VALUE(
|
||||
|
@ -101,7 +114,7 @@ TEST_F(IoctlTest, Enable) {
|
|||
}
|
||||
|
||||
TEST_F(IoctlTest, Measure) {
|
||||
// mount a verity fs on the existing tmpfs mount.
|
||||
// Mount a verity fs on the existing tmpfs mount.
|
||||
std::string mount_opts = "lower_path=" + tmpfs_dir_.path();
|
||||
auto const verity_dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
|
||||
ASSERT_THAT(
|
||||
|
@ -111,11 +124,10 @@ TEST_F(IoctlTest, Measure) {
|
|||
// Confirm that the file cannot be measured.
|
||||
auto const fd = ASSERT_NO_ERRNO_AND_VALUE(
|
||||
Open(JoinPath(verity_dir.path(), filename_), O_RDONLY, 0777));
|
||||
int digest_size = sizeof(struct fsverity_digest) + fsverity_max_digest_size;
|
||||
struct fsverity_digest *digest =
|
||||
reinterpret_cast<struct fsverity_digest *>(malloc(digest_size));
|
||||
memset(digest, 0, digest_size);
|
||||
digest->digest_size = fsverity_max_digest_size;
|
||||
uint8_t digest_array[sizeof(struct fsverity_digest) + kMaxDigestSize] = {0};
|
||||
struct fsverity_digest* digest =
|
||||
reinterpret_cast<struct fsverity_digest*>(digest_array);
|
||||
digest->digest_size = kMaxDigestSize;
|
||||
ASSERT_THAT(ioctl(fd.get(), FS_IOC_MEASURE_VERITY, digest),
|
||||
SyscallFailsWithErrno(ENODATA));
|
||||
|
||||
|
@ -123,8 +135,51 @@ TEST_F(IoctlTest, Measure) {
|
|||
ASSERT_THAT(ioctl(fd.get(), FS_IOC_ENABLE_VERITY), SyscallSucceeds());
|
||||
ASSERT_THAT(ioctl(fd.get(), FS_IOC_MEASURE_VERITY, digest),
|
||||
SyscallSucceeds());
|
||||
EXPECT_EQ(digest->digest_size, fsverity_default_digest_size);
|
||||
free(digest);
|
||||
EXPECT_EQ(digest->digest_size, kDefaultDigestSize);
|
||||
}
|
||||
|
||||
TEST_F(IoctlTest, Mount) {
|
||||
// Mount a verity fs on the existing tmpfs mount.
|
||||
std::string mount_opts = "lower_path=" + tmpfs_dir_.path();
|
||||
auto verity_dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
|
||||
ASSERT_THAT(
|
||||
mount("", verity_dir.path().c_str(), "verity", 0, mount_opts.c_str()),
|
||||
SyscallSucceeds());
|
||||
|
||||
// Enable both the file and the directory.
|
||||
auto const fd = ASSERT_NO_ERRNO_AND_VALUE(
|
||||
Open(JoinPath(verity_dir.path(), filename_), O_RDONLY, 0777));
|
||||
ASSERT_THAT(ioctl(fd.get(), FS_IOC_ENABLE_VERITY), SyscallSucceeds());
|
||||
auto const dir_fd =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(Open(verity_dir.path(), O_RDONLY, 0777));
|
||||
ASSERT_THAT(ioctl(dir_fd.get(), FS_IOC_ENABLE_VERITY), SyscallSucceeds());
|
||||
|
||||
// Measure the root hash.
|
||||
uint8_t digest_array[sizeof(struct fsverity_digest) + kMaxDigestSize] = {0};
|
||||
struct fsverity_digest* digest =
|
||||
reinterpret_cast<struct fsverity_digest*>(digest_array);
|
||||
digest->digest_size = kMaxDigestSize;
|
||||
ASSERT_THAT(ioctl(dir_fd.get(), FS_IOC_MEASURE_VERITY, digest),
|
||||
SyscallSucceeds());
|
||||
|
||||
// Mount a verity fs with specified root hash.
|
||||
mount_opts +=
|
||||
",root_hash=" + BytesToHexString(digest->digest, digest->digest_size);
|
||||
auto verity_with_hash_dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
|
||||
ASSERT_THAT(mount("", verity_with_hash_dir.path().c_str(), "verity", 0,
|
||||
mount_opts.c_str()),
|
||||
SyscallSucceeds());
|
||||
|
||||
// Make sure the file can be open and read in the mounted verity fs.
|
||||
auto const verity_fd = ASSERT_NO_ERRNO_AND_VALUE(
|
||||
Open(JoinPath(verity_with_hash_dir.path(), filename_), O_RDONLY, 0777));
|
||||
char buf[16];
|
||||
EXPECT_THAT(ReadFd(fd.get(), buf, sizeof(kContents)), SyscallSucceeds());
|
||||
|
||||
// Verity directories should not be deleted. Release the TempPath objects to
|
||||
// prevent those directories from being deleted by the destructor.
|
||||
verity_dir.release();
|
||||
verity_with_hash_dir.release();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in New Issue