On Fri, Jan 23, 2026 at 10:58:51AM +0100, Pratyush Yadav wrote:
> From: "Pratyush Yadav (Google)" <[email protected]>
> 
> File seals are used on memfd for making shared memory communication with
> untrusted peers safer and simpler. Seals provide a guarantee that
> certain operations won't be allowed on the file such as writes or
> truncations. Maintaining these guarantees across a live update will help
> keeping such use cases secure.
> 
> These guarantees will also be needed for IOMMUFD preservation with LUO.
> Normally when IOMMUFD maps a memfd, it pins all its pages to make sure
> any truncation operations on the memfd don't lead to IOMMUFD using freed
> memory. This doesn't work with LUO since the preserved memfd might have
> completely different pages after a live update, and mapping them back to
> the IOMMUFD will cause all sorts of problems. Using and preserving the
> seals allows IOMMUFD preservation logic to trust the memfd.
> 
> Preserve the seals by introducing a new 8-bit-wide bitfield. There are
> currently only 6 possible seals but 2 extra bits are used to provide
> room for future expansion. Since the seals are UAPI, it is safe to use
> them directly in the ABI.
> 
> Back the 8-bit field with a u64, leaving 56 unused bits. This is done to
> keep the struct nice and aligned. The unused bits can be used to add new
> flags later, potentially without even needing to bump the version
> number.
> 
> Since the serialization structure is changed, bump the version number to
> "memfd-v2".
> 
> Signed-off-by: Pratyush Yadav (Google) <[email protected]>
> ---
>  include/linux/kho/abi/memfd.h |  9 ++++++++-
>  mm/memfd_luo.c                | 23 +++++++++++++++++++++--
>  2 files changed, 29 insertions(+), 3 deletions(-)
> 
> diff --git a/include/linux/kho/abi/memfd.h b/include/linux/kho/abi/memfd.h
> index 68cb6303b846..bd549c81f1d2 100644
> --- a/include/linux/kho/abi/memfd.h
> +++ b/include/linux/kho/abi/memfd.h
> @@ -60,6 +60,11 @@ struct memfd_luo_folio_ser {
>   * struct memfd_luo_ser - Main serialization structure for a memfd.
>   * @pos:       The file's current position (f_pos).
>   * @size:      The total size of the file in bytes (i_size).
> + * @seals:     The seals present on the memfd. The seals are UAPI so it is 
> safe
> + *             to directly use them in the ABI. Note: currently there are 6
> + *             seals possible but this field is 8 bits to leave room for 
> future
> + *             expansion.
> + * @__reserved: Reserved bits. May be used later to add more flags.
>   * @nr_folios: Number of folios in the folios array.
>   * @folios:    KHO vmalloc descriptor pointing to the array of
>   *             struct memfd_luo_folio_ser.
> @@ -67,11 +72,13 @@ struct memfd_luo_folio_ser {
>  struct memfd_luo_ser {
>       u64 pos;
>       u64 size;
> +     u64 seals:8;

Kernel uABI defines seals as unsigned int, I think we can spare u32 for
them and reserve a u32 flags for other memfd flags (MFD_CLOEXEC,
MFD_HUGETLB etc).

> +     u64 __reserved:56;
>       u64 nr_folios;
>       struct kho_vmalloc folios;
>  } __packed;
>  
>  /* The compatibility string for memfd file handler */
> -#define MEMFD_LUO_FH_COMPATIBLE      "memfd-v1"
> +#define MEMFD_LUO_FH_COMPATIBLE      "memfd-v2"
>  
>  #endif /* _LINUX_KHO_ABI_MEMFD_H */
> diff --git a/mm/memfd_luo.c b/mm/memfd_luo.c
> index a34fccc23b6a..eb68e0b5457f 100644
> --- a/mm/memfd_luo.c
> +++ b/mm/memfd_luo.c
> @@ -79,6 +79,8 @@
>  #include <linux/shmem_fs.h>
>  #include <linux/vmalloc.h>
>  #include <linux/memfd.h>
> +#include <uapi/linux/memfd.h>
> +
>  #include "internal.h"
>  
>  static int memfd_luo_preserve_folios(struct file *file,
> @@ -222,7 +224,7 @@ static int memfd_luo_preserve(struct 
> liveupdate_file_op_args *args)
>       struct memfd_luo_folio_ser *folios_ser;
>       struct memfd_luo_ser *ser;
>       u64 nr_folios;
> -     int err = 0;
> +     int err = 0, seals;
>  
>       inode_lock(inode);
>       shmem_freeze(inode, true);
> @@ -234,8 +236,15 @@ static int memfd_luo_preserve(struct 
> liveupdate_file_op_args *args)
>               goto err_unlock;
>       }
>  
> +     seals = memfd_get_seals(args->file);
> +     if (seals < 0) {
> +             err = seals;
> +             goto err_free_ser;
> +     }
> +
>       ser->pos = args->file->f_pos;
>       ser->size = i_size_read(inode);
> +     ser->seals = seals;
>  
>       err = memfd_luo_preserve_folios(args->file, &ser->folios,
>                                       &folios_ser, &nr_folios);
> @@ -444,13 +453,23 @@ static int memfd_luo_retrieve(struct 
> liveupdate_file_op_args *args)
>       if (!ser)
>               return -EINVAL;
>  
> -     file = memfd_alloc_file("", 0);
> +     /*
> +      * The seals are preserved. Allow sealing here so they can be added
> +      * later.
> +      */
> +     file = memfd_alloc_file("", MFD_ALLOW_SEALING);

I think we should select flags passed to memfd_alloc_file() based on
ser->seals (and later based on ser->seals and ser->flags).

>       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);

I'm not sure using MFD_ALLOW_SEALING is enough if there was F_SEAL_EXEC in
seals.

> +     if (err) {
> +             pr_err("failed to add seals: %pe\n", ERR_PTR(err));
> +             goto put_file;
> +     }
> +
>       vfs_setpos(file, ser->pos, MAX_LFS_FILESIZE);
>       file->f_inode->i_size = ser->size;
>  
> -- 
> 2.52.0.457.g6b5491de43-goog
> 

-- 
Sincerely yours,
Mike.

Reply via email to