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
next prev parent 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