From d77db6646cabdbd3c6812c9d1e1136b3c3fa0f7b Mon Sep 17 00:00:00 2001 From: Denis Kirjanov Date: Apr 05 2022 12:47:31 +0000 Subject: Merge remote-tracking branch 'origin/users/tiwai/SLE15-SP3/bsc1197914' into SLE15-SP3_EMBARGO --- diff --git a/patches.kabi/drm-drm_file-kabi-workaround.patch b/patches.kabi/drm-drm_file-kabi-workaround.patch new file mode 100644 index 0000000..23f06af --- /dev/null +++ b/patches.kabi/drm-drm_file-kabi-workaround.patch @@ -0,0 +1,41 @@ +From: Takashi Iwai +Subject: drm: drm_file struct kABI compatibility workaround +Patch-mainline: Never, kABI workaround +References: bsc#1197914 + +The recent fix for DRM core + patches.suse/drm-serialize-drm_file.master-with-a-new-spinlock.patch +introduced a new field in struct drm_file. +Apply the standard workaround to move it at the tail with __GENKSYMS__ +for keeping the kABI compatibility; drm_file isn't embedded, so it +should be safe to do that. + +Signed-off-by: Takashi Iwai + +--- + include/drm/drm_file.h | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/include/drm/drm_file.h ++++ b/include/drm/drm_file.h +@@ -244,9 +244,6 @@ struct drm_file { + */ + struct drm_master *master; + +- /** @master_lock: Serializes @master. */ +- spinlock_t master_lookup_lock; +- + /** @pid: Process that opened this file. */ + struct pid *pid; + +@@ -362,6 +359,10 @@ struct drm_file { + #if IS_ENABLED(CONFIG_DRM_LEGACY) + unsigned long lock_count; /* DRI1 legacy lock count */ + #endif ++#ifndef __GENKSYMS__ ++ /** @master_lock: Serializes @master. */ ++ spinlock_t master_lookup_lock; ++#endif + }; + + /** diff --git a/patches.suse/drm-add-a-locked-version-of-drm_is_current_master-1f7ef07cfa14.patch b/patches.suse/drm-add-a-locked-version-of-drm_is_current_master-1f7ef07cfa14.patch new file mode 100644 index 0000000..f88afcd --- /dev/null +++ b/patches.suse/drm-add-a-locked-version-of-drm_is_current_master-1f7ef07cfa14.patch @@ -0,0 +1,120 @@ +From 1f7ef07cfa14fb8557d1f1b7a14c76926142a4fb Mon Sep 17 00:00:00 2001 +From: Desmond Cheong Zhi Xi +Date: Mon, 12 Jul 2021 12:35:06 +0800 +Subject: [PATCH] drm: add a locked version of drm_is_current_master +Git-commit: 1f7ef07cfa14fb8557d1f1b7a14c76926142a4fb +Patch-mainline: v5.15-rc1 +References: bsc#1197914 + +While checking the master status of the DRM file in +drm_is_current_master(), the device's master mutex should be +held. Without the mutex, the pointer fpriv->master may be freed +concurrently by another process calling drm_setmaster_ioctl(). This +could lead to use-after-free errors when the pointer is subsequently +dereferenced in drm_lease_owner(). + +The callers of drm_is_current_master() from drm_auth.c hold the +device's master mutex, but external callers do not. Hence, we implement +drm_is_current_master_locked() to be used within drm_auth.c, and +modify drm_is_current_master() to grab the device's master mutex +before checking the master status. + +Reported-by: Daniel Vetter +Signed-off-by: Desmond Cheong Zhi Xi +Reviewed-by: Emil Velikov +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20210712043508.11584-4-desmondcheongzx@gmail.com +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/drm_auth.c | 51 ++++++++++++++++++++++++++++----------------- + 1 file changed, 32 insertions(+), 19 deletions(-) + +--- a/drivers/gpu/drm/drm_auth.c ++++ b/drivers/gpu/drm/drm_auth.c +@@ -61,6 +61,35 @@ + * trusted clients. + */ + ++static bool drm_is_current_master_locked(struct drm_file *fpriv) ++{ ++ lockdep_assert_held_once(&fpriv->minor->dev->master_mutex); ++ ++ return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master; ++} ++ ++/** ++ * drm_is_current_master - checks whether @priv is the current master ++ * @fpriv: DRM file private ++ * ++ * Checks whether @fpriv is current master on its device. This decides whether a ++ * client is allowed to run DRM_MASTER IOCTLs. ++ * ++ * Most of the modern IOCTL which require DRM_MASTER are for kernel modesetting ++ * - the current master is assumed to own the non-shareable display hardware. ++ */ ++bool drm_is_current_master(struct drm_file *fpriv) ++{ ++ bool ret; ++ ++ mutex_lock(&fpriv->minor->dev->master_mutex); ++ ret = drm_is_current_master_locked(fpriv); ++ mutex_unlock(&fpriv->minor->dev->master_mutex); ++ ++ return ret; ++} ++EXPORT_SYMBOL(drm_is_current_master); ++ + int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) + { + struct drm_auth *auth = data; +@@ -223,7 +252,7 @@ int drm_setmaster_ioctl(struct drm_devic + if (ret) + goto out_unlock; + +- if (drm_is_current_master(file_priv)) ++ if (drm_is_current_master_locked(file_priv)) + goto out_unlock; + + if (dev->master) { +@@ -272,7 +301,7 @@ int drm_dropmaster_ioctl(struct drm_devi + if (ret) + goto out_unlock; + +- if (!drm_is_current_master(file_priv)) { ++ if (!drm_is_current_master_locked(file_priv)) { + ret = -EINVAL; + goto out_unlock; + } +@@ -321,7 +350,7 @@ void drm_master_release(struct drm_file + if (file_priv->magic) + idr_remove(&file_priv->master->magic_map, file_priv->magic); + +- if (!drm_is_current_master(file_priv)) ++ if (!drm_is_current_master_locked(file_priv)) + goto out; + + drm_legacy_lock_master_cleanup(dev, master); +@@ -343,22 +372,6 @@ out: + } + + /** +- * drm_is_current_master - checks whether @priv is the current master +- * @fpriv: DRM file private +- * +- * Checks whether @fpriv is current master on its device. This decides whether a +- * client is allowed to run DRM_MASTER IOCTLs. +- * +- * Most of the modern IOCTL which require DRM_MASTER are for kernel modesetting +- * - the current master is assumed to own the non-shareable display hardware. +- */ +-bool drm_is_current_master(struct drm_file *fpriv) +-{ +- return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master; +-} +-EXPORT_SYMBOL(drm_is_current_master); +- +-/** + * drm_master_get - reference a master pointer + * @master: &struct drm_master + * diff --git a/patches.suse/drm-protect-drm_master-pointers-in-drm_lease.c.patch b/patches.suse/drm-protect-drm_master-pointers-in-drm_lease.c.patch new file mode 100644 index 0000000..6838a7f --- /dev/null +++ b/patches.suse/drm-protect-drm_master-pointers-in-drm_lease.c.patch @@ -0,0 +1,337 @@ +From 56f0729a510f92151682ff6c89f69724d5595d6e Mon Sep 17 00:00:00 2001 +From: Desmond Cheong Zhi Xi +Date: Mon, 12 Jul 2021 12:35:08 +0800 +Subject: [PATCH] drm: protect drm_master pointers in drm_lease.c +Git-commit: 56f0729a510f92151682ff6c89f69724d5595d6e +Patch-mainline: v5.15-rc1 +References: bsc#1197914 + +drm_file->master pointers should be protected by +drm_device.master_mutex or drm_file.master_lookup_lock when being +dereferenced. + +However, in drm_lease.c, there are multiple instances where +drm_file->master is accessed and dereferenced while neither lock is +held. This makes drm_lease.c vulnerable to use-after-free bugs. + +We address this issue in 2 ways: + +1. Add a new drm_file_get_master() function that calls drm_master_get +on drm_file->master while holding on to +drm_file.master_lookup_lock. Since drm_master_get increments the +reference count of master, this prevents master from being freed until +we unreference it with drm_master_put. + +2. In each case where drm_file->master is directly accessed and +eventually dereferenced in drm_lease.c, we wrap the access in a call +to the new drm_file_get_master function, then unreference the master +pointer once we are done using it. + +Reported-by: Daniel Vetter +Signed-off-by: Desmond Cheong Zhi Xi +Reviewed-by: Emil Velikov +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20210712043508.11584-6-desmondcheongzx@gmail.com +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/drm_auth.c | 25 +++++++++++++ + drivers/gpu/drm/drm_lease.c | 81 +++++++++++++++++++++++++++++++++----------- + include/drm/drm_auth.h | 1 + include/drm/drm_file.h | 6 +++ + 4 files changed, 93 insertions(+), 20 deletions(-) + +--- a/drivers/gpu/drm/drm_auth.c ++++ b/drivers/gpu/drm/drm_auth.c +@@ -389,6 +389,31 @@ struct drm_master *drm_master_get(struct + } + EXPORT_SYMBOL(drm_master_get); + ++/** ++ * drm_file_get_master - reference &drm_file.master of @file_priv ++ * @file_priv: DRM file private ++ * ++ * Increments the reference count of @file_priv's &drm_file.master and returns ++ * the &drm_file.master. If @file_priv has no &drm_file.master, returns NULL. ++ * ++ * Master pointers returned from this function should be unreferenced using ++ * drm_master_put(). ++ */ ++struct drm_master *drm_file_get_master(struct drm_file *file_priv) ++{ ++ struct drm_master *master = NULL; ++ ++ spin_lock(&file_priv->master_lookup_lock); ++ if (!file_priv->master) ++ goto unlock; ++ master = drm_master_get(file_priv->master); ++ ++unlock: ++ spin_unlock(&file_priv->master_lookup_lock); ++ return master; ++} ++EXPORT_SYMBOL(drm_file_get_master); ++ + static void drm_master_destroy(struct kref *kref) + { + struct drm_master *master = container_of(kref, struct drm_master, refcount); +--- a/drivers/gpu/drm/drm_lease.c ++++ b/drivers/gpu/drm/drm_lease.c +@@ -107,10 +107,19 @@ static bool _drm_has_leased(struct drm_m + */ + bool _drm_lease_held(struct drm_file *file_priv, int id) + { +- if (!file_priv || !file_priv->master) ++ bool ret; ++ struct drm_master *master; ++ ++ if (!file_priv) + return true; + +- return _drm_lease_held_master(file_priv->master, id); ++ master = drm_file_get_master(file_priv); ++ if (!master) ++ return true; ++ ret = _drm_lease_held_master(master, id); ++ drm_master_put(&master); ++ ++ return ret; + } + + /** +@@ -129,13 +138,22 @@ bool drm_lease_held(struct drm_file *fil + struct drm_master *master; + bool ret; + +- if (!file_priv || !file_priv->master || !file_priv->master->lessor) ++ if (!file_priv) + return true; + +- master = file_priv->master; ++ master = drm_file_get_master(file_priv); ++ if (!master) ++ return true; ++ if (!master->lessor) { ++ ret = true; ++ goto out; ++ } + mutex_lock(&master->dev->mode_config.idr_mutex); + ret = _drm_lease_held_master(master, id); + mutex_unlock(&master->dev->mode_config.idr_mutex); ++ ++out: ++ drm_master_put(&master); + return ret; + } + +@@ -155,10 +173,16 @@ uint32_t drm_lease_filter_crtcs(struct d + int count_in, count_out; + uint32_t crtcs_out = 0; + +- if (!file_priv || !file_priv->master || !file_priv->master->lessor) ++ if (!file_priv) + return crtcs_in; + +- master = file_priv->master; ++ master = drm_file_get_master(file_priv); ++ if (!master) ++ return crtcs_in; ++ if (!master->lessor) { ++ crtcs_out = crtcs_in; ++ goto out; ++ } + dev = master->dev; + + count_in = count_out = 0; +@@ -177,6 +201,9 @@ uint32_t drm_lease_filter_crtcs(struct d + count_in++; + } + mutex_unlock(&master->dev->mode_config.idr_mutex); ++ ++out: ++ drm_master_put(&master); + return crtcs_out; + } + +@@ -490,7 +517,7 @@ int drm_mode_create_lease_ioctl(struct d + size_t object_count; + int ret = 0; + struct idr leases; +- struct drm_master *lessor = lessor_priv->master; ++ struct drm_master *lessor; + struct drm_master *lessee = NULL; + struct file *lessee_file = NULL; + struct file *lessor_file = lessor_priv->filp; +@@ -502,12 +529,6 @@ int drm_mode_create_lease_ioctl(struct d + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EOPNOTSUPP; + +- /* Do not allow sub-leases */ +- if (lessor->lessor) { +- DRM_DEBUG_LEASE("recursive leasing not allowed\n"); +- return -EINVAL; +- } +- + /* need some objects */ + if (cl->object_count == 0) { + DRM_DEBUG_LEASE("no objects in lease\n"); +@@ -519,12 +540,22 @@ int drm_mode_create_lease_ioctl(struct d + return -EINVAL; + } + ++ lessor = drm_file_get_master(lessor_priv); ++ /* Do not allow sub-leases */ ++ if (lessor->lessor) { ++ DRM_DEBUG_LEASE("recursive leasing not allowed\n"); ++ ret = -EINVAL; ++ goto out_lessor; ++ } ++ + object_count = cl->object_count; + + object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), + array_size(object_count, sizeof(__u32))); +- if (IS_ERR(object_ids)) +- return PTR_ERR(object_ids); ++ if (IS_ERR(object_ids)) { ++ ret = PTR_ERR(object_ids); ++ goto out_lessor; ++ } + + idr_init(&leases); + +@@ -535,14 +566,15 @@ int drm_mode_create_lease_ioctl(struct d + if (ret) { + DRM_DEBUG_LEASE("lease object lookup failed: %i\n", ret); + idr_destroy(&leases); +- return ret; ++ goto out_lessor; + } + + /* Allocate a file descriptor for the lease */ + fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK)); + if (fd < 0) { + idr_destroy(&leases); +- return fd; ++ ret = fd; ++ goto out_lessor; + } + + DRM_DEBUG_LEASE("Creating lease\n"); +@@ -578,6 +610,7 @@ int drm_mode_create_lease_ioctl(struct d + /* Hook up the fd */ + fd_install(fd, lessee_file); + ++ drm_master_put(&lessor); + DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n"); + return 0; + +@@ -587,6 +620,8 @@ out_lessee: + out_leases: + put_unused_fd(fd); + ++out_lessor: ++ drm_master_put(&lessor); + DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret); + return ret; + } +@@ -609,7 +644,7 @@ int drm_mode_list_lessees_ioctl(struct d + struct drm_mode_list_lessees *arg = data; + __u32 __user *lessee_ids = (__u32 __user *) (uintptr_t) (arg->lessees_ptr); + __u32 count_lessees = arg->count_lessees; +- struct drm_master *lessor = lessor_priv->master, *lessee; ++ struct drm_master *lessor, *lessee; + int count; + int ret = 0; + +@@ -620,6 +655,7 @@ int drm_mode_list_lessees_ioctl(struct d + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EOPNOTSUPP; + ++ lessor = drm_file_get_master(lessor_priv); + DRM_DEBUG_LEASE("List lessees for %d\n", lessor->lessee_id); + + mutex_lock(&dev->mode_config.idr_mutex); +@@ -643,6 +679,7 @@ int drm_mode_list_lessees_ioctl(struct d + arg->count_lessees = count; + + mutex_unlock(&dev->mode_config.idr_mutex); ++ drm_master_put(&lessor); + + return ret; + } +@@ -662,7 +699,7 @@ int drm_mode_get_lease_ioctl(struct drm_ + struct drm_mode_get_lease *arg = data; + __u32 __user *object_ids = (__u32 __user *) (uintptr_t) (arg->objects_ptr); + __u32 count_objects = arg->count_objects; +- struct drm_master *lessee = lessee_priv->master; ++ struct drm_master *lessee; + struct idr *object_idr; + int count; + void *entry; +@@ -676,6 +713,7 @@ int drm_mode_get_lease_ioctl(struct drm_ + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EOPNOTSUPP; + ++ lessee = drm_file_get_master(lessee_priv); + DRM_DEBUG_LEASE("get lease for %d\n", lessee->lessee_id); + + mutex_lock(&dev->mode_config.idr_mutex); +@@ -703,6 +741,7 @@ int drm_mode_get_lease_ioctl(struct drm_ + arg->count_objects = count; + + mutex_unlock(&dev->mode_config.idr_mutex); ++ drm_master_put(&lessee); + + return ret; + } +@@ -721,7 +760,7 @@ int drm_mode_revoke_lease_ioctl(struct d + void *data, struct drm_file *lessor_priv) + { + struct drm_mode_revoke_lease *arg = data; +- struct drm_master *lessor = lessor_priv->master; ++ struct drm_master *lessor; + struct drm_master *lessee; + int ret = 0; + +@@ -731,6 +770,7 @@ int drm_mode_revoke_lease_ioctl(struct d + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EOPNOTSUPP; + ++ lessor = drm_file_get_master(lessor_priv); + mutex_lock(&dev->mode_config.idr_mutex); + + lessee = _drm_find_lessee(lessor, arg->lessee_id); +@@ -751,6 +791,7 @@ int drm_mode_revoke_lease_ioctl(struct d + + fail: + mutex_unlock(&dev->mode_config.idr_mutex); ++ drm_master_put(&lessor); + + return ret; + } +--- a/include/drm/drm_auth.h ++++ b/include/drm/drm_auth.h +@@ -107,6 +107,7 @@ struct drm_master { + }; + + struct drm_master *drm_master_get(struct drm_master *master); ++struct drm_master *drm_file_get_master(struct drm_file *file_priv); + void drm_master_put(struct drm_master **master); + bool drm_is_current_master(struct drm_file *fpriv); + +--- a/include/drm/drm_file.h ++++ b/include/drm/drm_file.h +@@ -233,6 +233,12 @@ struct drm_file { + * this only matches &drm_device.master if the master is the currently + * active one. + * ++ * When dereferencing this pointer, either hold struct ++ * &drm_device.master_mutex for the duration of the pointer's use, or ++ * use drm_file_get_master() if struct &drm_device.master_mutex is not ++ * currently held and there is no other need to hold it. This prevents ++ * @master from being freed during use. ++ * + * See also @authentication and @is_master and the :ref:`section on + * primary nodes and authentication `. + */ diff --git a/patches.suse/drm-serialize-drm_file.master-with-a-new-spinlock.patch b/patches.suse/drm-serialize-drm_file.master-with-a-new-spinlock.patch new file mode 100644 index 0000000..c795849 --- /dev/null +++ b/patches.suse/drm-serialize-drm_file.master-with-a-new-spinlock.patch @@ -0,0 +1,128 @@ +From 0b0860a3cf5eccf183760b1177a1dcdb821b0b66 Mon Sep 17 00:00:00 2001 +From: Desmond Cheong Zhi Xi +Date: Mon, 12 Jul 2021 12:35:07 +0800 +Subject: [PATCH] drm: serialize drm_file.master with a new spinlock +Git-commit: 0b0860a3cf5eccf183760b1177a1dcdb821b0b66 +Patch-mainline: v5.15-rc1 +References: bsc#1197914 + +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: Daniel Vetter +Signed-off-by: Desmond Cheong Zhi Xi +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20210712043508.11584-5-desmondcheongzx@gmail.com +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/drm_auth.c | 17 +++++++++++------ + drivers/gpu/drm/drm_file.c | 1 + + include/drm/drm_file.h | 12 +++++++++--- + 3 files changed, 21 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/drm_auth.c ++++ b/drivers/gpu/drm/drm_auth.c +@@ -164,16 +164,18 @@ static void drm_set_master(struct drm_de + static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv) + { + struct drm_master *old_master; ++ struct drm_master *new_master; + + lockdep_assert_held_once(&dev->master_mutex); + + WARN_ON(fpriv->is_master); + old_master = fpriv->master; +- fpriv->master = drm_master_create(dev); +- if (!fpriv->master) { +- fpriv->master = old_master; ++ new_master = drm_master_create(dev); ++ if (!new_master) + return -ENOMEM; +- } ++ spin_lock(&fpriv->master_lookup_lock); ++ fpriv->master = new_master; ++ spin_unlock(&fpriv->master_lookup_lock); + + fpriv->is_master = 1; + fpriv->authenticated = 1; +@@ -331,10 +333,13 @@ int drm_master_open(struct drm_file *fil + /* if there is no current master make this fd it, but do not create + * any master object for render clients */ + mutex_lock(&dev->master_mutex); +- if (!dev->master) ++ if (!dev->master) { + ret = drm_new_set_master(dev, file_priv); +- else ++ } else { ++ spin_lock(&file_priv->master_lookup_lock); + file_priv->master = drm_master_get(dev->master); ++ spin_unlock(&file_priv->master_lookup_lock); ++ } + mutex_unlock(&dev->master_mutex); + + return ret; +--- a/drivers/gpu/drm/drm_file.c ++++ b/drivers/gpu/drm/drm_file.c +@@ -177,6 +177,7 @@ struct drm_file *drm_file_alloc(struct d + init_waitqueue_head(&file->event_wait); + file->event_space = 4096; /* set aside 4k for event buffer */ + ++ spin_lock_init(&file->master_lookup_lock); + mutex_init(&file->event_read_lock); + + if (drm_core_check_feature(dev, DRIVER_GEM)) +--- a/include/drm/drm_file.h ++++ b/include/drm/drm_file.h +@@ -226,15 +226,21 @@ struct drm_file { + /** + * @master: + * +- * Master this node is currently associated with. Only relevant if +- * drm_is_primary_client() returns true. Note that this only +- * matches &drm_device.master if the master is the currently active one. ++ * Master this node is currently associated with. Protected by struct ++ * &drm_device.master_mutex, and serialized by @master_lookup_lock. ++ * ++ * Only relevant if drm_is_primary_client() returns true. Note that ++ * this only matches &drm_device.master if the master is the currently ++ * active one. + * + * See also @authentication and @is_master and the :ref:`section on + * primary nodes and authentication `. + */ + struct drm_master *master; + ++ /** @master_lock: Serializes @master. */ ++ spinlock_t master_lookup_lock; ++ + /** @pid: Process that opened this file. */ + struct pid *pid; + diff --git a/patches.suse/drm-use-the-lookup-lock-in-drm_is_current_master.patch b/patches.suse/drm-use-the-lookup-lock-in-drm_is_current_master.patch new file mode 100644 index 0000000..9ad0749 --- /dev/null +++ b/patches.suse/drm-use-the-lookup-lock-in-drm_is_current_master.patch @@ -0,0 +1,51 @@ +From 28be2405fb753927e18bc1a891617a430b2a0684 Mon Sep 17 00:00:00 2001 +From: Desmond Cheong Zhi Xi +Date: Sat, 24 Jul 2021 19:18:22 +0800 +Subject: [PATCH] drm: use the lookup lock in drm_is_current_master +Git-commit: 28be2405fb753927e18bc1a891617a430b2a0684 +Patch-mainline: v5.15-rc1 +References: bsc#1197914 + +Inside drm_is_current_master, using the outer drm_device.master_mutex +to protect reads of drm_file.master makes the function prone to creating +lock hierarchy inversions. Instead, we can use the +drm_file.master_lookup_lock that sits at the bottom of the lock +hierarchy. + +Reported-by: Daniel Vetter +Signed-off-by: Desmond Cheong Zhi Xi +Reviewed-by: Daniel Vetter +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20210724111824.59266-2-desmondcheongzx@gmail.com +Acked-by: Takashi Iwai + +--- + drivers/gpu/drm/drm_auth.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/drm_auth.c ++++ b/drivers/gpu/drm/drm_auth.c +@@ -63,8 +63,9 @@ + + static bool drm_is_current_master_locked(struct drm_file *fpriv) + { +- lockdep_assert_held_once(&fpriv->minor->dev->master_mutex); +- ++ /* Either drm_device.master_mutex or drm_file.master_lookup_lock ++ * should be held here. ++ */ + return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master; + } + +@@ -82,9 +83,9 @@ bool drm_is_current_master(struct drm_fi + { + bool ret; + +- mutex_lock(&fpriv->minor->dev->master_mutex); ++ spin_lock(&fpriv->master_lookup_lock); + ret = drm_is_current_master_locked(fpriv); +- mutex_unlock(&fpriv->minor->dev->master_mutex); ++ spin_unlock(&fpriv->master_lookup_lock); + + return ret; + } diff --git a/series.conf b/series.conf index de4de92..f30be3e 100644 --- a/series.conf +++ b/series.conf @@ -52463,12 +52463,16 @@ patches.suse/drm-of-free-the-iterator-object-on-failure.patch patches.suse/video-fbdev-kyro-fix-a-DoS-bug-by-restricting-user-i.patch patches.suse/drm-avoid-blocking-in-drm_clients_info-s-rcu-section.patch + patches.suse/drm-add-a-locked-version-of-drm_is_current_master-1f7ef07cfa14.patch + patches.suse/drm-serialize-drm_file.master-with-a-new-spinlock.patch + patches.suse/drm-protect-drm_master-pointers-in-drm_lease.c.patch patches.suse/drm-bridge-nwl-dsi-Avoid-potential-multiplication-ov.patch patches.suse/video-fbdev-asiliantfb-Error-out-if-pixclock-equals-.patch patches.suse/video-fbdev-kyro-Error-out-if-pixclock-equals-zero.patch patches.suse/video-fbdev-riva-Error-out-if-pixclock-equals-zero.patch patches.suse/drm-prime-fix-comment-on-PRIME-Helpers.patch patches.suse/drm-dp_mst-Fix-return-code-on-sideband-message-failu.patch + patches.suse/drm-use-the-lookup-lock-in-drm_is_current_master.patch patches.suse/drm-amdgpu-Fix-amdgpu_ras_eeprom_init.patch patches.suse/drm-amd-display-Fix-timer_per_pixel-unit-error.patch patches.suse/drm-amdgpu-Fix-a-printing-message.patch @@ -55330,6 +55334,7 @@ patches.kabi/fuse-handle-kabi-change-in-struct-fuse_args.patch patches.kabi/ALSA-kABI-workaround-for-snd_pcm_runtime-changes.patch patches.kabi/net-ax25_dev-kabi-workaround.patch + patches.kabi/drm-drm_file-kabi-workaround.patch ######################################################## # You'd better have a good reason for adding a patch