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