vfio: Fully lock struct vfio_group::container
authorJason Gunthorpe <jgg@nvidia.com>
Mon, 16 May 2022 23:41:20 +0000 (20:41 -0300)
committerAlex Williamson <alex.williamson@redhat.com>
Tue, 17 May 2022 19:07:09 +0000 (13:07 -0600)
commite0e29bdb594adf472eeff475539ee39708b2b07b
tree678a21fe1aac3d249d5972394a038148e5a680bd
parent805bb6c1bd9009e389f884fa30ec5f5e5079376d
vfio: Fully lock struct vfio_group::container

This is necessary to avoid various user triggerable races, for instance
racing SET_CONTAINER/UNSET_CONTAINER:

                                  ioctl(VFIO_GROUP_SET_CONTAINER)
ioctl(VFIO_GROUP_UNSET_CONTAINER)
 vfio_group_unset_container
    int users = atomic_cmpxchg(&group->container_users, 1, 0);
    // users == 1 container_users == 0
    __vfio_group_unset_container(group);
      container = group->container;
                                    vfio_group_set_container()
                              if (!atomic_read(&group->container_users))
        down_write(&container->group_lock);
        group->container = container;
        up_write(&container->group_lock);

      down_write(&container->group_lock);
      group->container = NULL;
      up_write(&container->group_lock);
      vfio_container_put(container);
      /* woops we lost/leaked the new container  */

This can then go on to NULL pointer deref since container == 0 and
container_users == 1.

Wrap all touches of container, except those on a performance path with a
known open device, with the group_rwsem.

The only user of vfio_group_add_container_user() holds the user count for
a simple operation, change it to just hold the group_lock over the
operation and delete vfio_group_add_container_user(). Containers now only
gain a user when a device FD is opened.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Tested-by: Matthew Rosato <mjrosato@linux.ibm.com>
Link: https://lore.kernel.org/r/4-v2-d035a1842d81+1bf-vfio_group_locking_jgg@nvidia.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
drivers/vfio/vfio.c