• Paul Mackerras's avatar
    KVM: PPC: Book3S HV: Protect updates to spapr_tce_tables list · edd03602
    Paul Mackerras authored
    Al Viro pointed out that while one thread of a process is executing
    in kvm_vm_ioctl_create_spapr_tce(), another thread could guess the
    file descriptor returned by anon_inode_getfd() and close() it before
    the first thread has added it to the kvm->arch.spapr_tce_tables list.
    That highlights a more general problem: there is no mutual exclusion
    between writers to the spapr_tce_tables list, leading to the
    possibility of the list becoming corrupted, which could cause a
    host kernel crash.
    
    To fix the mutual exclusion problem, we add a mutex_lock/unlock
    pair around the list_del_rce in kvm_spapr_tce_release().  Also,
    this moves the call to anon_inode_getfd() inside the region
    protected by the kvm->lock mutex, after we have done the check for
    a duplicate LIOBN.  This means that if another thread does guess the
    file descriptor and closes it, its call to kvm_spapr_tce_release()
    will not do any harm because it will have to wait until the first
    thread has released kvm->lock.  With this, there are no failure
    points in kvm_vm_ioctl_create_spapr_tce() after the call to
    anon_inode_getfd().
    
    The other things that the second thread could do with the guessed
    file descriptor are to mmap it or to pass it as a parameter to a
    KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE ioctl on a KVM device fd.  An mmap
    call won't cause any harm because kvm_spapr_tce_mmap() and
    kvm_spapr_tce_fault() don't access the spapr_tce_tables list or
    the kvmppc_spapr_tce_table.list field, and the fields that they do use
    have been properly initialized by the time of the anon_inode_getfd()
    call.
    
    The KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE ioctl calls
    kvm_spapr_tce_attach_iommu_group(), which scans the spapr_tce_tables
    list looking for the kvmppc_spapr_tce_table struct corresponding to
    the fd given as the parameter.  Either it will find the new entry
    or it won't; if it doesn't, it just returns an error, and if it
    does, it will function normally.  So, in each case there is no
    harmful effect.
    Reviewed-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
    Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
    edd03602
book3s_64_vio.c 14.8 KB