Linux CXL
 help / color / mirror / Atom feed
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

  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox