Commit 07c99001 authored by Eric Biggers's avatar Eric Biggers

fs-verity: support reading signature with ioctl

Add support for FS_VERITY_METADATA_TYPE_SIGNATURE to
FS_IOC_READ_VERITY_METADATA.  This allows a userspace server program to
retrieve the built-in signature (if present) of a verity file for
serving to a client which implements fs-verity compatible verification.
See the patch which introduced FS_IOC_READ_VERITY_METADATA for more
details.

The ability for userspace to read the built-in signatures is also useful
because it allows a system that is using the in-kernel signature
verification to migrate to userspace signature verification.

This has been tested using a new xfstest which calls this ioctl via a
new subcommand for the 'fsverity' program from fsverity-utils.

Link: https://lore.kernel.org/r/20210115181819.34732-7-ebiggers@kernel.orgReviewed-by: default avatarVictor Hsieh <victorhsieh@google.com>
Reviewed-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
parent 947191ac
...@@ -236,6 +236,7 @@ This ioctl takes in a pointer to the following structure:: ...@@ -236,6 +236,7 @@ This ioctl takes in a pointer to the following structure::
#define FS_VERITY_METADATA_TYPE_MERKLE_TREE 1 #define FS_VERITY_METADATA_TYPE_MERKLE_TREE 1
#define FS_VERITY_METADATA_TYPE_DESCRIPTOR 2 #define FS_VERITY_METADATA_TYPE_DESCRIPTOR 2
#define FS_VERITY_METADATA_TYPE_SIGNATURE 3
struct fsverity_read_metadata_arg { struct fsverity_read_metadata_arg {
__u64 metadata_type; __u64 metadata_type;
...@@ -256,6 +257,10 @@ This ioctl takes in a pointer to the following structure:: ...@@ -256,6 +257,10 @@ This ioctl takes in a pointer to the following structure::
- ``FS_VERITY_METADATA_TYPE_DESCRIPTOR`` reads the fs-verity - ``FS_VERITY_METADATA_TYPE_DESCRIPTOR`` reads the fs-verity
descriptor. See `fs-verity descriptor`_. descriptor. See `fs-verity descriptor`_.
- ``FS_VERITY_METADATA_TYPE_SIGNATURE`` reads the signature which was
passed to FS_IOC_ENABLE_VERITY, if any. See `Built-in signature
verification`_.
The semantics are similar to those of ``pread()``. ``offset`` The semantics are similar to those of ``pread()``. ``offset``
specifies the offset in bytes into the metadata item to read from, and specifies the offset in bytes into the metadata item to read from, and
``length`` specifies the maximum number of bytes to read from the ``length`` specifies the maximum number of bytes to read from the
...@@ -279,7 +284,9 @@ FS_IOC_READ_VERITY_METADATA can fail with the following errors: ...@@ -279,7 +284,9 @@ FS_IOC_READ_VERITY_METADATA can fail with the following errors:
- ``EINTR``: the ioctl was interrupted before any data was read - ``EINTR``: the ioctl was interrupted before any data was read
- ``EINVAL``: reserved fields were set, or ``offset + length`` - ``EINVAL``: reserved fields were set, or ``offset + length``
overflowed overflowed
- ``ENODATA``: the file is not a verity file - ``ENODATA``: the file is not a verity file, or
FS_VERITY_METADATA_TYPE_SIGNATURE was requested but the file doesn't
have a built-in signature
- ``ENOTTY``: this type of filesystem does not implement fs-verity, or - ``ENOTTY``: this type of filesystem does not implement fs-verity, or
this ioctl is not yet implemented on it this ioctl is not yet implemented on it
- ``EOPNOTSUPP``: the kernel was not configured with fs-verity - ``EOPNOTSUPP``: the kernel was not configured with fs-verity
......
...@@ -114,6 +114,34 @@ static int fsverity_read_descriptor(struct inode *inode, ...@@ -114,6 +114,34 @@ static int fsverity_read_descriptor(struct inode *inode,
kfree(desc); kfree(desc);
return res; return res;
} }
static int fsverity_read_signature(struct inode *inode,
void __user *buf, u64 offset, int length)
{
struct fsverity_descriptor *desc;
size_t desc_size;
int res;
res = fsverity_get_descriptor(inode, &desc, &desc_size);
if (res)
return res;
if (desc->sig_size == 0) {
res = -ENODATA;
goto out;
}
/*
* Include only the signature. Note that fsverity_get_descriptor()
* already verified that sig_size is in-bounds.
*/
res = fsverity_read_buffer(buf, offset, length, desc->signature,
le32_to_cpu(desc->sig_size));
out:
kfree(desc);
return res;
}
/** /**
* fsverity_ioctl_read_metadata() - read verity metadata from a file * fsverity_ioctl_read_metadata() - read verity metadata from a file
* @filp: file to read the metadata from * @filp: file to read the metadata from
...@@ -158,6 +186,8 @@ int fsverity_ioctl_read_metadata(struct file *filp, const void __user *uarg) ...@@ -158,6 +186,8 @@ int fsverity_ioctl_read_metadata(struct file *filp, const void __user *uarg)
length); length);
case FS_VERITY_METADATA_TYPE_DESCRIPTOR: case FS_VERITY_METADATA_TYPE_DESCRIPTOR:
return fsverity_read_descriptor(inode, buf, arg.offset, length); return fsverity_read_descriptor(inode, buf, arg.offset, length);
case FS_VERITY_METADATA_TYPE_SIGNATURE:
return fsverity_read_signature(inode, buf, arg.offset, length);
default: default:
return -EINVAL; return -EINVAL;
} }
......
...@@ -85,6 +85,7 @@ struct fsverity_formatted_digest { ...@@ -85,6 +85,7 @@ struct fsverity_formatted_digest {
#define FS_VERITY_METADATA_TYPE_MERKLE_TREE 1 #define FS_VERITY_METADATA_TYPE_MERKLE_TREE 1
#define FS_VERITY_METADATA_TYPE_DESCRIPTOR 2 #define FS_VERITY_METADATA_TYPE_DESCRIPTOR 2
#define FS_VERITY_METADATA_TYPE_SIGNATURE 3
struct fsverity_read_metadata_arg { struct fsverity_read_metadata_arg {
__u64 metadata_type; __u64 metadata_type;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment