LKML Archive on lore.kernel.org help / color / mirror / Atom feed
* [PATCH 0/3] drm, drm/vmwgfx: fixes and updates related to drm_master @ 2021-07-22 9:29 Desmond Cheong Zhi Xi 2021-07-22 9:29 ` [PATCH 1/3] drm: use the lookup lock in drm_is_current_master Desmond Cheong Zhi Xi ` (2 more replies) 0 siblings, 3 replies; 18+ messages in thread From: Desmond Cheong Zhi Xi @ 2021-07-22 9:29 UTC (permalink / raw) To: linux-graphics-maintainer, zackr, airlied, daniel, maarten.lankhorst, mripard, tzimmermann Cc: Desmond Cheong Zhi Xi, dri-devel, linux-kernel, intel-gfx, skhan, gregkh, linux-kernel-mentees Hi, This series contains some improvements that Daniel Vetter proposed following a discussion on a recent series: https://lore.kernel.org/lkml/20210712043508.11584-1-desmondcheongzx@gmail.com/ While preparing these patches, I also noticed some unprotected uses of drm_master in the vmwgfx driver that can be addressed by new functions from the previous series. This series is thus broken up into three patches: 1. Switch from the outer drm_device.master_mutex to the inner drm_file.master_lookup_lock in drm_is_current_master. 2. Update the kerneldoc for lease fields in drm_master to clarify lifetime/locking rules. 3. Prevent potential use-after-free bugs by replacing calls to drm_master_get with drm_file_get_master in vmwgfx_surface.c. Best wishes, Desmond Desmond Cheong Zhi Xi (3): drm: use the lookup lock in drm_is_current_master drm: clarify lifetime/locking for drm_master's lease fields drm/vmwgfx: fix potential UAF in vmwgfx_surface.c drivers/gpu/drm/drm_auth.c | 9 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 4 +- include/drm/drm_auth.h | 62 ++++++++++++++++++++----- 3 files changed, 58 insertions(+), 17 deletions(-) -- 2.25.1 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 1/3] drm: use the lookup lock in drm_is_current_master 2021-07-22 9:29 [PATCH 0/3] drm, drm/vmwgfx: fixes and updates related to drm_master Desmond Cheong Zhi Xi @ 2021-07-22 9:29 ` Desmond Cheong Zhi Xi 2021-07-22 10:38 ` Daniel Vetter 2021-07-22 9:29 ` [PATCH 2/3] drm: clarify lifetime/locking for drm_master's lease fields Desmond Cheong Zhi Xi 2021-07-22 9:29 ` [PATCH 3/3] drm/vmwgfx: fix potential UAF in vmwgfx_surface.c Desmond Cheong Zhi Xi 2 siblings, 1 reply; 18+ messages in thread From: Desmond Cheong Zhi Xi @ 2021-07-22 9:29 UTC (permalink / raw) To: linux-graphics-maintainer, zackr, airlied, daniel, maarten.lankhorst, mripard, tzimmermann Cc: Desmond Cheong Zhi Xi, dri-devel, linux-kernel, intel-gfx, skhan, gregkh, linux-kernel-mentees, Daniel Vetter 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 <daniel.vetter@ffwll.ch> Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> --- drivers/gpu/drm/drm_auth.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index f00354bec3fb..9c24b8cc8e36 100644 --- 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_file *fpriv) { 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; } -- 2.25.1 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] drm: use the lookup lock in drm_is_current_master 2021-07-22 9:29 ` [PATCH 1/3] drm: use the lookup lock in drm_is_current_master Desmond Cheong Zhi Xi @ 2021-07-22 10:38 ` Daniel Vetter 2021-07-22 15:04 ` Boqun Feng 2021-07-27 14:37 ` Peter Zijlstra 0 siblings, 2 replies; 18+ messages in thread From: Daniel Vetter @ 2021-07-22 10:38 UTC (permalink / raw) To: Desmond Cheong Zhi Xi, Boqun Feng, LKML, Peter Zijlstra Cc: linux-graphics-maintainer, zackr, airlied, daniel, maarten.lankhorst, mripard, tzimmermann, dri-devel, linux-kernel, intel-gfx, skhan, gregkh, linux-kernel-mentees, Daniel Vetter On Thu, Jul 22, 2021 at 05:29:27PM +0800, Desmond Cheong Zhi Xi wrote: > 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 <daniel.vetter@ffwll.ch> > Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> > --- > drivers/gpu/drm/drm_auth.c | 9 +++++---- > 1 file changed, 5 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c > index f00354bec3fb..9c24b8cc8e36 100644 > --- 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. > + */ Disappointing that lockdep can't check or conditions for us, a lockdep_assert_held_either would be really neat in some cases. Adding lockdep folks, maybe they have ideas. On the patch: Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> > return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master; > } > > @@ -82,9 +83,9 @@ bool drm_is_current_master(struct drm_file *fpriv) > { > 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; > } > -- > 2.25.1 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] drm: use the lookup lock in drm_is_current_master 2021-07-22 10:38 ` Daniel Vetter @ 2021-07-22 15:04 ` Boqun Feng 2021-07-22 19:02 ` Daniel Vetter 2021-07-27 14:37 ` Peter Zijlstra 1 sibling, 1 reply; 18+ messages in thread From: Boqun Feng @ 2021-07-22 15:04 UTC (permalink / raw) To: Desmond Cheong Zhi Xi, LKML, Peter Zijlstra, linux-graphics-maintainer, zackr, airlied, maarten.lankhorst, mripard, tzimmermann, dri-devel, intel-gfx, skhan, gregkh, linux-kernel-mentees On Thu, Jul 22, 2021 at 12:38:10PM +0200, Daniel Vetter wrote: > On Thu, Jul 22, 2021 at 05:29:27PM +0800, Desmond Cheong Zhi Xi wrote: > > 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 <daniel.vetter@ffwll.ch> > > Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> > > --- > > drivers/gpu/drm/drm_auth.c | 9 +++++---- > > 1 file changed, 5 insertions(+), 4 deletions(-) > > > > diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c > > index f00354bec3fb..9c24b8cc8e36 100644 > > --- 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. > > + */ > > Disappointing that lockdep can't check or conditions for us, a > lockdep_assert_held_either would be really neat in some cases. > The implementation is not hard but I don't understand the usage, for example, if we have a global variable x, and two locks L1 and L2, and the function void do_something_to_x(void) { lockdep_assert_held_either(L1, L2); x++; } and two call sites: void f(void) { lock(L1); do_something_to_x(); unlock(L1); } void g(void) { lock(L2); do_something_to_x(); unlock(L2); } , wouldn't it be racy if f() and g() called by two threads at the same time? Usually I would expect there exists a third synchronazition mechanism (say M), which synchronizes the calls to f() and g(), and we put M in the lockdep_assert_held() check inside do_something_to_x() like: void do_something_to_x(void) { lockdep_assert_held_once(M); x++; } But of course, M may not be a lock, so we cannot put the assert there. My cscope failed to find ->master_lookup_lock in -rc2 and seems it's not introduced in the patchset either, could you point me the branch this patchset is based on, so that I could understand this better, and maybe come up with a solution? Thanks ;-) Regards, Boqun > Adding lockdep folks, maybe they have ideas. > > On the patch: > > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> > > > return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master; > > } > > > > @@ -82,9 +83,9 @@ bool drm_is_current_master(struct drm_file *fpriv) > > { > > 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; > > } > > -- > > 2.25.1 > > > > -- > Daniel Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] drm: use the lookup lock in drm_is_current_master 2021-07-22 15:04 ` Boqun Feng @ 2021-07-22 19:02 ` Daniel Vetter 2021-07-23 7:16 ` Boqun Feng 0 siblings, 1 reply; 18+ messages in thread From: Daniel Vetter @ 2021-07-22 19:02 UTC (permalink / raw) To: Boqun Feng Cc: Desmond Cheong Zhi Xi, LKML, Peter Zijlstra, VMware Graphics, Zack Rusin, Dave Airlie, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, dri-devel, intel-gfx, Shuah Khan, Greg KH, linux-kernel-mentees On Thu, Jul 22, 2021 at 6:00 PM Boqun Feng <boqun.feng@gmail.com> wrote: > > On Thu, Jul 22, 2021 at 12:38:10PM +0200, Daniel Vetter wrote: > > On Thu, Jul 22, 2021 at 05:29:27PM +0800, Desmond Cheong Zhi Xi wrote: > > > 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 <daniel.vetter@ffwll.ch> > > > Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> > > > --- > > > drivers/gpu/drm/drm_auth.c | 9 +++++---- > > > 1 file changed, 5 insertions(+), 4 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c > > > index f00354bec3fb..9c24b8cc8e36 100644 > > > --- 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. > > > + */ > > > > Disappointing that lockdep can't check or conditions for us, a > > lockdep_assert_held_either would be really neat in some cases. > > > > The implementation is not hard but I don't understand the usage, for > example, if we have a global variable x, and two locks L1 and L2, and > the function > > void do_something_to_x(void) > { > lockdep_assert_held_either(L1, L2); > x++; > } > > and two call sites: > > void f(void) > { > lock(L1); > do_something_to_x(); > unlock(L1); > } > > void g(void) > { > lock(L2); > do_something_to_x(); > unlock(L2); > } > > , wouldn't it be racy if f() and g() called by two threads at the same > time? Usually I would expect there exists a third synchronazition > mechanism (say M), which synchronizes the calls to f() and g(), and we > put M in the lockdep_assert_held() check inside do_something_to_x() > like: > > void do_something_to_x(void) > { > lockdep_assert_held_once(M); > x++; > } > > But of course, M may not be a lock, so we cannot put the assert there. > > My cscope failed to find ->master_lookup_lock in -rc2 and seems it's not > introduced in the patchset either, could you point me the branch this > patchset is based on, so that I could understand this better, and maybe > come up with a solution? Thanks ;-) The use case is essentially 2 nesting locks, and only the innermost is used to update a field. So when you only read this field, it's safe if either of these two locks are held. Essentially this is a read/write lock type of thing, except for various reasons the two locks might not be of the same type (like here where the write lock is a mutex, but the read lock is a spinlock). It's a bit like the rcu_derefence macro where it's ok to either be in a rcu_read_lock() section, or holding the relevant lock that's used to update the value. We do _not_ have two different locks that allow writing to the same X. Does that make it clearer what's the use-case here? In an example: void * interesting_pointer. do_update_interesting_pointer() { mutex_lock(A); /* do more stuff to prepare things */ spin_lock(B); interesting_pointer = new_value; spin_unlock(B); mutex_unlock(A); } read_interesting_thing_locked() { lockdep_assert_held_either(A, B); return interesting_pointer->thing; } read_interesting_thing() { int thing; spin_lock(B); thing = interesting_pointer->thing; spin_unlock(B); return B; } spinlock might also be irqsafe here if this can be called from irq context. Cheers, Daniel > Regards, > Boqun > > > Adding lockdep folks, maybe they have ideas. > > > > On the patch: > > > > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> > > > > > return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master; > > > } > > > > > > @@ -82,9 +83,9 @@ bool drm_is_current_master(struct drm_file *fpriv) > > > { > > > 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; > > > } > > > -- > > > 2.25.1 > > > > > > > -- > > Daniel Vetter > > Software Engineer, Intel Corporation > > http://blog.ffwll.ch -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] drm: use the lookup lock in drm_is_current_master 2021-07-22 19:02 ` Daniel Vetter @ 2021-07-23 7:16 ` Boqun Feng 0 siblings, 0 replies; 18+ messages in thread From: Boqun Feng @ 2021-07-23 7:16 UTC (permalink / raw) To: Desmond Cheong Zhi Xi, LKML, Peter Zijlstra, VMware Graphics, Zack Rusin, Dave Airlie, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, dri-devel, intel-gfx, Shuah Khan, Greg KH, linux-kernel-mentees On Thu, Jul 22, 2021 at 09:02:41PM +0200, Daniel Vetter wrote: > On Thu, Jul 22, 2021 at 6:00 PM Boqun Feng <boqun.feng@gmail.com> wrote: > > > > On Thu, Jul 22, 2021 at 12:38:10PM +0200, Daniel Vetter wrote: > > > On Thu, Jul 22, 2021 at 05:29:27PM +0800, Desmond Cheong Zhi Xi wrote: > > > > 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 <daniel.vetter@ffwll.ch> > > > > Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> > > > > --- > > > > drivers/gpu/drm/drm_auth.c | 9 +++++---- > > > > 1 file changed, 5 insertions(+), 4 deletions(-) > > > > > > > > diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c > > > > index f00354bec3fb..9c24b8cc8e36 100644 > > > > --- 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. > > > > + */ > > > > > > Disappointing that lockdep can't check or conditions for us, a > > > lockdep_assert_held_either would be really neat in some cases. > > > > > > > The implementation is not hard but I don't understand the usage, for > > example, if we have a global variable x, and two locks L1 and L2, and > > the function > > > > void do_something_to_x(void) > > { > > lockdep_assert_held_either(L1, L2); > > x++; > > } > > > > and two call sites: > > > > void f(void) > > { > > lock(L1); > > do_something_to_x(); > > unlock(L1); > > } > > > > void g(void) > > { > > lock(L2); > > do_something_to_x(); > > unlock(L2); > > } > > > > , wouldn't it be racy if f() and g() called by two threads at the same > > time? Usually I would expect there exists a third synchronazition > > mechanism (say M), which synchronizes the calls to f() and g(), and we > > put M in the lockdep_assert_held() check inside do_something_to_x() > > like: > > > > void do_something_to_x(void) > > { > > lockdep_assert_held_once(M); > > x++; > > } > > > > But of course, M may not be a lock, so we cannot put the assert there. > > > > My cscope failed to find ->master_lookup_lock in -rc2 and seems it's not > > introduced in the patchset either, could you point me the branch this > > patchset is based on, so that I could understand this better, and maybe > > come up with a solution? Thanks ;-) > > The use case is essentially 2 nesting locks, and only the innermost is > used to update a field. So when you only read this field, it's safe if > either of these two locks are held. Essentially this is a read/write lock > type of thing, except for various reasons the two locks might not be of > the same type (like here where the write lock is a mutex, but the read > lock is a spinlock). > > It's a bit like the rcu_derefence macro where it's ok to either be in a > rcu_read_lock() section, or holding the relevant lock that's used to > update the value. We do _not_ have two different locks that allow writing > to the same X. > > Does that make it clearer what's the use-case here? > > In an example: > > void * interesting_pointer. > > do_update_interesting_pointer() > { > mutex_lock(A); > /* do more stuff to prepare things */ > spin_lock(B); > interesting_pointer = new_value; > spin_unlock(B); > mutex_unlock(A); > } > > read_interesting_thing_locked() > { > lockdep_assert_held_either(A, B); > > return interesting_pointer->thing; > } > > read_interesting_thing() > { > int thing; > spin_lock(B); > thing = interesting_pointer->thing; > spin_unlock(B); > > return B; > } > > spinlock might also be irqsafe here if this can be called from irq > context. > Make sense, so we'd better also provide lockdep_assert_held_both(), I think, to use it at the update side, something as below: /* * lockdep_assert_held_{both,either}(). * * Sometimes users can use a combination of two locks to * implement a rwlock-like lock, for example, say we have * locks L1 and L2, and we only allow updates when two locks * both held like: * * update() * { * lockdep_assert_held_both(L1, L2); * x++; // update x * } * * while for read-only accesses, either lock suffices (since * holding either lock means others cannot hold both, so readers * serialized with the updaters): * * read() * { * lockdep_assert_held_either(L1, L2); * r = x; // read x * } */ #define lockdep_assert_held_both(l1, l2) do { \ WARN_ON_ONCE(debug_locks && \ (!lockdep_is_held(l1) || \ !lockdep_is_held(l2))); \ } while (0) #define lockdep_assert_held_either(l1, l2) do { \ WARN_ON_ONCE(debug_locks && \ (!lockdep_is_held(l1) && \ !lockdep_is_held(l2))); \ } while (0) Still need sometime to think through this (e.g. on whether this it the best implementation). Regards, Boqun > Cheers, Daniel > > > Regards, > > Boqun > > > > > Adding lockdep folks, maybe they have ideas. > > > > > > On the patch: > > > > > > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> > > > > > > > return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master; > > > > } > > > > > > > > @@ -82,9 +83,9 @@ bool drm_is_current_master(struct drm_file *fpriv) > > > > { > > > > 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; > > > > } > > > > -- > > > > 2.25.1 > > > > > > > > > > -- > > > Daniel Vetter > > > Software Engineer, Intel Corporation > > > http://blog.ffwll.ch > > > > -- > Daniel Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] drm: use the lookup lock in drm_is_current_master 2021-07-22 10:38 ` Daniel Vetter 2021-07-22 15:04 ` Boqun Feng @ 2021-07-27 14:37 ` Peter Zijlstra 2021-07-29 7:00 ` Daniel Vetter 1 sibling, 1 reply; 18+ messages in thread From: Peter Zijlstra @ 2021-07-27 14:37 UTC (permalink / raw) To: Desmond Cheong Zhi Xi, Boqun Feng, LKML, linux-graphics-maintainer, zackr, airlied, maarten.lankhorst, mripard, tzimmermann, dri-devel, intel-gfx, skhan, gregkh, linux-kernel-mentees On Thu, Jul 22, 2021 at 12:38:10PM +0200, Daniel Vetter wrote: > On Thu, Jul 22, 2021 at 05:29:27PM +0800, Desmond Cheong Zhi Xi wrote: > > 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 <daniel.vetter@ffwll.ch> > > Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> > > --- > > drivers/gpu/drm/drm_auth.c | 9 +++++---- > > 1 file changed, 5 insertions(+), 4 deletions(-) > > > > diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c > > index f00354bec3fb..9c24b8cc8e36 100644 > > --- 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. > > + */ > > Disappointing that lockdep can't check or conditions for us, a > lockdep_assert_held_either would be really neat in some cases. > > Adding lockdep folks, maybe they have ideas. #ifdef CONFIG_LOCKDEP WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&drm_device.master_mutex) || lockdep_is_held(&drm_file.master_lookup_lock))); #endif doesn't exactly roll off the tongue, but should do as you want I suppose. Would something like: #define lockdep_assert(cond) WARN_ON_ONCE(debug_locks && !(cond)) Such that we can write: lockdep_assert(lockdep_is_held(&drm_device.master_mutex) || lockdep_is_held(&drm_file.master_lookup_lock)); make it better ? --- Subject: locking/lockdep: Provide lockdep_assert{,_once}() helpers Extract lockdep_assert{,_once}() helpers to more easily write composite assertions like, for example: lockdep_assert(lockdep_is_held(&drm_device.master_mutex) || lockdep_is_held(&drm_file.master_lookup_lock)); Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 5cf387813754..0da67341c1fb 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -306,31 +306,29 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie); #define lockdep_depth(tsk) (debug_locks ? (tsk)->lockdep_depth : 0) -#define lockdep_assert_held(l) do { \ - WARN_ON(debug_locks && \ - lockdep_is_held(l) == LOCK_STATE_NOT_HELD); \ - } while (0) +#define lockdep_assert(cond) \ + do { WARN_ON(debug_locks && !(cond)); } while (0) -#define lockdep_assert_not_held(l) do { \ - WARN_ON(debug_locks && \ - lockdep_is_held(l) == LOCK_STATE_HELD); \ - } while (0) +#define lockdep_assert_once(cond) \ + do { WARN_ON_ONCE(debug_locks && !(cond)); } while (0) -#define lockdep_assert_held_write(l) do { \ - WARN_ON(debug_locks && !lockdep_is_held_type(l, 0)); \ - } while (0) +#define lockdep_assert_held(l) \ + lockdep_assert(lockdep_is_held(l) != LOCK_STAT_NOT_HELD) -#define lockdep_assert_held_read(l) do { \ - WARN_ON(debug_locks && !lockdep_is_held_type(l, 1)); \ - } while (0) +#define lockdep_assert_not_held(l) \ + lockdep_assert(lockdep_is_held(l) != LOCK_STATE_HELD) -#define lockdep_assert_held_once(l) do { \ - WARN_ON_ONCE(debug_locks && !lockdep_is_held(l)); \ - } while (0) +#define lockdep_assert_held_write(l) \ + lockdep_assert(lockdep_is_held_type(l, 0)) -#define lockdep_assert_none_held_once() do { \ - WARN_ON_ONCE(debug_locks && current->lockdep_depth); \ - } while (0) +#define lockdep_assert_held_read(l) \ + lockdep_assert(lockdep_is_held_type(l, 1)) + +#define lockdep_assert_held_once(l) \ + lockdep_assert_once(lockdep_is_held(l) != LOCK_STAT_NOT_HELD) + +#define lockdep_assert_none_held_once() \ + lockdep_assert_once(!current->lockdep_depth) #define lockdep_recursing(tsk) ((tsk)->lockdep_recursion) @@ -407,6 +405,9 @@ extern int lock_is_held(const void *); extern int lockdep_is_held(const void *); #define lockdep_is_held_type(l, r) (1) +#define lockdep_assert(c) do { } while (0) +#define lockdep_assert_once(c) do { } while (0) + #define lockdep_assert_held(l) do { (void)(l); } while (0) #define lockdep_assert_not_held(l) do { (void)(l); } while (0) #define lockdep_assert_held_write(l) do { (void)(l); } while (0) ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] drm: use the lookup lock in drm_is_current_master 2021-07-27 14:37 ` Peter Zijlstra @ 2021-07-29 7:00 ` Daniel Vetter 2021-07-29 14:32 ` Desmond Cheong Zhi Xi 0 siblings, 1 reply; 18+ messages in thread From: Daniel Vetter @ 2021-07-29 7:00 UTC (permalink / raw) To: Peter Zijlstra Cc: Desmond Cheong Zhi Xi, Boqun Feng, LKML, linux-graphics-maintainer, zackr, airlied, maarten.lankhorst, mripard, tzimmermann, dri-devel, intel-gfx, skhan, gregkh, linux-kernel-mentees On Tue, Jul 27, 2021 at 04:37:22PM +0200, Peter Zijlstra wrote: > On Thu, Jul 22, 2021 at 12:38:10PM +0200, Daniel Vetter wrote: > > On Thu, Jul 22, 2021 at 05:29:27PM +0800, Desmond Cheong Zhi Xi wrote: > > > 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 <daniel.vetter@ffwll.ch> > > > Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> > > > --- > > > drivers/gpu/drm/drm_auth.c | 9 +++++---- > > > 1 file changed, 5 insertions(+), 4 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c > > > index f00354bec3fb..9c24b8cc8e36 100644 > > > --- 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. > > > + */ > > > > Disappointing that lockdep can't check or conditions for us, a > > lockdep_assert_held_either would be really neat in some cases. > > > > Adding lockdep folks, maybe they have ideas. > > #ifdef CONFIG_LOCKDEP > WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&drm_device.master_mutex) || > lockdep_is_held(&drm_file.master_lookup_lock))); > #endif > > doesn't exactly roll off the tongue, but should do as you want I > suppose. > > Would something like: > > #define lockdep_assert(cond) WARN_ON_ONCE(debug_locks && !(cond)) > > Such that we can write: > > lockdep_assert(lockdep_is_held(&drm_device.master_mutex) || > lockdep_is_held(&drm_file.master_lookup_lock)); > > make it better ? Yeah I think that's pretty tidy and flexible. Desmond, can you pls give this a shot with Peter's patch below? -Daniel > > --- > Subject: locking/lockdep: Provide lockdep_assert{,_once}() helpers > > Extract lockdep_assert{,_once}() helpers to more easily write composite > assertions like, for example: > > lockdep_assert(lockdep_is_held(&drm_device.master_mutex) || > lockdep_is_held(&drm_file.master_lookup_lock)); > > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> > --- > diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h > index 5cf387813754..0da67341c1fb 100644 > --- a/include/linux/lockdep.h > +++ b/include/linux/lockdep.h > @@ -306,31 +306,29 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie); > > #define lockdep_depth(tsk) (debug_locks ? (tsk)->lockdep_depth : 0) > > -#define lockdep_assert_held(l) do { \ > - WARN_ON(debug_locks && \ > - lockdep_is_held(l) == LOCK_STATE_NOT_HELD); \ > - } while (0) > +#define lockdep_assert(cond) \ > + do { WARN_ON(debug_locks && !(cond)); } while (0) > > -#define lockdep_assert_not_held(l) do { \ > - WARN_ON(debug_locks && \ > - lockdep_is_held(l) == LOCK_STATE_HELD); \ > - } while (0) > +#define lockdep_assert_once(cond) \ > + do { WARN_ON_ONCE(debug_locks && !(cond)); } while (0) > > -#define lockdep_assert_held_write(l) do { \ > - WARN_ON(debug_locks && !lockdep_is_held_type(l, 0)); \ > - } while (0) > +#define lockdep_assert_held(l) \ > + lockdep_assert(lockdep_is_held(l) != LOCK_STAT_NOT_HELD) > > -#define lockdep_assert_held_read(l) do { \ > - WARN_ON(debug_locks && !lockdep_is_held_type(l, 1)); \ > - } while (0) > +#define lockdep_assert_not_held(l) \ > + lockdep_assert(lockdep_is_held(l) != LOCK_STATE_HELD) > > -#define lockdep_assert_held_once(l) do { \ > - WARN_ON_ONCE(debug_locks && !lockdep_is_held(l)); \ > - } while (0) > +#define lockdep_assert_held_write(l) \ > + lockdep_assert(lockdep_is_held_type(l, 0)) > > -#define lockdep_assert_none_held_once() do { \ > - WARN_ON_ONCE(debug_locks && current->lockdep_depth); \ > - } while (0) > +#define lockdep_assert_held_read(l) \ > + lockdep_assert(lockdep_is_held_type(l, 1)) > + > +#define lockdep_assert_held_once(l) \ > + lockdep_assert_once(lockdep_is_held(l) != LOCK_STAT_NOT_HELD) > + > +#define lockdep_assert_none_held_once() \ > + lockdep_assert_once(!current->lockdep_depth) > > #define lockdep_recursing(tsk) ((tsk)->lockdep_recursion) > > @@ -407,6 +405,9 @@ extern int lock_is_held(const void *); > extern int lockdep_is_held(const void *); > #define lockdep_is_held_type(l, r) (1) > > +#define lockdep_assert(c) do { } while (0) > +#define lockdep_assert_once(c) do { } while (0) > + > #define lockdep_assert_held(l) do { (void)(l); } while (0) > #define lockdep_assert_not_held(l) do { (void)(l); } while (0) > #define lockdep_assert_held_write(l) do { (void)(l); } while (0) > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] drm: use the lookup lock in drm_is_current_master 2021-07-29 7:00 ` Daniel Vetter @ 2021-07-29 14:32 ` Desmond Cheong Zhi Xi 2021-07-29 14:45 ` Peter Zijlstra 0 siblings, 1 reply; 18+ messages in thread From: Desmond Cheong Zhi Xi @ 2021-07-29 14:32 UTC (permalink / raw) To: Daniel Vetter, Peter Zijlstra, Boqun Feng, LKML, linux-graphics-maintainer, zackr, airlied, maarten.lankhorst, mripard, tzimmermann Cc: dri-devel, intel-gfx, skhan, gregkh, linux-kernel-mentees On 29/7/21 3:00 pm, Daniel Vetter wrote: > On Tue, Jul 27, 2021 at 04:37:22PM +0200, Peter Zijlstra wrote: >> On Thu, Jul 22, 2021 at 12:38:10PM +0200, Daniel Vetter wrote: >>> On Thu, Jul 22, 2021 at 05:29:27PM +0800, Desmond Cheong Zhi Xi wrote: >>>> 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 <daniel.vetter@ffwll.ch> >>>> Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> >>>> --- >>>> drivers/gpu/drm/drm_auth.c | 9 +++++---- >>>> 1 file changed, 5 insertions(+), 4 deletions(-) >>>> >>>> diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c >>>> index f00354bec3fb..9c24b8cc8e36 100644 >>>> --- 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. >>>> + */ >>> >>> Disappointing that lockdep can't check or conditions for us, a >>> lockdep_assert_held_either would be really neat in some cases. >>> >>> Adding lockdep folks, maybe they have ideas. >> >> #ifdef CONFIG_LOCKDEP >> WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&drm_device.master_mutex) || >> lockdep_is_held(&drm_file.master_lookup_lock))); >> #endif >> >> doesn't exactly roll off the tongue, but should do as you want I >> suppose. >> >> Would something like: >> >> #define lockdep_assert(cond) WARN_ON_ONCE(debug_locks && !(cond)) >> >> Such that we can write: >> >> lockdep_assert(lockdep_is_held(&drm_device.master_mutex) || >> lockdep_is_held(&drm_file.master_lookup_lock)); >> >> make it better ? > > Yeah I think that's pretty tidy and flexible. > > Desmond, can you pls give this a shot with Peter's patch below? > -Daniel Sounds good, will do. Thanks for the patch, Peter. Just going to make a small edit: s/LOCK_STAT_NOT_HELD/LOCK_STATE_NOT_HELD/ Best wishes, Desmond >> >> --- >> Subject: locking/lockdep: Provide lockdep_assert{,_once}() helpers >> >> Extract lockdep_assert{,_once}() helpers to more easily write composite >> assertions like, for example: >> >> lockdep_assert(lockdep_is_held(&drm_device.master_mutex) || >> lockdep_is_held(&drm_file.master_lookup_lock)); >> >> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> >> --- >> diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h >> index 5cf387813754..0da67341c1fb 100644 >> --- a/include/linux/lockdep.h >> +++ b/include/linux/lockdep.h >> @@ -306,31 +306,29 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie); >> >> #define lockdep_depth(tsk) (debug_locks ? (tsk)->lockdep_depth : 0) >> >> -#define lockdep_assert_held(l) do { \ >> - WARN_ON(debug_locks && \ >> - lockdep_is_held(l) == LOCK_STATE_NOT_HELD); \ >> - } while (0) >> +#define lockdep_assert(cond) \ >> + do { WARN_ON(debug_locks && !(cond)); } while (0) >> >> -#define lockdep_assert_not_held(l) do { \ >> - WARN_ON(debug_locks && \ >> - lockdep_is_held(l) == LOCK_STATE_HELD); \ >> - } while (0) >> +#define lockdep_assert_once(cond) \ >> + do { WARN_ON_ONCE(debug_locks && !(cond)); } while (0) >> >> -#define lockdep_assert_held_write(l) do { \ >> - WARN_ON(debug_locks && !lockdep_is_held_type(l, 0)); \ >> - } while (0) >> +#define lockdep_assert_held(l) \ >> + lockdep_assert(lockdep_is_held(l) != LOCK_STAT_NOT_HELD) >> >> -#define lockdep_assert_held_read(l) do { \ >> - WARN_ON(debug_locks && !lockdep_is_held_type(l, 1)); \ >> - } while (0) >> +#define lockdep_assert_not_held(l) \ >> + lockdep_assert(lockdep_is_held(l) != LOCK_STATE_HELD) >> >> -#define lockdep_assert_held_once(l) do { \ >> - WARN_ON_ONCE(debug_locks && !lockdep_is_held(l)); \ >> - } while (0) >> +#define lockdep_assert_held_write(l) \ >> + lockdep_assert(lockdep_is_held_type(l, 0)) >> >> -#define lockdep_assert_none_held_once() do { \ >> - WARN_ON_ONCE(debug_locks && current->lockdep_depth); \ >> - } while (0) >> +#define lockdep_assert_held_read(l) \ >> + lockdep_assert(lockdep_is_held_type(l, 1)) >> + >> +#define lockdep_assert_held_once(l) \ >> + lockdep_assert_once(lockdep_is_held(l) != LOCK_STAT_NOT_HELD) >> + >> +#define lockdep_assert_none_held_once() \ >> + lockdep_assert_once(!current->lockdep_depth) >> >> #define lockdep_recursing(tsk) ((tsk)->lockdep_recursion) >> >> @@ -407,6 +405,9 @@ extern int lock_is_held(const void *); >> extern int lockdep_is_held(const void *); >> #define lockdep_is_held_type(l, r) (1) >> >> +#define lockdep_assert(c) do { } while (0) >> +#define lockdep_assert_once(c) do { } while (0) >> + >> #define lockdep_assert_held(l) do { (void)(l); } while (0) >> #define lockdep_assert_not_held(l) do { (void)(l); } while (0) >> #define lockdep_assert_held_write(l) do { (void)(l); } while (0) >> > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 1/3] drm: use the lookup lock in drm_is_current_master 2021-07-29 14:32 ` Desmond Cheong Zhi Xi @ 2021-07-29 14:45 ` Peter Zijlstra 0 siblings, 0 replies; 18+ messages in thread From: Peter Zijlstra @ 2021-07-29 14:45 UTC (permalink / raw) To: Desmond Cheong Zhi Xi Cc: Daniel Vetter, Boqun Feng, LKML, linux-graphics-maintainer, zackr, airlied, maarten.lankhorst, mripard, tzimmermann, dri-devel, intel-gfx, skhan, gregkh, linux-kernel-mentees On Thu, Jul 29, 2021 at 10:32:13PM +0800, Desmond Cheong Zhi Xi wrote: > Sounds good, will do. Thanks for the patch, Peter. > > Just going to make a small edit: > s/LOCK_STAT_NOT_HELD/LOCK_STATE_NOT_HELD/ Bah, I knew I should've compile tested it :-), Thanks! ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 2/3] drm: clarify lifetime/locking for drm_master's lease fields 2021-07-22 9:29 [PATCH 0/3] drm, drm/vmwgfx: fixes and updates related to drm_master Desmond Cheong Zhi Xi 2021-07-22 9:29 ` [PATCH 1/3] drm: use the lookup lock in drm_is_current_master Desmond Cheong Zhi Xi @ 2021-07-22 9:29 ` Desmond Cheong Zhi Xi 2021-07-22 10:35 ` Daniel Vetter 2021-07-22 9:29 ` [PATCH 3/3] drm/vmwgfx: fix potential UAF in vmwgfx_surface.c Desmond Cheong Zhi Xi 2 siblings, 1 reply; 18+ messages in thread From: Desmond Cheong Zhi Xi @ 2021-07-22 9:29 UTC (permalink / raw) To: linux-graphics-maintainer, zackr, airlied, daniel, maarten.lankhorst, mripard, tzimmermann Cc: Desmond Cheong Zhi Xi, dri-devel, linux-kernel, intel-gfx, skhan, gregkh, linux-kernel-mentees In particular, we make it clear that &drm_device.mode_config.idr_mutex protects the lease idr and list structures for drm_master. The lessor field itself doesn't need to be protected as it doesn't change after it's set in drm_lease_create. Additionally, we add descriptions for the lifetime of lessors and leases to make it easier to reason about them. Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> --- include/drm/drm_auth.h | 62 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/include/drm/drm_auth.h b/include/drm/drm_auth.h index f99d3417f304..c978c85464fa 100644 --- a/include/drm/drm_auth.h +++ b/include/drm/drm_auth.h @@ -58,12 +58,6 @@ struct drm_lock_data { * @refcount: Refcount for this master object. * @dev: Link back to the DRM device * @driver_priv: Pointer to driver-private information. - * @lessor: Lease holder - * @lessee_id: id for lessees. Owners always have id 0 - * @lessee_list: other lessees of the same master - * @lessees: drm_masters leasing from this one - * @leases: Objects leased to this drm_master. - * @lessee_idr: All lessees under this owner (only used where lessor == NULL) * * Note that master structures are only relevant for the legacy/primary device * nodes, hence there can only be one per device, not one per drm_minor. @@ -88,17 +82,63 @@ struct drm_master { struct idr magic_map; void *driver_priv; - /* Tree of display resource leases, each of which is a drm_master struct - * All of these get activated simultaneously, so drm_device master points - * at the top of the tree (for which lessor is NULL). Protected by - * &drm_device.mode_config.idr_mutex. + /** + * @lessor: + * + * Lease holder. The lessor does not change once it's set in + * drm_lease_create(). Each lessee holds a reference to its lessor that + * it releases upon being destroyed in drm_lease_destroy(). + * + * Display resource leases form a tree of &struct drm_master. All of + * these get activated simultaneously, so &drm_device.master + * points at the top of the tree (for which lessor is NULL). */ - struct drm_master *lessor; + + /** + * @lessee_id: + * + * ID for lessees. Owners always have ID 0. Protected by + * &drm_device.mode_config's &drm_mode_config.idr_mutex. + */ int lessee_id; + + /** + * @lessee_list: + * + * List of lessees of the same master. Protected by + * &drm_device.mode_config's &drm_mode_config.idr_mutex. + */ struct list_head lessee_list; + + /** + * @lessees: + * + * List of drm_masters leasing from this one. Protected by + * &drm_device.mode_config's &drm_mode_config.idr_mutex. + * + * This master cannot be destroyed unless this list is empty as lessors + * are referenced by all their lessees. + */ struct list_head lessees; + + /** + * @leases: + * + * Objects leased to this drm_master. Protected by + * &drm_device.mode_config's &drm_mode_config.idr_mutex. + * + * Objects are leased all together in drm_lease_create(), and are + * removed all together when the lease is revoked. + */ struct idr leases; + + /** + * @lessee_idr: + * + * All lessees under this owner (only used where lessor is NULL). + * Protected by &drm_device.mode_config's &drm_mode_config.idr_mutex. + */ struct idr lessee_idr; /* private: */ #if IS_ENABLED(CONFIG_DRM_LEGACY) -- 2.25.1 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/3] drm: clarify lifetime/locking for drm_master's lease fields 2021-07-22 9:29 ` [PATCH 2/3] drm: clarify lifetime/locking for drm_master's lease fields Desmond Cheong Zhi Xi @ 2021-07-22 10:35 ` Daniel Vetter 2021-07-22 13:02 ` Desmond Cheong Zhi Xi 0 siblings, 1 reply; 18+ messages in thread From: Daniel Vetter @ 2021-07-22 10:35 UTC (permalink / raw) To: Desmond Cheong Zhi Xi Cc: linux-graphics-maintainer, zackr, airlied, daniel, maarten.lankhorst, mripard, tzimmermann, dri-devel, linux-kernel, intel-gfx, skhan, gregkh, linux-kernel-mentees On Thu, Jul 22, 2021 at 05:29:28PM +0800, Desmond Cheong Zhi Xi wrote: > In particular, we make it clear that &drm_device.mode_config.idr_mutex > protects the lease idr and list structures for drm_master. The lessor > field itself doesn't need to be protected as it doesn't change after > it's set in drm_lease_create. > > Additionally, we add descriptions for the lifetime of lessors and > leases to make it easier to reason about them. > > Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> > --- > include/drm/drm_auth.h | 62 ++++++++++++++++++++++++++++++++++-------- > 1 file changed, 51 insertions(+), 11 deletions(-) > > diff --git a/include/drm/drm_auth.h b/include/drm/drm_auth.h > index f99d3417f304..c978c85464fa 100644 > --- a/include/drm/drm_auth.h > +++ b/include/drm/drm_auth.h > @@ -58,12 +58,6 @@ struct drm_lock_data { > * @refcount: Refcount for this master object. > * @dev: Link back to the DRM device > * @driver_priv: Pointer to driver-private information. > - * @lessor: Lease holder > - * @lessee_id: id for lessees. Owners always have id 0 > - * @lessee_list: other lessees of the same master > - * @lessees: drm_masters leasing from this one > - * @leases: Objects leased to this drm_master. > - * @lessee_idr: All lessees under this owner (only used where lessor == NULL) > * > * Note that master structures are only relevant for the legacy/primary device > * nodes, hence there can only be one per device, not one per drm_minor. > @@ -88,17 +82,63 @@ struct drm_master { > struct idr magic_map; > void *driver_priv; > > - /* Tree of display resource leases, each of which is a drm_master struct > - * All of these get activated simultaneously, so drm_device master points > - * at the top of the tree (for which lessor is NULL). Protected by > - * &drm_device.mode_config.idr_mutex. > + /** > + * @lessor: > + * > + * Lease holder. The lessor does not change once it's set in Lessor is the lease grantor, lessee is the one receiving the lease. Maybe clarify this with "Lease grantor, only set if this struct drm_master represents a lessee holding a lease of objects from @lessor. Full owners of the device have this set to NULL." > + * drm_lease_create(). Each lessee holds a reference to its lessor that I also figured it'd be a good idea to link to the drm_lease docs here to explain the concepts, but alas we don't have those :-( Hence at least define what we mean with lessor, lessee, lease and owner. > + * it releases upon being destroyed in drm_lease_destroy(). > + * > + * Display resource leases form a tree of &struct drm_master. All of For now we've limited the tree to a depth of 1, you can't create another lease if yourself are a lease. I guess another reason to update the drm_lease.c docs. So maybe add "Currently the lease tree depth is limited to 1." > + * these get activated simultaneously, so &drm_device.master > + * points at the top of the tree (for which lessor is NULL). > */ > - > struct drm_master *lessor; > + > + /** > + * @lessee_id: > + * > + * ID for lessees. Owners always have ID 0. Protected by Maybe clarify to "Owners (i.e. @lessor is NULL) ..." > + * &drm_device.mode_config's &drm_mode_config.idr_mutex. > + */ > int lessee_id; > + > + /** > + * @lessee_list: > + * > + * List of lessees of the same master. Protected by We try to distinguis between list entries and the list, even though it's the same struct. So maybe "List entry of lessees of @lessor, where they are linked to @lessee. Not use for owners." > + * &drm_device.mode_config's &drm_mode_config.idr_mutex. > + */ > struct list_head lessee_list; > + > + /** > + * @lessees: > + * > + * List of drm_masters leasing from this one. Protected by > + * &drm_device.mode_config's &drm_mode_config.idr_mutex. > + * > + * This master cannot be destroyed unless this list is empty as lessors > + * are referenced by all their lessees. Maybe add "this list is empty of no leases have been granted." > + */ > struct list_head lessees; > + > + /** > + * @leases: > + * > + * Objects leased to this drm_master. Protected by > + * &drm_device.mode_config's &drm_mode_config.idr_mutex. > + * > + * Objects are leased all together in drm_lease_create(), and are > + * removed all together when the lease is revoked. > + */ > struct idr leases; > + > + /** > + * @lessee_idr: > + * > + * All lessees under this owner (only used where lessor is NULL). @lessor so it's highlighted correctly > + * Protected by &drm_device.mode_config's &drm_mode_config.idr_mutex. > + */ > struct idr lessee_idr; > /* private: */ With the nits addressed: Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Thanks for updating the docs! -Daniel > #if IS_ENABLED(CONFIG_DRM_LEGACY) > -- > 2.25.1 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/3] drm: clarify lifetime/locking for drm_master's lease fields 2021-07-22 10:35 ` Daniel Vetter @ 2021-07-22 13:02 ` Desmond Cheong Zhi Xi 2021-07-22 14:17 ` Daniel Vetter 0 siblings, 1 reply; 18+ messages in thread From: Desmond Cheong Zhi Xi @ 2021-07-22 13:02 UTC (permalink / raw) To: Daniel Vetter Cc: linux-graphics-maintainer, zackr, airlied, maarten.lankhorst, mripard, tzimmermann, dri-devel, linux-kernel, intel-gfx, skhan, gregkh, linux-kernel-mentees On 22/7/21 6:35 pm, Daniel Vetter wrote: > On Thu, Jul 22, 2021 at 05:29:28PM +0800, Desmond Cheong Zhi Xi wrote: >> In particular, we make it clear that &drm_device.mode_config.idr_mutex >> protects the lease idr and list structures for drm_master. The lessor >> field itself doesn't need to be protected as it doesn't change after >> it's set in drm_lease_create. >> >> Additionally, we add descriptions for the lifetime of lessors and >> leases to make it easier to reason about them. >> >> Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> >> --- >> include/drm/drm_auth.h | 62 ++++++++++++++++++++++++++++++++++-------- >> 1 file changed, 51 insertions(+), 11 deletions(-) >> >> diff --git a/include/drm/drm_auth.h b/include/drm/drm_auth.h >> index f99d3417f304..c978c85464fa 100644 >> --- a/include/drm/drm_auth.h >> +++ b/include/drm/drm_auth.h >> @@ -58,12 +58,6 @@ struct drm_lock_data { >> * @refcount: Refcount for this master object. >> * @dev: Link back to the DRM device >> * @driver_priv: Pointer to driver-private information. >> - * @lessor: Lease holder >> - * @lessee_id: id for lessees. Owners always have id 0 >> - * @lessee_list: other lessees of the same master >> - * @lessees: drm_masters leasing from this one >> - * @leases: Objects leased to this drm_master. >> - * @lessee_idr: All lessees under this owner (only used where lessor == NULL) >> * >> * Note that master structures are only relevant for the legacy/primary device >> * nodes, hence there can only be one per device, not one per drm_minor. >> @@ -88,17 +82,63 @@ struct drm_master { >> struct idr magic_map; >> void *driver_priv; >> >> - /* Tree of display resource leases, each of which is a drm_master struct >> - * All of these get activated simultaneously, so drm_device master points >> - * at the top of the tree (for which lessor is NULL). Protected by >> - * &drm_device.mode_config.idr_mutex. >> + /** >> + * @lessor: >> + * >> + * Lease holder. The lessor does not change once it's set in > > Lessor is the lease grantor, lessee is the one receiving the lease. Maybe > clarify this with > > "Lease grantor, only set if this struct drm_master represents a lessee > holding a lease of objects from @lessor. Full owners of the device have > this set to NULL." > >> + * drm_lease_create(). Each lessee holds a reference to its lessor that > > I also figured it'd be a good idea to link to the drm_lease docs here to > explain the concepts, but alas we don't have those :-( Hence at least > define what we mean with lessor, lessee, lease and owner. > Thanks for the suggestions, Daniel. I'll incorporate them in a v2. Regarding the missing drm_lease docs... any reason we can't just add it in? Seems like most of the comments in drm_lease.c are almost correctly formatted too. I could clean them up, define the terms in a preamble, then add it to the v2 patch. >> + * it releases upon being destroyed in drm_lease_destroy(). >> + * >> + * Display resource leases form a tree of &struct drm_master. All of > > For now we've limited the tree to a depth of 1, you can't create another > lease if yourself are a lease. I guess another reason to update the > drm_lease.c docs. > > So maybe add "Currently the lease tree depth is limited to 1." > >> + * these get activated simultaneously, so &drm_device.master >> + * points at the top of the tree (for which lessor is NULL). >> */ >> - >> struct drm_master *lessor; >> + >> + /** >> + * @lessee_id: >> + * >> + * ID for lessees. Owners always have ID 0. Protected by > > Maybe clarify to "Owners (i.e. @lessor is NULL) ..." > >> + * &drm_device.mode_config's &drm_mode_config.idr_mutex. >> + */ >> int lessee_id; >> + >> + /** >> + * @lessee_list: >> + * >> + * List of lessees of the same master. Protected by > > We try to distinguis between list entries and the list, even though it's > the same struct. So maybe > > "List entry of lessees of @lessor, where they are linked to @lessee. Not > use for owners." > >> + * &drm_device.mode_config's &drm_mode_config.idr_mutex. > >> + */ >> struct list_head lessee_list; >> + >> + /** >> + * @lessees: >> + * >> + * List of drm_masters leasing from this one. Protected by >> + * &drm_device.mode_config's &drm_mode_config.idr_mutex. >> + * >> + * This master cannot be destroyed unless this list is empty as lessors >> + * are referenced by all their lessees. > > Maybe add "this list is empty of no leases have been granted." > >> + */ >> struct list_head lessees; >> + >> + /** >> + * @leases: >> + * >> + * Objects leased to this drm_master. Protected by >> + * &drm_device.mode_config's &drm_mode_config.idr_mutex. >> + * >> + * Objects are leased all together in drm_lease_create(), and are >> + * removed all together when the lease is revoked. >> + */ >> struct idr leases; >> + >> + /** >> + * @lessee_idr: >> + * >> + * All lessees under this owner (only used where lessor is NULL). > > @lessor so it's highlighted correctly > >> + * Protected by &drm_device.mode_config's &drm_mode_config.idr_mutex. >> + */ >> struct idr lessee_idr; >> /* private: */ > > With the nits addressed: > > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> > > Thanks for updating the docs! > -Daniel > >> #if IS_ENABLED(CONFIG_DRM_LEGACY) >> -- >> 2.25.1 >> > ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/3] drm: clarify lifetime/locking for drm_master's lease fields 2021-07-22 13:02 ` Desmond Cheong Zhi Xi @ 2021-07-22 14:17 ` Daniel Vetter 0 siblings, 0 replies; 18+ messages in thread From: Daniel Vetter @ 2021-07-22 14:17 UTC (permalink / raw) To: Desmond Cheong Zhi Xi Cc: VMware Graphics, Zack Rusin, Dave Airlie, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, dri-devel, Linux Kernel Mailing List, intel-gfx, Shuah Khan, Greg KH, linux-kernel-mentees On Thu, Jul 22, 2021 at 3:03 PM Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> wrote: > > On 22/7/21 6:35 pm, Daniel Vetter wrote: > > On Thu, Jul 22, 2021 at 05:29:28PM +0800, Desmond Cheong Zhi Xi wrote: > >> In particular, we make it clear that &drm_device.mode_config.idr_mutex > >> protects the lease idr and list structures for drm_master. The lessor > >> field itself doesn't need to be protected as it doesn't change after > >> it's set in drm_lease_create. > >> > >> Additionally, we add descriptions for the lifetime of lessors and > >> leases to make it easier to reason about them. > >> > >> Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> > >> --- > >> include/drm/drm_auth.h | 62 ++++++++++++++++++++++++++++++++++-------- > >> 1 file changed, 51 insertions(+), 11 deletions(-) > >> > >> diff --git a/include/drm/drm_auth.h b/include/drm/drm_auth.h > >> index f99d3417f304..c978c85464fa 100644 > >> --- a/include/drm/drm_auth.h > >> +++ b/include/drm/drm_auth.h > >> @@ -58,12 +58,6 @@ struct drm_lock_data { > >> * @refcount: Refcount for this master object. > >> * @dev: Link back to the DRM device > >> * @driver_priv: Pointer to driver-private information. > >> - * @lessor: Lease holder > >> - * @lessee_id: id for lessees. Owners always have id 0 > >> - * @lessee_list: other lessees of the same master > >> - * @lessees: drm_masters leasing from this one > >> - * @leases: Objects leased to this drm_master. > >> - * @lessee_idr: All lessees under this owner (only used where lessor == NULL) > >> * > >> * Note that master structures are only relevant for the legacy/primary device > >> * nodes, hence there can only be one per device, not one per drm_minor. > >> @@ -88,17 +82,63 @@ struct drm_master { > >> struct idr magic_map; > >> void *driver_priv; > >> > >> - /* Tree of display resource leases, each of which is a drm_master struct > >> - * All of these get activated simultaneously, so drm_device master points > >> - * at the top of the tree (for which lessor is NULL). Protected by > >> - * &drm_device.mode_config.idr_mutex. > >> + /** > >> + * @lessor: > >> + * > >> + * Lease holder. The lessor does not change once it's set in > > > > Lessor is the lease grantor, lessee is the one receiving the lease. Maybe > > clarify this with > > > > "Lease grantor, only set if this struct drm_master represents a lessee > > holding a lease of objects from @lessor. Full owners of the device have > > this set to NULL." > > > >> + * drm_lease_create(). Each lessee holds a reference to its lessor that > > > > I also figured it'd be a good idea to link to the drm_lease docs here to > > explain the concepts, but alas we don't have those :-( Hence at least > > define what we mean with lessor, lessee, lease and owner. > > > > Thanks for the suggestions, Daniel. I'll incorporate them in a v2. > > Regarding the missing drm_lease docs... any reason we can't just add it > in? Seems like most of the comments in drm_lease.c are almost correctly > formatted too. I could clean them up, define the terms in a preamble, > then add it to the v2 patch. Sure if you want to do that, that would be great. Usual style tips: - We only document driver interfaces, so structs/inline functions in headers and exported symbols in .c files. - Anything else interesting just leave as normal C comments - An overview DOC: section that explains a bit how leases work and why (git blame on the commit that added it should help, otherwise I can type that up) would also be really great. I think the right place for this is in the drm-uapi.rst section after the section about primary nodes: https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#modeset-base-object-abstraction Cheers, Daniel > > >> + * it releases upon being destroyed in drm_lease_destroy(). > >> + * > >> + * Display resource leases form a tree of &struct drm_master. All of > > > > For now we've limited the tree to a depth of 1, you can't create another > > lease if yourself are a lease. I guess another reason to update the > > drm_lease.c docs. > > > > So maybe add "Currently the lease tree depth is limited to 1." > > > >> + * these get activated simultaneously, so &drm_device.master > >> + * points at the top of the tree (for which lessor is NULL). > >> */ > >> - > >> struct drm_master *lessor; > >> + > >> + /** > >> + * @lessee_id: > >> + * > >> + * ID for lessees. Owners always have ID 0. Protected by > > > > Maybe clarify to "Owners (i.e. @lessor is NULL) ..." > > > >> + * &drm_device.mode_config's &drm_mode_config.idr_mutex. > >> + */ > >> int lessee_id; > >> + > >> + /** > >> + * @lessee_list: > >> + * > >> + * List of lessees of the same master. Protected by > > > > We try to distinguis between list entries and the list, even though it's > > the same struct. So maybe > > > > "List entry of lessees of @lessor, where they are linked to @lessee. Not > > use for owners." > > > >> + * &drm_device.mode_config's &drm_mode_config.idr_mutex. > > > >> + */ > >> struct list_head lessee_list; > >> + > >> + /** > >> + * @lessees: > >> + * > >> + * List of drm_masters leasing from this one. Protected by > >> + * &drm_device.mode_config's &drm_mode_config.idr_mutex. > >> + * > >> + * This master cannot be destroyed unless this list is empty as lessors > >> + * are referenced by all their lessees. > > > > Maybe add "this list is empty of no leases have been granted." > > > >> + */ > >> struct list_head lessees; > >> + > >> + /** > >> + * @leases: > >> + * > >> + * Objects leased to this drm_master. Protected by > >> + * &drm_device.mode_config's &drm_mode_config.idr_mutex. > >> + * > >> + * Objects are leased all together in drm_lease_create(), and are > >> + * removed all together when the lease is revoked. > >> + */ > >> struct idr leases; > >> + > >> + /** > >> + * @lessee_idr: > >> + * > >> + * All lessees under this owner (only used where lessor is NULL). > > > > @lessor so it's highlighted correctly > > > >> + * Protected by &drm_device.mode_config's &drm_mode_config.idr_mutex. > >> + */ > >> struct idr lessee_idr; > >> /* private: */ > > > > With the nits addressed: > > > > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> > > > > Thanks for updating the docs! > > -Daniel > > > >> #if IS_ENABLED(CONFIG_DRM_LEGACY) > >> -- > >> 2.25.1 > >> > > > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 3/3] drm/vmwgfx: fix potential UAF in vmwgfx_surface.c 2021-07-22 9:29 [PATCH 0/3] drm, drm/vmwgfx: fixes and updates related to drm_master Desmond Cheong Zhi Xi 2021-07-22 9:29 ` [PATCH 1/3] drm: use the lookup lock in drm_is_current_master Desmond Cheong Zhi Xi 2021-07-22 9:29 ` [PATCH 2/3] drm: clarify lifetime/locking for drm_master's lease fields Desmond Cheong Zhi Xi @ 2021-07-22 9:29 ` Desmond Cheong Zhi Xi 2021-07-22 10:39 ` Daniel Vetter 2021-07-22 19:17 ` Zack Rusin 2 siblings, 2 replies; 18+ messages in thread From: Desmond Cheong Zhi Xi @ 2021-07-22 9:29 UTC (permalink / raw) To: linux-graphics-maintainer, zackr, airlied, daniel, maarten.lankhorst, mripard, tzimmermann Cc: Desmond Cheong Zhi Xi, dri-devel, linux-kernel, intel-gfx, skhan, gregkh, linux-kernel-mentees drm_file.master should be protected by either drm_device.master_mutex or drm_file.master_lookup_lock when being dereferenced. However, drm_master_get is called on unprotected file_priv->master pointers in vmw_surface_define_ioctl and vmw_gb_surface_define_internal. This is fixed by replacing drm_master_get with drm_file_get_master. Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> --- drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 0eba47762bed..5d53a5f9d123 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -865,7 +865,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, user_srf->prime.base.shareable = false; user_srf->prime.base.tfile = NULL; if (drm_is_primary_client(file_priv)) - user_srf->master = drm_master_get(file_priv->master); + user_srf->master = drm_file_get_master(file_priv); /** * From this point, the generic resource management functions @@ -1534,7 +1534,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, user_srf = container_of(srf, struct vmw_user_surface, srf); if (drm_is_primary_client(file_priv)) - user_srf->master = drm_master_get(file_priv->master); + user_srf->master = drm_file_get_master(file_priv); res = &user_srf->srf.res; -- 2.25.1 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] drm/vmwgfx: fix potential UAF in vmwgfx_surface.c 2021-07-22 9:29 ` [PATCH 3/3] drm/vmwgfx: fix potential UAF in vmwgfx_surface.c Desmond Cheong Zhi Xi @ 2021-07-22 10:39 ` Daniel Vetter 2021-07-22 19:17 ` Zack Rusin 1 sibling, 0 replies; 18+ messages in thread From: Daniel Vetter @ 2021-07-22 10:39 UTC (permalink / raw) To: Desmond Cheong Zhi Xi Cc: linux-graphics-maintainer, zackr, airlied, daniel, maarten.lankhorst, mripard, tzimmermann, dri-devel, linux-kernel, intel-gfx, skhan, gregkh, linux-kernel-mentees On Thu, Jul 22, 2021 at 05:29:29PM +0800, Desmond Cheong Zhi Xi wrote: > drm_file.master should be protected by either drm_device.master_mutex > or drm_file.master_lookup_lock when being dereferenced. However, > drm_master_get is called on unprotected file_priv->master pointers in > vmw_surface_define_ioctl and vmw_gb_surface_define_internal. > > This is fixed by replacing drm_master_get with drm_file_get_master. > > Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> I'll let Zack take a look at this and expect him to push this patch to drm-misc.git. -Daniel > --- > drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > index 0eba47762bed..5d53a5f9d123 100644 > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c > @@ -865,7 +865,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, > user_srf->prime.base.shareable = false; > user_srf->prime.base.tfile = NULL; > if (drm_is_primary_client(file_priv)) > - user_srf->master = drm_master_get(file_priv->master); > + user_srf->master = drm_file_get_master(file_priv); > > /** > * From this point, the generic resource management functions > @@ -1534,7 +1534,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, > > user_srf = container_of(srf, struct vmw_user_surface, srf); > if (drm_is_primary_client(file_priv)) > - user_srf->master = drm_master_get(file_priv->master); > + user_srf->master = drm_file_get_master(file_priv); > > res = &user_srf->srf.res; > > -- > 2.25.1 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] drm/vmwgfx: fix potential UAF in vmwgfx_surface.c 2021-07-22 9:29 ` [PATCH 3/3] drm/vmwgfx: fix potential UAF in vmwgfx_surface.c Desmond Cheong Zhi Xi 2021-07-22 10:39 ` Daniel Vetter @ 2021-07-22 19:17 ` Zack Rusin 2021-07-23 6:44 ` Desmond Cheong Zhi Xi 1 sibling, 1 reply; 18+ messages in thread From: Zack Rusin @ 2021-07-22 19:17 UTC (permalink / raw) To: Desmond Cheong Zhi Xi, linux-graphics-maintainer, airlied, daniel, maarten.lankhorst, mripard, tzimmermann Cc: dri-devel, linux-kernel, intel-gfx, skhan, gregkh, linux-kernel-mentees On 7/22/21 5:29 AM, Desmond Cheong Zhi Xi wrote: > drm_file.master should be protected by either drm_device.master_mutex > or drm_file.master_lookup_lock when being dereferenced. However, > drm_master_get is called on unprotected file_priv->master pointers in > vmw_surface_define_ioctl and vmw_gb_surface_define_internal. > > This is fixed by replacing drm_master_get with drm_file_get_master. > > Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> Reviewed-by: Zack Rusin <zackr@vmware.com> Thanks for taking the time to fix this. Apart from the clear logic error, do you happen to know under what circumstances would this be hit? We have someone looking at writing some vmwgfx specific igt tests and I was wondering if I could add this to the list. z ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 3/3] drm/vmwgfx: fix potential UAF in vmwgfx_surface.c 2021-07-22 19:17 ` Zack Rusin @ 2021-07-23 6:44 ` Desmond Cheong Zhi Xi 0 siblings, 0 replies; 18+ messages in thread From: Desmond Cheong Zhi Xi @ 2021-07-23 6:44 UTC (permalink / raw) To: Zack Rusin, linux-graphics-maintainer, airlied, daniel, maarten.lankhorst, mripard, tzimmermann Cc: dri-devel, linux-kernel, intel-gfx, skhan, gregkh, linux-kernel-mentees On 23/7/21 3:17 am, Zack Rusin wrote: > On 7/22/21 5:29 AM, Desmond Cheong Zhi Xi wrote: >> drm_file.master should be protected by either drm_device.master_mutex >> or drm_file.master_lookup_lock when being dereferenced. However, >> drm_master_get is called on unprotected file_priv->master pointers in >> vmw_surface_define_ioctl and vmw_gb_surface_define_internal. >> >> This is fixed by replacing drm_master_get with drm_file_get_master. >> >> Signed-off-by: Desmond Cheong Zhi Xi <desmondcheongzx@gmail.com> > > Reviewed-by: Zack Rusin <zackr@vmware.com> > > Thanks for taking the time to fix this. Apart from the clear logic > error, do you happen to know under what circumstances would this be hit? > We have someone looking at writing some vmwgfx specific igt tests and I > was wondering if I could add this to the list. > > z Hi Zack, Thanks for the review. For some context, the use-after-free happens when there's a race between accessing the value of drm_file.master, and a call to drm_setmaster_ioctl. If drm_file is not the creator of master, then the ioctl allocates a new master for drm_file and puts the old master. Thus for example, the old value of drm_file.master could be freed in between getting the value of file_priv->master, and the call to drm_master_get. I'm not entirely sure whether this scenario is a good candidate for a test? For further reference, the issue was originally caught by Syzbot here: https://syzkaller.appspot.com/bug?id=148d2f1dfac64af52ffd27b661981a540724f803 And from the logs it seems that the reproducer set up a race between DRM_IOCTL_GET_UNIQUE and DRM_IOCTL_SET_MASTER. So possibly a race between VMW_CREATE_SURFACE and DRM_IOCTL_SET_MASTER could trigger the same bug. Best wishes, Desmond ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2021-07-29 14:47 UTC | newest] Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-07-22 9:29 [PATCH 0/3] drm, drm/vmwgfx: fixes and updates related to drm_master Desmond Cheong Zhi Xi 2021-07-22 9:29 ` [PATCH 1/3] drm: use the lookup lock in drm_is_current_master Desmond Cheong Zhi Xi 2021-07-22 10:38 ` Daniel Vetter 2021-07-22 15:04 ` Boqun Feng 2021-07-22 19:02 ` Daniel Vetter 2021-07-23 7:16 ` Boqun Feng 2021-07-27 14:37 ` Peter Zijlstra 2021-07-29 7:00 ` Daniel Vetter 2021-07-29 14:32 ` Desmond Cheong Zhi Xi 2021-07-29 14:45 ` Peter Zijlstra 2021-07-22 9:29 ` [PATCH 2/3] drm: clarify lifetime/locking for drm_master's lease fields Desmond Cheong Zhi Xi 2021-07-22 10:35 ` Daniel Vetter 2021-07-22 13:02 ` Desmond Cheong Zhi Xi 2021-07-22 14:17 ` Daniel Vetter 2021-07-22 9:29 ` [PATCH 3/3] drm/vmwgfx: fix potential UAF in vmwgfx_surface.c Desmond Cheong Zhi Xi 2021-07-22 10:39 ` Daniel Vetter 2021-07-22 19:17 ` Zack Rusin 2021-07-23 6:44 ` Desmond Cheong Zhi Xi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).