diff --git a/Documentation/filesystems/fsverity.rst b/Documentation/filesystems/fsverity.rst index 22b49b295d1f..e5d38439bf58 100644 --- a/Documentation/filesystems/fsverity.rst +++ b/Documentation/filesystems/fsverity.rst @@ -170,6 +170,7 @@ fatal signal), no changes are made to the file. FS_IOC_ENABLE_VERITY can fail with the following errors: - ``EACCES``: the process does not have write access to the file +- ``EBADF``: the file descriptor is not open for reading - ``EBADMSG``: the builtin signature is malformed - ``EBUSY``: this ioctl is already running on the file - ``EEXIST``: the file already has verity enabled @@ -232,6 +233,7 @@ regardless of the size of the file. FS_IOC_MEASURE_VERITY can fail with the following errors: +- ``EBADF``: the file descriptor is not open for reading - ``EFAULT``: the caller provided inaccessible memory - ``ENODATA``: the file is not a verity file - ``ENOTTY``: this type of filesystem does not implement fs-verity @@ -310,6 +312,7 @@ blocks from disk without actually verifying the path to the root node. FS_IOC_READ_VERITY_METADATA can fail with the following errors: +- ``EBADF``: the file descriptor is not open for reading - ``EFAULT``: the caller provided inaccessible memory - ``EINTR``: the ioctl was interrupted before any data was read - ``EINVAL``: reserved fields were set, or ``offset + length`` diff --git a/fs/verity/measure.c b/fs/verity/measure.c index 68dfccb69772..0c75616dca01 100644 --- a/fs/verity/measure.c +++ b/fs/verity/measure.c @@ -31,6 +31,16 @@ int fsverity_ioctl_measure(struct file *filp, void __user *_uarg) const struct fsverity_hash_alg *hash_alg; struct fsverity_digest arg; + /* + * This ioctl returns a hash of the file contents, so it should require + * read permission. Disallow it on ioctl-only (i.e., nonstandard access + * mode 3) fds, which can in some cases be acquired without passing all + * LSM read-permission checks. Also disallow write-only fds, which can + * refer only to non-verity files which would fail with ENODATA anyway. + */ + if (!(filp->f_mode & FMODE_READ)) + return -EBADF; + vi = fsverity_get_info(inode); if (!vi) return -ENODATA; /* not a verity file */ diff --git a/fs/verity/read_metadata.c b/fs/verity/read_metadata.c index b4c0892430cd..6694149f7b46 100644 --- a/fs/verity/read_metadata.c +++ b/fs/verity/read_metadata.c @@ -166,13 +166,19 @@ int fsverity_ioctl_read_metadata(struct file *filp, const void __user *uarg) int length; void __user *buf; + /* + * This ioctl returns file contents block hashes, so it should require + * read permission. Disallow it on ioctl-only (i.e., nonstandard access + * mode 3) fds, which can in some cases be acquired without passing all + * LSM read-permission checks. Also disallow write-only fds, which can + * refer only to non-verity files which would fail with ENODATA anyway. + */ + if (!(filp->f_mode & FMODE_READ)) + return -EBADF; + vi = fsverity_get_info(inode); if (!vi) return -ENODATA; /* not a verity file */ - /* - * Note that we don't have to explicitly check that the file is open for - * reading, since verity files can only be opened for reading. - */ if (copy_from_user(&arg, uarg, sizeof(arg))) return -EFAULT;