• Desmond Cheong Zhi Xi's avatar
    drm: serialize drm_file.master with a new spinlock · 0b0860a3
    Desmond Cheong Zhi Xi authored
    Currently, drm_file.master pointers should be protected by
    drm_device.master_mutex when being dereferenced. This is because
    drm_file.master is not invariant for the lifetime of drm_file. If
    drm_file is not the creator of master, then drm_file.is_master is
    false, and a call to drm_setmaster_ioctl will invoke
    drm_new_set_master, which then allocates a new master for drm_file and
    puts the old master.
    
    Thus, without holding drm_device.master_mutex, the old value of
    drm_file.master could be freed while it is being used by another
    concurrent process.
    
    However, it is not always possible to lock drm_device.master_mutex to
    dereference drm_file.master. Through the fbdev emulation code, this
    might occur in a deep nest of other locks. But drm_device.master_mutex
    is also the outermost lock in the nesting hierarchy, so this leads to
    potential deadlocks.
    
    To address this, we introduce a new spin lock at the bottom of the
    lock hierarchy that only serializes drm_file.master. With this change,
    the value of drm_file.master changes only when both
    drm_device.master_mutex and drm_file.master_lookup_lock are
    held. Hence, any process holding either of those locks can ensure that
    the value of drm_file.master will not change concurrently.
    
    Since no lock depends on the new drm_file.master_lookup_lock, when
    drm_file.master is dereferenced, but drm_device.master_mutex cannot be
    held, we can safely protect the master pointer with
    drm_file.master_lookup_lock.
    Reported-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
    Signed-off-by: default avatarDesmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
    Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
    Link: https://patchwork.freedesktop.org/patch/msgid/20210712043508.11584-5-desmondcheongzx@gmail.com
    0b0860a3
drm_file.c 30.3 KB