From: sashiko-bot@kernel.org
To: "John Groves" <john@jagalactic.com>
Cc: nvdimm@lists.linux.dev, linux-cxl@vger.kernel.org
Subject: Re: [PATCH V11 6/9] famfs_fuse: Plumb dax iomap and fuse read/write/mmap
Date: Mon, 20 Jul 2026 03:57:03 +0000 [thread overview]
Message-ID: <20260720035703.D96F01F000E9@smtp.kernel.org> (raw)
In-Reply-To: <0100019f7da1cf3d-bb04c043-a09f-4925-bf63-eb92452871e5-000000@email.amazonses.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [Critical] famfs_fuse_write_iter and famfs_fuse_read_iter completely bypass mandatory VFS locking, security privilege stripping, and POSIX semantics.
- [High] famfs_fuse_mmap fails to set the VM_MIXEDMAP flag, guaranteeing a BUG_ON() crash during DAX page faults.
- [High] Explicitly returning -EIO for splice operations on famfs files breaks standard system calls like sendfile() and splice().
- [High] 32-bit architectures suffer from silent data truncation due to the use of size_t and off_t for 64-bit file offsets and sizes.
- [Medium] Concurrent, lockless modification of `meta->error` in `famfs_file_bad()` creates a data race.
--
--- Patch [6]: [PATCH V11 6/9] famfs_fuse: Plumb dax iomap and fuse read/write/mmap ---
commit 26226f89d9106affa50e5f7fc0a4be4656c4531c
Author: John Groves <john@groves.net>
famfs_fuse: Plumb dax iomap and fuse read/write/mmap
This commit adds read, write, and mmap support for famfs files using the
dev_dax_iomap interface. It handles file offset resolution and page faults
via DAX upcalls.
> diff --git a/fs/fuse/famfs.c b/fs/fuse/famfs.c
> index a2a7dd631dc0f..ac56317944d93 100644
> --- a/fs/fuse/famfs.c
> +++ b/fs/fuse/famfs.c
[ ... ]
> +static int
> +famfs_fileofs_to_daxofs(struct inode *inode, struct iomap *iomap,
> + loff_t file_offset, off_t len, unsigned int flags)
> +{
[Severity: High]
Does defining the len parameter as off_t truncate the mapping length on 32-bit
systems?
[ ... ]
> +const struct vm_operations_struct famfs_file_vm_ops = {
> + .fault = famfs_filemap_fault,
> + .huge_fault = famfs_filemap_huge_fault,
> + .map_pages = filemap_map_pages,
[Severity: High]
Is it correct to assign a page-cache-specific mapping function here? Since
DAX mappings bypass the page cache, using filemap_map_pages might lead to
unexpected behavior.
> + .page_mkwrite = famfs_filemap_mkwrite,
> + .pfn_mkwrite = famfs_filemap_mkwrite,
> +};
[ ... ]
> +static int
> +famfs_file_bad(struct inode *inode)
> +{
> + struct fuse_inode *fi = get_fuse_inode(inode);
> + struct famfs_file_meta *meta = fi->famfs_meta;
> + size_t i_size = i_size_read(inode);
> +
> + if (!meta) {
> + pr_err("%s: un-initialized famfs file\n", __func__);
> + return -EIO;
> + }
> + if (meta->error) {
> + pr_debug("%s: previously detected metadata errors\n", __func__);
> + return -EIO;
> + }
> + if (i_size != meta->file_size) {
> + pr_warn("%s: i_size overwritten from %ld to %ld\n",
> + __func__, meta->file_size, i_size);
> + meta->error = true;
[Severity: Medium]
Can concurrent I/O operations cause a data race on meta->error? Since read
and write paths can execute without the inode lock, multiple threads might
modify this flag simultaneously.
> + return -ENXIO;
> + }
[ ... ]
> +static ssize_t
> +famfs_fuse_rw_prep(struct kiocb *iocb, struct iov_iter *ubuf)
> +{
> + struct inode *inode = iocb->ki_filp->f_mapping->host;
> + size_t i_size = i_size_read(inode);
[Severity: High]
Might reading i_size_read() into a size_t truncate the 64-bit value on 32-bit
platforms? This would break I/O bounds checking for files larger than 4GB.
This also applies to the file_size field in the famfs_file_meta structure if
it is similarly defined as size_t.
> + size_t count = iov_iter_count(ubuf);
> + size_t max_count;
> + ssize_t rc;
[ ... ]
> +ssize_t
> +famfs_fuse_read_iter(struct kiocb *iocb, struct iov_iter *to)
> +{
> + ssize_t rc;
> +
> + rc = famfs_fuse_rw_prep(iocb, to);
> + if (rc)
> + return rc;
> +
> + if (!iov_iter_count(to))
> + return 0;
> +
> + rc = dax_iomap_rw(iocb, to, &famfs_iomap_ops);
[Severity: Critical]
Does this read path need to acquire inode_lock_shared()? The standard VFS
read paths typically acquire it before calling dax_iomap_rw().
> +
> + file_accessed(iocb->ki_filp);
> + return rc;
> +}
> +
> +ssize_t
> +famfs_fuse_write_iter(struct kiocb *iocb, struct iov_iter *from)
> +{
> + ssize_t rc;
> +
> + rc = famfs_fuse_rw_prep(iocb, from);
> + if (rc)
> + return rc;
> +
> + if (!iov_iter_count(from))
> + return 0;
> +
> + return dax_iomap_rw(iocb, from, &famfs_iomap_ops);
> +}
[Severity: Critical]
Does this write path omit mandatory VFS security and integrity checks?
Calling dax_iomap_rw() directly without acquiring inode_lock() bypasses
generic_write_checks() and file_remove_privs(), which could allow
unprivileged modification of setuid/setgid files and bypass O_APPEND
restrictions.
> +int
> +famfs_fuse_mmap(struct file *file, struct vm_area_struct *vma)
> +{
> + struct inode *inode = file_inode(file);
> + ssize_t rc;
> +
> + rc = famfs_file_bad(inode);
> + if (rc)
> + return rc;
> +
> + file_accessed(file);
> + vma->vm_ops = &famfs_file_vm_ops;
> + vm_flags_set(vma, VM_HUGEPAGE);
[Severity: High]
Could this trigger a kernel panic during DAX page faults? The
vmf_insert_mixed() path expects VM_MIXEDMAP or VM_PFNMAP to be set on the
vma, but VM_MIXEDMAP appears to be omitted here.
> + return 0;
> +}
[ ... ]
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index b4e7b6a645870..2435a79cbb4a3 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
[ ... ]
> @@ -1896,9 +1900,13 @@ static ssize_t fuse_splice_read(struct file *in, loff_t *ppos,
> unsigned int flags)
> {
> struct fuse_file *ff = in->private_data;
> + struct inode *inode = file_inode(in);
> + struct fuse_inode *fi = get_fuse_inode(inode);
>
> /* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */
> - if (fuse_file_passthrough(ff) && !(ff->open_flags & FOPEN_DIRECT_IO))
> + if (fuse_file_famfs(fi))
> + return -EIO; /* famfs does not use the page cache... */
[Severity: High]
Will returning -EIO break standard system calls like splice() and sendfile()
for famfs files? Should this fall back to iter_file_splice_read() or
copy_splice_read() instead?
> + else if (fuse_file_passthrough(ff) && !(ff->open_flags & FOPEN_DIRECT_IO))
> return fuse_passthrough_splice_read(in, ppos, pipe, len, flags);
> else
> return filemap_splice_read(in, ppos, pipe, len, flags);
> @@ -1908,9 +1916,13 @@ static ssize_t fuse_splice_write(struct pipe_inode_info *pipe, struct file *out,
> loff_t *ppos, size_t len, unsigned int flags)
> {
> struct fuse_file *ff = out->private_data;
> + struct inode *inode = file_inode(out);
> + struct fuse_inode *fi = get_fuse_inode(inode);
>
> /* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */
> - if (fuse_file_passthrough(ff) && !(ff->open_flags & FOPEN_DIRECT_IO))
> + if (fuse_file_famfs(fi))
> + return -EIO; /* famfs does not use the page cache... */
[Severity: High]
Does hardcoding -EIO here also break splice writes? Falling back to
iter_file_splice_write() might be required to keep standard system calls
functioning.
> + else if (fuse_file_passthrough(ff) && !(ff->open_flags & FOPEN_DIRECT_IO))
> return fuse_passthrough_splice_write(pipe, out, ppos, len, flags);
> else
> return iter_file_splice_write(pipe, out, ppos, len, flags);
--
Sashiko AI review · https://sashiko.dev/#/patchset/0100019f7d9fbe81-6cb16662-2522-47ea-a152-fab0ee3d9b35-000000@email.amazonses.com?part=6
next prev parent reply other threads:[~2026-07-20 3:57 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260720034358.68714-1-john@jagalactic.com>
2026-07-20 3:44 ` [PATCH V11 0/9] famfs: port into fuse John Groves
2026-07-20 3:45 ` [PATCH V11 1/9] famfs_fuse: Update macro s/FUSE_IS_DAX/FUSE_IS_VIRTIO_DAX/ John Groves
2026-07-20 3:45 ` [PATCH V11 2/9] famfs_fuse: Basic fuse kernel ABI enablement for famfs John Groves
2026-07-20 3:56 ` sashiko-bot
2026-07-20 3:45 ` [PATCH V11 3/9] famfs_fuse: Plumb the GET_FMAP message/response John Groves
2026-07-20 3:56 ` sashiko-bot
2026-07-20 3:46 ` [PATCH V11 4/9] famfs_fuse: Create files with famfs fmaps John Groves
2026-07-20 3:59 ` sashiko-bot
2026-07-20 3:46 ` [PATCH V11 5/9] famfs_fuse: register fs-dax daxdevs via FUSE_DEV_IOC_DAXDEV_OPEN John Groves
2026-07-20 4:02 ` sashiko-bot
2026-07-20 3:46 ` [PATCH V11 6/9] famfs_fuse: Plumb dax iomap and fuse read/write/mmap John Groves
2026-07-20 3:57 ` sashiko-bot [this message]
2026-07-20 3:46 ` [PATCH V11 7/9] famfs_fuse: fail I/O on invalid or errored daxdevs John Groves
2026-07-20 4:00 ` sashiko-bot
2026-07-20 3:46 ` [PATCH V11 8/9] famfs_fuse: Add DAX address_space_operations with noop_dirty_folio John Groves
2026-07-20 4:04 ` sashiko-bot
2026-07-20 3:47 ` [PATCH V11 9/9] famfs_fuse: Add documentation John Groves
2026-07-20 4:09 ` sashiko-bot
2026-07-20 10:07 ` [PATCH V11 0/9] famfs: port into fuse Amir Goldstein
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=20260720035703.D96F01F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=john@jagalactic.com \
--cc=linux-cxl@vger.kernel.org \
--cc=nvdimm@lists.linux.dev \
--cc=sashiko-reviews@lists.linux.dev \
/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.