From: Eric Biggers <ebiggers@kernel.org>
To: fsverity@lists.linux.dev
Cc: linux-fsdevel@vger.kernel.org,
linux-security-module@vger.kernel.org,
Andrey Albershteyn <aalbersh@kernel.org>,
Eric Biggers <ebiggers@kernel.org>,
stable@vger.kernel.org
Subject: [PATCH] fsverity: Explicitly require FMODE_READ to retrieve hashes
Date: Thu, 22 Oct 2026 21:15:22 +0000 [thread overview]
Message-ID: <20261022211522.1489943-1-ebiggers@kernel.org> (raw)
The comment in fsverity_ioctl_read_metadata(), which justifies not
checking for FMODE_READ, doesn't consider that the nonstandard access
mode 3 (ioctl-only) exists.
Opening an ioctl-only fd generally requires read (and write) permission.
However, there are gaps with certain LSMs: an ioctl-only fd requests
read (and write) permission via security_inode_permission, but not
security_file_open. With certain LSMs relying on the latter, such as
Landlock and AppArmor, an ioctl-only fd can be opened without the LSM
granting read (and write) permission.
Since FS_IOC_READ_VERITY_METADATA returns hashes of file contents
blocks, it should require read permission. This also applies to
FS_IOC_MEASURE_VERITY, which returns a hash for the whole file.
Meanwhile, ioctl-only fds are a rarely-used feature, not known to be
used with either ioctl.
Therefore, just disallow these ioctls on ioctl-only file descriptors,
similar to what was already done with FS_IOC_ENABLE_VERITY.
More specifically, explicitly check for FMODE_READ. This also covers
write-only fds to non-verity files which otherwise would have failed
with ENODATA. This change in error code for write-only fds should be
fine too, as these ioctls cannot be usefully used with write-only fds
anyway, but it's worth noting as another technicality.
Fixes: 4dd893d832cf ("fs-verity: implement FS_IOC_MEASURE_VERITY ioctl")
Fixes: e17fe6579de0 ("fs-verity: add FS_IOC_READ_VERITY_METADATA ioctl")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
Documentation/filesystems/fsverity.rst | 3 +++
fs/verity/measure.c | 10 ++++++++++
fs/verity/read_metadata.c | 14 ++++++++++----
3 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/Documentation/filesystems/fsverity.rst b/Documentation/filesystems/fsverity.rst
index 22b49b295d1f9..e5d38439bf585 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 68dfccb697720..0c75616dca011 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 b4c0892430cde..6694149f7b467 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;
base-commit: 7be4bc52fd9e0e55dc9a2e0232b89427d2c4b614
--
2.56.0.307.g5fe7bd680c-goog
next reply other threads:[~2026-10-22 21:15 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-22 21:15 Eric Biggers [this message]
2026-10-22 21:18 ` [PATCH] fsverity: Explicitly require FMODE_READ to retrieve hashes sashiko-bot
2026-10-26 13:36 ` Andrey Albershteyn
2026-10-28 18:06 ` Eric Biggers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261022211522.1489943-1-ebiggers@kernel.org \
--to=ebiggers@kernel.org \
--cc=aalbersh@kernel.org \
--cc=fsverity@lists.linux.dev \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.