2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00
linux/include/drm
Simona Vetter bd46cece51 drm/gem: Fix race in drm_gem_handle_create_tail()
Object creation is a careful dance where we must guarantee that the
object is fully constructed before it is visible to other threads, and
GEM buffer objects are no difference.

Final publishing happens by calling drm_gem_handle_create(). After
that the only allowed thing to do is call drm_gem_object_put() because
a concurrent call to the GEM_CLOSE ioctl with a correctly guessed id
(which is trivial since we have a linear allocator) can already tear
down the object again.

Luckily most drivers get this right, the very few exceptions I've
pinged the relevant maintainers for. Unfortunately we also need
drm_gem_handle_create() when creating additional handles for an
already existing object (e.g. GETFB ioctl or the various bo import
ioctl), and hence we cannot have a drm_gem_handle_create_and_put() as
the only exported function to stop these issues from happening.

Now unfortunately the implementation of drm_gem_handle_create() isn't
living up to standards: It does correctly finishe object
initialization at the global level, and hence is safe against a
concurrent tear down. But it also sets up the file-private aspects of
the handle, and that part goes wrong: We fully register the object in
the drm_file.object_idr before calling drm_vma_node_allow() or
obj->funcs->open, which opens up races against concurrent removal of
that handle in drm_gem_handle_delete().

Fix this with the usual two-stage approach of first reserving the
handle id, and then only registering the object after we've completed
the file-private setup.

Jacek reported this with a testcase of concurrently calling GEM_CLOSE
on a freshly-created object (which also destroys the object), but it
should be possible to hit this with just additional handles created
through import or GETFB without completed destroying the underlying
object with the concurrent GEM_CLOSE ioctl calls.

