Skip to content

Commit

Permalink
lib: Add lcfs_fd_measure_fsverity
Browse files Browse the repository at this point in the history
Our history with fsverity APIs is a bit messy. For now historical
reasons lcfs_fd_get_fsverity tries to query the kernel (via ioctl)
but will silently fall back to userspace computation - which
is sometimes desirable, other times not.

We also have lcfs_fd_compute_fsverity which is unconditionally
userspace.

However some cases actually really want to require the
fd to have fsverity - so add an API to do that.

Signed-off-by: Colin Walters <[email protected]>
  • Loading branch information
cgwalters committed Nov 6, 2024
1 parent 738793a commit 95b4792
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 14 deletions.
39 changes: 25 additions & 14 deletions libcomposefs/lcfs-writer.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,10 +564,9 @@ int lcfs_compute_fsverity_from_fd(uint8_t *digest, int fd)
return lcfs_compute_fsverity_from_content(digest, &_fd, fsverity_read_cb);
}

// Given a file descriptor, first query the kernel for its fsverity digest. If
// it is not available in the kernel, perform an in-memory computation. The file
// position will always be reset to zero if needed.
int lcfs_fd_get_fsverity(uint8_t *digest, int fd)
// Given a file descriptor, query the kernel for its fsverity digest. It
// is an error if fsverity is not enabled.
int lcfs_fd_measure_fsverity(uint8_t *digest, int fd)
{
char buf[sizeof(struct fsverity_digest) + MAX_DIGEST_SIZE];
struct fsverity_digest *fsv = (struct fsverity_digest *)&buf;
Expand All @@ -577,16 +576,6 @@ int lcfs_fd_get_fsverity(uint8_t *digest, int fd)
fsv->digest_size = MAX_DIGEST_SIZE;
int res = ioctl(fd, FS_IOC_MEASURE_VERITY, fsv);
if (res == -1) {
// Under this condition, the file didn't have fsverity enabled or the
// kernel doesn't support it at all. We need to compute it in the current process.
if (errno == ENODATA || errno == EOPNOTSUPP || errno == ENOTTY) {
// For consistency ensure we start from the beginning. We could
// avoid this by using pread() in the future.
if (lseek(fd, 0, SEEK_SET) < 0)
return -errno;
return lcfs_compute_fsverity_from_fd(digest, fd);
}
// In this case, we found an unexpected error
return -errno;
}
// The file has fsverity enabled, but with an unexpected different algorithm (e.g. sha512).
Expand All @@ -600,6 +589,28 @@ int lcfs_fd_get_fsverity(uint8_t *digest, int fd)
return 0;
}

// Given a file descriptor, first query the kernel for its fsverity digest. If
// it is not available in the kernel, perform an in-memory computation. The file
// position will always be reset to zero if needed.
int lcfs_fd_get_fsverity(uint8_t *digest, int fd)
{
int res = lcfs_fd_measure_fsverity(digest, fd);
if (res == 0) {
return 0;
}
// Under this condition, the file didn't have fsverity enabled or the
// kernel doesn't support it at all. We need to compute it in the current process.
if (errno == ENODATA || errno == EOPNOTSUPP || errno == ENOTTY) {
// For consistency ensure we start from the beginning. We could
// avoid this by using pread() in the future.
if (lseek(fd, 0, SEEK_SET) < 0)
return -errno;
return lcfs_compute_fsverity_from_fd(digest, fd);
}
// In this case, we found an unexpected error
return -errno;
}

int lcfs_compute_fsverity_from_data(uint8_t *digest, uint8_t *data, size_t data_len)
{
FsVerityContext *ctx;
Expand Down
1 change: 1 addition & 0 deletions libcomposefs/lcfs-writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ LCFS_EXTERN int lcfs_compute_fsverity_from_content(uint8_t *digest, void *file,
LCFS_EXTERN int lcfs_compute_fsverity_from_fd(uint8_t *digest, int fd);
LCFS_EXTERN int lcfs_compute_fsverity_from_data(uint8_t *digest, uint8_t *data,
size_t data_len);
LCFS_EXTERN int lcfs_fd_measure_fsverity(uint8_t *digest, int fd);
LCFS_EXTERN int lcfs_fd_get_fsverity(uint8_t *digest, int fd);

LCFS_EXTERN int lcfs_node_set_from_content(struct lcfs_node_s *node, int dirfd,
Expand Down
15 changes: 15 additions & 0 deletions tests/test-lcfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "lcfs-writer.h"
#include <assert.h>
#include <unistd.h>
#include <errno.h>

static inline void lcfs_node_unrefp(struct lcfs_node_s **nodep)
Expand Down Expand Up @@ -75,8 +76,22 @@ static void test_add_uninitialized_child(void)
assert(errno == EINVAL);
}

// Verifies that lcfs_fd_measure_fsverity fails on a fd without fsverity
static void test_no_verity(void)
{
char buf[] = "/tmp/test-verity.XXXXXX";
int tmpfd = mkstemp(buf);
assert(tmpfd > 0);

uint8_t digest[LCFS_DIGEST_SIZE];
int r = lcfs_fd_require_fsverity(digest, tmpfd);
assert(r != 0);
close(tmpfd);
}

int main(int argc, char **argv)
{
test_basic();
test_no_verity();
test_add_uninitialized_child();
}

0 comments on commit 95b4792

Please sign in to comment.