summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2023-07-26 11:06:52 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2023-07-26 11:06:52 +0000
commitee092654a1a1d812ffb6e6560a87b3fb63da3eba (patch)
tree589131e7970f2e8168b64616f2b9428dad07dbff /sys
parentf5a8620687b4f50c52e5895ddc49cef2d4d1a82d (diff)
drm/atomic: Fix potential use-after-free in nonblocking commits
From Daniel Vetter e4a0e09b79bd2c0895c508cdc5e0265a083cc05d in linux-6.1.y/6.1.40 4e076c73e4f6e90816b30fcd4a0d7ab365087255 in mainline linux
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/drm/drm_atomic.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/sys/dev/pci/drm/drm_atomic.c b/sys/dev/pci/drm/drm_atomic.c
index 5b1afb8f161..b876b2dc755 100644
--- a/sys/dev/pci/drm/drm_atomic.c
+++ b/sys/dev/pci/drm/drm_atomic.c
@@ -140,6 +140,12 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
if (!state->planes)
goto fail;
+ /*
+ * Because drm_atomic_state can be committed asynchronously we need our
+ * own reference and cannot rely on the on implied by drm_file in the
+ * ioctl call.
+ */
+ drm_dev_get(dev);
state->dev = dev;
drm_dbg_atomic(dev, "Allocated atomic state %p\n", state);
@@ -299,7 +305,8 @@ EXPORT_SYMBOL(drm_atomic_state_clear);
void __drm_atomic_state_free(struct kref *ref)
{
struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
- struct drm_mode_config *config = &state->dev->mode_config;
+ struct drm_device *dev = state->dev;
+ struct drm_mode_config *config = &dev->mode_config;
drm_atomic_state_clear(state);
@@ -311,6 +318,8 @@ void __drm_atomic_state_free(struct kref *ref)
drm_atomic_state_default_release(state);
kfree(state);
}
+
+ drm_dev_put(dev);
}
EXPORT_SYMBOL(__drm_atomic_state_free);