Note that the close-side of this race was fixed in f6cd7daecf ("drm:
Release driver references to handle before making it available
again"), which means a cool 9 years have passed until someone noticed
that we need to make this symmetry or there's still gaps left :-/
Without the 2-stage close approach we'd still have a race, therefore
that's an integral part of this bugfix.

More importantly, this means we can have NULL pointers behind
allocated id in our drm_file.object_idr. We need to check for that
now:

- drm_gem_handle_delete() checks for ERR_OR_NULL already

- drm_gem.c:object_lookup() also chekcs for NULL

- drm_gem_release() should never be called if there's another thread
  still existing that could call into an IOCTL that creates a new
  handle, so cannot race. For paranoia I added a NULL check to
  drm_gem_object_release_handle() though.

- most drivers (etnaviv, i915, msm) are find because they use
  idr_find(), which maps both ENOENT and NULL to NULL.

- drivers using idr_for_each_entry() should also be fine, because
  idr_get_next does filter out NULL entries and continues the
  iteration.

- The same holds for drm_show_memory_stats().

v2: Use drm_WARN_ON (Thomas)

Reported-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Tested-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Cc: stable@vger.kernel.org
Cc: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@gmail.com>
Cc: Simona Vetter <simona@ffwll.ch>
Signed-off-by: Simona Vetter <simona.vetter@intel.com>
Signed-off-by: Simona Vetter <simona.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20250707151814.603897-1-simona.vetter@ffwll.ch
2025-07-09 15:53:34 +02:00
..
bridge drm/bridge: analogix_dp: Add support for RK3588 2025-04-21 01:27:10 +03:00
clients drm/client: Move public client header to clients/ subdirectory 2024-11-15 09:42:13 +01:00
display drm/dp: add option to disable zero sized address only transactions. 2025-05-19 07:14:45 +10:00
intel drm for 6.16-rc1 2025-05-28 09:46:39 -07:00
ttm drm for 6.16-rc1 2025-05-28 09:46:39 -07:00
amd_asic_type.h drm/amdgpu: make amd_asic_type.h self-contained 2024-03-07 17:17:25 +02:00
drm_accel.h drm next for 6.12-rc1 2024-09-19 10:18:15 +02:00
drm_atomic_helper.h drm/atomic-helper: Introduce drm_atomic_helper_reset_crtc() 2025-02-13 16:17:46 +01:00
drm_atomic_state_helper.h
drm_atomic_uapi.h
drm_atomic.h drm/atomic: Introduce helper to lookup connector by encoder 2025-03-20 14:45:46 +01:00
drm_audio_component.h
drm_auth.h drm: Remove source code for non-KMS drivers 2023-12-06 10:08:37 +01:00
drm_blend.h Revert "drm: Introduce pixel_source DRM plane property" 2023-12-04 21:33:10 +02:00
drm_bridge_connector.h
drm_bridge_helper.h drm/bridge: Add helper to reset bridge pipeline 2025-03-20 14:45:48 +01:00
drm_bridge.h drm/bridge: add function interface for DisplayPort audio implementation 2025-04-07 15:49:17 +03:00
drm_buddy.h drm/buddy: Add start address support to trim function 2024-08-07 18:19:00 -04:00
drm_cache.h
drm_client_event.h drm/client: include types.h to make drm_client_event.h self-contained 2025-02-12 10:44:43 +02:00
drm_client.h drm/client: Send pending hotplug events after resume 2025-03-05 21:48:49 +01:00
drm_color_mgmt.h drm: using mul_u32_u32() requires linux/math64.h 2023-12-19 15:29:17 +02:00
drm_connector.h drm/display/hdmi: implement hotplug functions 2025-01-04 08:47:11 +02:00
drm_crtc_helper.h
drm_crtc.h drm: add clone mode check for CRTC 2025-01-08 01:39:58 +02:00
drm_damage_helper.h drm/damage-helper: add const qualifier in drm_atomic_helper_damage_merged() 2025-03-03 14:45:40 +02:00
drm_debugfs_crc.h drm/crc: make drm_debugfs_crc.h self-contained and fix kernel-doc 2024-03-07 17:17:25 +02:00
drm_debugfs.h drm/gpuvm: rename struct drm_gpuva_manager to struct drm_gpuvm 2023-09-26 01:51:28 +02:00
drm_device.h drm/prime: Support dedicated DMA device for dma-buf imports 2025-03-12 09:03:46 +01:00
drm_drv.h drm: drv: implement __drm_dev_alloc() 2025-04-24 13:50:03 +02:00
drm_edid.h drm/edid: Use unsigned int in drm_add_modes_noedid() 2025-04-02 17:19:54 -04:00
drm_eld.h drm/eld: add helpers to modify the SADs of an ELD 2023-11-09 16:48:27 +02:00
drm_encoder.h drm/encoder: register per-encoder debugfs dir 2023-12-04 16:07:29 +02:00
drm_exec.h Merge drm/drm-next into drm-misc-next 2024-01-29 14:20:23 +01:00
drm_fb_dma_helper.h drm/fb_dma: s/drm_panic_gem_get_scanout_buffer/drm_fb_dma_get_scanout_buffer 2024-04-15 13:50:40 -03:00
drm_fb_helper.h drm/fb-helper: Remove struct drm_fb_helper.fb_probe 2025-03-05 21:48:50 +01:00
drm_fbdev_dma.h drm/fbdev-dma: Remove obsolete setup function 2024-09-26 09:31:27 +02:00
drm_fbdev_shmem.h drm/fbdev-shmem: Remove obsolete setup function 2024-09-26 09:31:28 +02:00
drm_fbdev_ttm.h drm/fbdev-ttm: Remove obsolete setup function 2024-09-26 09:31:29 +02:00
drm_file.h drm/gem: Fix race in drm_gem_handle_create_tail() 2025-07-09 15:53:34 +02:00
drm_fixed.h drm: fixed: Don't use "proxy" headers 2024-08-13 12:13:45 +03:00
drm_flip_work.h drm: Fix flip-task docs 2023-11-14 10:23:12 +01:00
drm_format_helper.h drm/format-helper: Add conversion from XRGB8888 to BGR888 2025-03-03 16:13:33 +01:00
drm_fourcc.h drm/fbdev-helper: Move color-mode lookup into 4CC format helper 2024-09-26 08:27:49 +02:00
drm_framebuffer.h drm/framebuffer: Acquire internal references on GEM handles 2025-07-09 14:03:28 +02:00
drm_gem_atomic_helper.h drm/atomic-helper: Add format-conversion state to shadow-plane state 2023-11-14 10:01:14 +01:00
drm_gem_dma_helper.h fs: move FMODE_UNSIGNED_OFFSET to fop_flags 2024-08-30 08:22:36 +02:00
drm_gem_framebuffer_helper.h
drm_gem_shmem_helper.h drm/shmem-helper: Use refcount_t for vmap_use_count 2025-03-26 23:00:22 +03:00
drm_gem_ttm_helper.h
drm_gem_vram_helper.h drm/gem-vram: Remove support for simple display pipelines 2024-09-06 14:41:38 +02:00
drm_gem.h Linux 6.15-rc5 2025-05-06 16:39:25 +10:00
drm_gpusvm.h drm/gpusvm: Add timeslicing support to GPU SVM 2025-05-14 09:03:29 -07:00
drm_gpuvm.h drm/gpuvm: Add DRM_GPUVA_OP_DRIVER 2025-03-06 11:35:42 -08:00
drm_ioctl.h drm: Remove locking for legacy ioctls and DRM_UNLOCKED 2023-12-06 10:08:32 +01:00
drm_kunit_helpers.h Merge tag 'drm-misc-next-2025-04-09' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next 2025-04-14 15:29:49 +10:00
drm_lease.h drm/lease: make drm_lease.h self-contained 2024-03-07 17:17:25 +02:00
drm_managed.h drm/managed: Add DRM-managed alloc_ordered_workqueue 2025-01-21 10:32:31 +01:00
drm_mipi_dbi.h drm/mipi-dbi: Add support for DRM_FORMAT_RGB888 2024-06-07 16:09:05 +02:00
drm_mipi_dsi.h drm/mipi-dsi: Add dev_is_mipi_dsi function 2025-06-27 11:22:39 +02:00
drm_mm.h drm/mm: Remove unused drm_mm_replace_node 2024-06-06 10:24:13 -04:00
drm_mode_config.h drm/plane: Add new plane property IN_FORMATS_ASYNC 2025-05-09 15:29:40 +05:30
drm_mode_object.h drm/drm_mode_object: fix typo in kerneldoc 2025-02-04 14:11:14 +01:00
drm_modes.h drm: Move drm_set_preferred_mode() helper from drm_edid to drm_modes 2024-01-05 21:14:46 +01:00
drm_modeset_helper_vtables.h drm/atomic: Let drivers decide which planes to async flip 2025-02-14 00:54:29 +02:00
drm_modeset_helper.h
drm_modeset_lock.h
drm_module.h
drm_of.h drm: of: Add drm_of_lvds_get_dual_link_pixel_order_sink() 2024-11-05 13:26:42 +02:00
drm_pagemap.h drm/pagemap: Add DRM pagemap 2025-03-06 11:35:25 -08:00
drm_panel.h drm/panel: make prepare/enable and disable/unprepare calls return void 2025-04-22 16:49:11 +03:00
drm_panic.h drm/panic: Add support to scanout buffer as array of pages 2025-04-10 10:50:58 +02:00
drm_pciids.h
drm_plane_helper.h drm/plane-helper: Move drm_plane_helper_atomic_check() into udl 2023-12-06 10:35:49 +01:00
drm_plane.h drm/plane: Add new plane property IN_FORMATS_ASYNC 2025-05-09 15:29:40 +05:30
drm_prime.h drm: new helper: drm_gem_prime_handle_to_dmabuf() 2024-09-10 13:44:30 -04:00
drm_print.h drm/print: Add drm_coredump_printer_is_full 2025-04-24 15:51:41 -07:00
drm_privacy_screen_consumer.h
drm_privacy_screen_driver.h
drm_privacy_screen_machine.h
drm_probe_helper.h drm/probe-helper: Do not fail from drmm_kms_helper_poll_init() 2025-03-24 09:31:03 +01:00
drm_property.h drm/drm_property: make replace_property_blob_from_id a DRM helper 2023-12-13 15:09:53 -05:00
drm_rect.h drm/rect: Add drm_rect_overlap() 2024-08-23 16:47:56 +02:00
drm_self_refresh_helper.h
drm_simple_kms_helper.h
drm_suballoc.h drm/suballoc: fix drm_suballoc.h kernel-doc 2024-03-07 17:17:25 +02:00
drm_syncobj.h drm/syncobj: add IOCTL to register an eventfd 2023-07-20 12:01:03 +02:00
drm_sysfs.h drm/sysfs: rename drm_sysfs_connector_status_event() 2023-06-23 15:54:00 +02:00
drm_util.h drm: Move for_each_if() to util_macros.h for wider use 2025-02-17 14:27:35 +01:00
drm_utils.h drm: Add panel backlight quirks 2024-11-21 09:28:11 -06:00
drm_vblank_work.h drm: Add drm_vblank_work_flush_all(). 2024-06-24 18:03:18 +02:00
drm_vblank.h drm/vblank: add dynamic per-crtc vblank configuration support 2024-07-26 17:40:10 -04:00
drm_vma_manager.h
drm_writeback.h drm: writeback: Create drmm variants for drm_writeback_connector initialization 2025-01-21 10:32:33 +01:00
gpu_scheduler.h drm/sched: Update timedout_job()'s documentation 2025-03-06 16:36:32 +01:00
gud.h
Makefile scripts/kernel-doc.py: don't create *.pyc files 2025-04-24 10:12:46 -06:00
spsc_queue.h drm/sched: Increment job count before swapping tail spsc queue 2025-07-01 16:14:47 -07:00
task_barrier.h drm: Spelling s/randevouz/rendez-vous/ 2023-07-29 21:11:54 +02:00