All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Pasha Tatashin" <pasha.tatashin@soleen.com>,
	rppt@kernel.org, shuah@kernel.org, akpm@linux-foundation.org,
	vipinsh@google.com, dmatlack@google.com,
	kexec@lists.infradead.org, pratyush@kernel.org, graf@amazon.com
Subject: Re: [PATCH v1 6/7] mm/memfd_luo: Support tmpfs preservation and retrieval
Date: Thu, 15 Oct 2026 09:54:08 +0000	[thread overview]
Message-ID: <sashiko-outbox-172604@kernel.org> (raw)
In-Reply-To: <20261015093816.2438942-7-pasha.tatashin@soleen.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] mm: memfd_luo_retrieve drops file seals on tmpfs retrieval causing security bypass
- [High] mm: memfd_luo_retrieve ABBA deadlock between inode lock and f_pos_lock
- [High] mm: permanent leak of KHO folios on early memfd_luo_retrieve errors
--

commit 54190d07831630c2e724ceea33310f62bf42a6dd
Author: David Matlack <dmatlack@google.com>

mm/memfd_luo: Support tmpfs preservation and retrieval

This commit relaxes memfd_luo_can_preserve() to support general shmem-backed
files, allowing userspace to preserve standard tmpfs files across kexec. It
introduces a new MEMFD_LUO_FLAG_TMPFS flag and a new UAPI struct
liveupdate_memfd_retrieve_arg to support restoring preserved tmpfs folios
to a newly created tmpfs file.

