The patch titled Subject: mm/memfd: make F_SEAL_FUTURE_WRITE seal more robust has been added to the -mm tree. Its filename is mm-add-an-f_seal_future_write-seal-to-memfd-fix.patch This patch should soon appear at http://ozlabs.org/~akpm/mmots/broken-out/mm-add-an-f_seal_future_write-seal-to-memfd-fix.patch and later at http://ozlabs.org/~akpm/mmotm/broken-out/mm-add-an-f_seal_future_write-seal-to-memfd-fix.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next and is updated there every 3-4 working days ------------------------------------------------------ From: "Joel Fernandes (Google)" <joel@xxxxxxxxxxxxxxxxx> Subject: mm/memfd: make F_SEAL_FUTURE_WRITE seal more robust A better way to do F_SEAL_FUTURE_WRITE seal was discussed [1] last week where we don't need to modify core VFS structures to get the same behavior of the seal. This solves several side-effects pointed out by Andy [2]. [1] https://lore.kernel.org/lkml/20181111173650.GA256781@xxxxxxxxxx/ [2] https://lore.kernel.org/lkml/69CE06CC-E47C-4992-848A-66EB23EE6C74@xxxxxxxxxxxxxx/ Link: http://lkml.kernel.org/r/20181120052137.74317-1-joel@xxxxxxxxxxxxxxxxx Signed-off-by: Joel Fernandes (Google) <joel@xxxxxxxxxxxxxxxxx> Suggested-by: Andy Lutomirski <luto@xxxxxxxxxx> Cc: John Stultz <john.stultz@xxxxxxxxxx> Cc: John Reck <jreck@xxxxxxxxxx> Cc: Todd Kjos <tkjos@xxxxxxxxxx> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxxxxxxxxx> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: Daniel Colascione <dancol@xxxxxxxxxx> Cc: J. Bruce Fields <bfields@xxxxxxxxxxxx> Cc: Jeff Layton <jlayton@xxxxxxxxxx> Cc: Khalid Aziz <khalid.aziz@xxxxxxxxxx> Cc: Lei Yang <Lei.Yang@xxxxxxxxxxxxx> Cc: Marc-Andr Lureau <marcandre.lureau@xxxxxxxxxx> Cc: Mike Kravetz <mike.kravetz@xxxxxxxxxx> Cc: Minchan Kim <minchan@xxxxxxxxxx> Cc: Shuah Khan <shuah@xxxxxxxxxx> Cc: Valdis Kletnieks <valdis.kletnieks@xxxxxx> Cc: Jann Horn <jannh@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- --- a/fs/hugetlbfs/inode.c~mm-add-an-f_seal_future_write-seal-to-memfd-fix +++ a/fs/hugetlbfs/inode.c @@ -530,7 +530,7 @@ static long hugetlbfs_punch_hole(struct inode_lock(inode); /* protected by i_mutex */ - if (info->seals & F_SEAL_WRITE) { + if (info->seals & (F_SEAL_WRITE | F_SEAL_FUTURE_WRITE)) { inode_unlock(inode); return -EPERM; } --- a/mm/memfd.c~mm-add-an-f_seal_future_write-seal-to-memfd-fix +++ a/mm/memfd.c @@ -201,25 +201,6 @@ static int memfd_add_seals(struct file * } } - if ((seals & F_SEAL_FUTURE_WRITE) && - !(*file_seals & F_SEAL_FUTURE_WRITE)) { - /* - * The FUTURE_WRITE seal also prevents growing and shrinking - * so we need them to be already set, or requested now. - */ - int test_seals = (seals | *file_seals) & - (F_SEAL_GROW | F_SEAL_SHRINK); - - if (test_seals != (F_SEAL_GROW | F_SEAL_SHRINK)) { - error = -EINVAL; - goto unlock; - } - - spin_lock(&file->f_lock); - file->f_mode &= ~(FMODE_WRITE | FMODE_PWRITE); - spin_unlock(&file->f_lock); - } - *file_seals |= seals; error = 0; --- a/mm/shmem.c~mm-add-an-f_seal_future_write-seal-to-memfd-fix +++ a/mm/shmem.c @@ -2119,6 +2119,23 @@ out_nomem: static int shmem_mmap(struct file *file, struct vm_area_struct *vma) { + struct shmem_inode_info *info = SHMEM_I(file_inode(file)); + + /* + * New PROT_READ and MAP_SHARED mmaps are not allowed when "future + * write" seal active. + */ + if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE) && + (info->seals & F_SEAL_FUTURE_WRITE)) + return -EPERM; + + /* + * Since the F_SEAL_FUTURE_WRITE seals allow for a MAP_SHARED read-only + * mapping, take care to not allow mprotect to revert protections. + */ + if (info->seals & F_SEAL_FUTURE_WRITE) + vma->vm_flags &= ~(VM_MAYWRITE); + file_accessed(file); vma->vm_ops = &shmem_vm_ops; if (IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE) && @@ -2344,8 +2361,9 @@ shmem_write_begin(struct file *file, str pgoff_t index = pos >> PAGE_SHIFT; /* i_mutex is held by caller */ - if (unlikely(info->seals & (F_SEAL_WRITE | F_SEAL_GROW))) { - if (info->seals & F_SEAL_WRITE) + if (unlikely(info->seals & (F_SEAL_GROW | + F_SEAL_WRITE | F_SEAL_FUTURE_WRITE))) { + if (info->seals & (F_SEAL_WRITE | F_SEAL_FUTURE_WRITE)) return -EPERM; if ((info->seals & F_SEAL_GROW) && pos + len > inode->i_size) return -EPERM; @@ -2608,7 +2626,7 @@ static long shmem_fallocate(struct file DECLARE_WAIT_QUEUE_HEAD_ONSTACK(shmem_falloc_waitq); /* protected by i_mutex */ - if (info->seals & F_SEAL_WRITE) { + if (info->seals & (F_SEAL_WRITE | F_SEAL_FUTURE_WRITE)) { error = -EPERM; goto out; } _ Patches currently in -mm which might be from joel@xxxxxxxxxxxxxxxxx are mm-treewide-remove-unused-address-argument-from-pte_alloc-functions-v2.patch mm-speed-up-mremap-by-20x-on-large-regions-v5.patch mm-speed-up-mremap-by-20x-on-large-regions-v5-fix.patch mm-select-have_move_pmd-in-x86-for-faster-mremap.patch mm-add-an-f_seal_future_write-seal-to-memfd.patch mm-add-an-f_seal_future_write-seal-to-memfd-fix.patch selftests-memfd-add-tests-for-f_seal_future_write-seal.patch selftests-memfd-add-tests-for-f_seal_future_write-seal-fix.patch