• Nicolas Geoffray's avatar
    mm, memfd: fix COW issue on MAP_PRIVATE and F_SEAL_FUTURE_WRITE mappings · 05d35110
    Nicolas Geoffray authored
    F_SEAL_FUTURE_WRITE has unexpected behavior when used with MAP_PRIVATE:
    A private mapping created after the memfd file that gets sealed with
    F_SEAL_FUTURE_WRITE loses the copy-on-write at fork behavior, meaning
    children and parent share the same memory, even though the mapping is
    private.
    
    The reason for this is due to the code below:
    
      static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
      {
            struct shmem_inode_info *info = SHMEM_I(file_inode(file));
    
            if (info->seals & F_SEAL_FUTURE_WRITE) {
                    /*
                     * New PROT_WRITE and MAP_SHARED mmaps are not allowed when
                     * "future write" seal active.
                     */
                    if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_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.
                     */
                    vma->vm_flags &= ~(VM_MAYWRITE);
            }
            ...
      }
    
    And for the mm to know if a mapping is copy-on-write:
    
      static inline bool is_cow_mapping(vm_flags_t flags)
      {
            return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
      }
    
    The patch fixes the issue by making the mprotect revert protection
    happen only for shared mappings.  For private mappings, using mprotect
    will have no effect on the seal behavior.
    
    The F_SEAL_FUTURE_WRITE feature was introduced in v5.1 so v5.3.x stable
    kernels would need a backport.
    
    [akpm@linux-foundation.org: reflow comment, per Christoph]
    Link: http://lkml.kernel.org/r/20191107195355.80608-1-joel@joelfernandes.org
    Fixes: ab3948f5 ("mm/memfd: add an F_SEAL_FUTURE_WRITE seal to memfd")
    Signed-off-by: default avatarNicolas Geoffray <ngeoffray@google.com>
    Signed-off-by: default avatarJoel Fernandes (Google) <joel@joelfernandes.org>
    Cc: Hugh Dickins <hughd@google.com>
    Cc: Shuah Khan <shuah@kernel.org>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    05d35110
shmem.c 108 KB