> diff --git a/mm/memfd_luo.c b/mm/memfd_luo.c
> --- a/mm/memfd_luo.c
> +++ b/mm/memfd_luo.c
> @@ -516,10 +519,60 @@ static int memfd_luo_retrieve_folios(struct file *file,
>  	return err;
>  }
>  
> +static struct file *memfd_luo_get_tmpfs_file(struct liveupdate_file_op_args *args)
> +{
> +	const struct liveupdate_memfd_retrieve_arg *rarg = args->arg;

[ ... ]

> +	inode = file_inode(file);
> +	inode_lock(inode);
> +	if (!inode->i_nlink) {
> +		err = -EINVAL;
> +		goto unlock_inode;
> +	}

[ ... ]

> +	return file;
> +
> +unlock_inode:
> +	inode_unlock(inode);
> +put_file:
> +	fput(file);
> +	return ERR_PTR(err);
> +}
> +
>  static int memfd_luo_retrieve(struct liveupdate_file_op_args *args)
>  {
>  	struct memfd_luo_folio_ser *folios_ser;
>  	struct memfd_luo_ser *ser;
> +	struct inode *inode;
>  	struct file *file;
>  	int err;
>  
> @@ -527,50 +580,75 @@ static int memfd_luo_retrieve(struct liveupdate_file_op_args *args)
>  	if (!ser)
>  		return -EINVAL;
>  
> -	/* Make sure the file only has seals supported by this version. */
> -	if (ser->seals & ~MEMFD_LUO_ALL_SEALS) {
> +	/* Make sure the file only has seals and flags supported by this version. */
> +	if ((ser->seals & ~MEMFD_LUO_ALL_SEALS) ||
> +	    (ser->flags & ~MEMFD_LUO_ALL_FLAGS)) {
>  		err = -EOPNOTSUPP;
>  		goto free_ser;
>  	}

[Severity: High]
Does this error path permanently leak the KHO memory?

If memfd_luo_retrieve() encounters a permanent error here (like unsupported
seals), it jumps to free_ser and returns an error without setting
args->retryable = true. The LUO core then records this negative error code
in luo_file->retrieve_status. 

When memfd_luo_finish() is later called:

	if (args->retrieve_status)
		return;

It returns early because args->retrieve_status != 0, never attempting to
discard the ser->folios vmalloc array or the underlying physical data
folios. Those folios would remain permanently reserved in memblock.

> +	if (ser->flags & MEMFD_LUO_FLAG_TMPFS) {
> +		file = memfd_luo_get_tmpfs_file(args);
> +		if (IS_ERR(file)) {
> +			args->retryable = true;
> +			return PTR_ERR(file);
> +		}
> +		inode = file_inode(file);
> +	} else {
> +		if (args->arg) {
> +			args->retryable = true;
> +			return -EINVAL;
> +		}
>  
> -		/*
> -		 * The seals are preserved. Allow sealing here so they can be added
> -		 * later.
> -		 */
> -		file = memfd_alloc_file("", MFD_ALLOW_SEALING);
> -		if (IS_ERR(file)) {
> -			pr_err("failed to setup file: %pe\n", file);
> -			err = PTR_ERR(file);
> -			goto free_ser;
> -		}
> +		/*
> +		 * The seals are preserved. Allow sealing here so they can be
> +		 * added later.
> +		 */
> +		file = memfd_alloc_file("", MFD_ALLOW_SEALING);
> +		if (IS_ERR(file)) {
> +			pr_err("failed to setup file: %pe\n", file);
> +			err = PTR_ERR(file);
> +			goto free_ser;
> +		}
>  
> -	err = memfd_add_seals(file, ser->seals);
> -	if (err) {
> -		pr_err("failed to add seals: %pe\n", ERR_PTR(err));
> -		goto put_file;
> -	}
> +		err = memfd_add_seals(file, ser->seals);
> +		if (err) {
> +			pr_err("failed to add seals: %pe\n", ERR_PTR(err));
> +			goto put_file;
> +		}
> +
> +		inode = file_inode(file);
> +		inode_lock(inode);
> +	}

[Severity: High]
Does this bypass security seals on retrieved tmpfs files?

memfd_luo_preserve() records seals in ser->seals for all files. However,
the tmpfs branch above entirely skips calling memfd_add_seals(). If an
immutable or write-sealed memfd was linked to the filesystem prior to kexec,
it appears it will be restored into the user's empty tmpfs file without any
seals applied, resulting in a fully writable and modifiable file.

>  	if (ser->nr_folios) {
>  		folios_ser = kho_restore_vmalloc(&ser->folios);
>  		if (!folios_ser) {
>  			err = -EINVAL;
> -			goto put_file;
> +			goto unclaim_file;
>  		}
>  
>  		err = memfd_luo_retrieve_folios(file, folios_ser, ser->nr_folios);
>  		vfree(folios_ser);
>  		if (err)
> -			goto put_file;
> +			goto unclaim_file;
>  	}
>  
> +	vfs_setpos(file, ser->pos, MAX_LFS_FILESIZE);

[Severity: High]
Can this create an ABBA deadlock between inode_lock and f_pos_lock?

For tmpfs files, memfd_luo_get_tmpfs_file() acquires and returns with
inode_lock(inode) held. Later, vfs_setpos() is called here, which acquires
mutex_lock(&file->f_pos_lock) while inode_lock is still held.

Since the file is a normal file descriptor passed by userspace, the standard
VFS write path acquires file->f_pos_lock first via fdget_pos(), and then
acquires inode_lock(inode) inside the filesystem's write iterator. A
concurrent write() on the provided file descriptor could trigger a deadlock.

> +	i_size_write(inode, ser->size);
> +	inode_unlock(inode);
> +
>  	args->file = file;
>  	kho_restore_free(ser);
>  
>  	return 0;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261015093816.2438942-1-pasha.tatashin@soleen.com?part=6


  reply	other threads:[~2026-10-15  9:54 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-15  9:38 [PATCH v1 0/7] liveupdate: tmpfs preservation and early freeze Pasha Tatashin
2026-10-15  9:38 ` [PATCH v1 1/7] liveupdate: Add LIVEUPDATE_SESSION_FREEZE ioctl to freeze sessions early Pasha Tatashin
2026-10-15  9:47   ` sashiko-bot
2026-10-15  9:38 ` [PATCH v1 2/7] selftests: liveupdate: Add tests for LIVEUPDATE_SESSION_FREEZE Pasha Tatashin
2026-10-15  9:45   ` sashiko-bot
2026-10-15  9:38 ` [PATCH v1 3/7] liveupdate: Pass user argument to file preserve and retrieve Pasha Tatashin
2026-10-15  9:49   ` sashiko-bot
2026-10-15  9:38 ` [PATCH v1 4/7] selftests: liveupdate: Add tests for preserve and retrieve user argument Pasha Tatashin
2026-10-15  9:45   ` sashiko-bot
2026-10-15  9:38 ` [PATCH v1 5/7] liveupdate: Allow file handlers to mark retrieve failures as retryable Pasha Tatashin
2026-10-15  9:46   ` sashiko-bot
2026-10-15  9:38 ` [PATCH v1 6/7] mm/memfd_luo: Support tmpfs preservation and retrieval Pasha Tatashin
2026-10-15  9:54   ` sashiko-bot [this message]
2026-10-15  9:38 ` [PATCH v1 7/7] selftests: liveupdate: Add test coverage for " Pasha Tatashin
2026-10-15  9:47   ` sashiko-bot
2026-10-15 17:48 ` [PATCH v1 0/7] liveupdate: tmpfs preservation and early freeze David Matlack
2026-10-15 18:23   ` Pasha Tatashin
2026-10-15 18:54     ` David Matlack
2026-10-15 20:38       ` Pasha Tatashin
2026-10-15 21:53         ` David Matlack

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=sashiko-outbox-172604@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=dmatlack@google.com \
    --cc=graf@amazon.com \
    --cc=kexec@lists.infradead.org \
    --cc=pasha.tatashin@soleen.com \
    --cc=pratyush@kernel.org \
    --cc=rppt@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=shuah@kernel.org \
    --cc=vipinsh@google.com \
    /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.