[bug report] mm: abstract the vma_merge()/split_vma() pattern for mprotect() et al.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Lorenzo Stoakes,

The patch 9c3e157a6d1e: "mm: abstract the vma_merge()/split_vma()
pattern for mprotect() et al." from Oct 9, 2023 (linux-next), leads
to the following Smatch static checker warning:

	fs/userfaultfd.c:940 userfaultfd_release()
	error: 'vma' dereferencing possible ERR_PTR()

fs/userfaultfd.c
    896 static int userfaultfd_release(struct inode *inode, struct file *file)
    897 {
    898         struct userfaultfd_ctx *ctx = file->private_data;
    899         struct mm_struct *mm = ctx->mm;
    900         struct vm_area_struct *vma, *prev;
    901         /* len == 0 means wake all */
    902         struct userfaultfd_wake_range range = { .len = 0, };
    903         unsigned long new_flags;
    904         VMA_ITERATOR(vmi, mm, 0);
    905 
    906         WRITE_ONCE(ctx->released, true);
    907 
    908         if (!mmget_not_zero(mm))
    909                 goto wakeup;
    910 
    911         /*
    912          * Flush page faults out of all CPUs. NOTE: all page faults
    913          * must be retried without returning VM_FAULT_SIGBUS if
    914          * userfaultfd_ctx_get() succeeds but vma->vma_userfault_ctx
    915          * changes while handle_userfault released the mmap_lock. So
    916          * it's critical that released is set to true (above), before
    917          * taking the mmap_lock for writing.
    918          */
    919         mmap_write_lock(mm);
    920         prev = NULL;
    921         for_each_vma(vmi, vma) {
    922                 cond_resched();
    923                 BUG_ON(!!vma->vm_userfaultfd_ctx.ctx ^
    924                        !!(vma->vm_flags & __VM_UFFD_FLAGS));
    925                 if (vma->vm_userfaultfd_ctx.ctx != ctx) {
    926                         prev = vma;
    927                         continue;
    928                 }
    929                 new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS;
    930                 prev = vma_modify_flags_uffd(&vmi, prev, vma, vma->vm_start,
    931                                              vma->vm_end, new_flags,
    932                                              NULL_VM_UFFD_CTX);

This assignment used to be prev = vma_merge() which returns NULL but now
it's a vma_modify which can return NULL or error pointers.  Presumably
it doesn't actually return error pointers in this case, but I figured it
was worth checking.

    933 
    934                 if (prev) {
    935                         vma = prev;
    936                 } else {
    937                         prev = vma;
    938                 }
    939 
--> 940                 vma_start_write(vma);
                                        ^^^
Here is where an error pointer would crash.

    941                 userfaultfd_set_vm_flags(vma, new_flags);
    942                 vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
    943         }
    944         mmap_write_unlock(mm);
    945         mmput(mm);
    946 wakeup:
    947         /*

regards,
dan carpenter




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux