* Trying to fix drm/prime: remove drm_prime_lookup_buf_by_handle @ 2025-06-13 13:12 Christian König 2025-06-13 13:12 ` [PATCH] drm/prime: fix drm_prime_add_buf_handle Christian König 2025-06-13 14:32 ` Trying to fix drm/prime: remove drm_prime_lookup_buf_by_handle Saarinen, Jani 0 siblings, 2 replies; 13+ messages in thread From: Christian König @ 2025-06-13 13:12 UTC (permalink / raw) To: jani.saarinen, jani.nikula, tursulin, simona.vetter, tzimmermann, dri-devel The problem with this patch is that we now don't check if the handle already existed any more, but just blindly try to add it again. This obviously breaks re-exporting DMA-bufs but also surfaces an issue that we don't seem to take into account that multiple handles can point to the same GEM object. Try to fix this by just ignoring adding the same DMA-buf to the rb tree multiple times. Not sure if that is the best approach, but it should fix the issue at hand. Regards, Christian. ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-13 13:12 Trying to fix drm/prime: remove drm_prime_lookup_buf_by_handle Christian König @ 2025-06-13 13:12 ` Christian König 2025-06-13 14:04 ` Simona Vetter 2025-06-13 14:32 ` Trying to fix drm/prime: remove drm_prime_lookup_buf_by_handle Saarinen, Jani 1 sibling, 1 reply; 13+ messages in thread From: Christian König @ 2025-06-13 13:12 UTC (permalink / raw) To: jani.saarinen, jani.nikula, tursulin, simona.vetter, tzimmermann, dri-devel It is possible through flink or IOCTLs like MODE_GETFB2 to create multiple handles for the same underlying GEM object. But in prime we explicitely don't want to have multiple handles for the same DMA-buf. So just ignore it if a DMA-buf is exported with another handle. This was made obvious by removing the extra check in drm_gem_prime_handle_to_dmabuf() to not add the handle if we could already find it in the housekeeping structures. Signed-off-by: Christian König <christian.koenig@amd.com> --- drivers/gpu/drm/drm_prime.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 1d93b44c00c4..f5f30d947b61 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -113,6 +113,17 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, rb = *p; pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); + + /* + * Just ignore the new handle if we already have an handle for + * this DMA-buf. + */ + if (dma_buf == pos->dma_buf) { + dma_buf_put(dma_buf); + kfree(member); + return 0; + + } if (dma_buf > pos->dma_buf) p = &rb->rb_right; else -- 2.34.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-13 13:12 ` [PATCH] drm/prime: fix drm_prime_add_buf_handle Christian König @ 2025-06-13 14:04 ` Simona Vetter 2025-06-13 14:10 ` Simona Vetter 2025-06-13 14:12 ` Christian König 0 siblings, 2 replies; 13+ messages in thread From: Simona Vetter @ 2025-06-13 14:04 UTC (permalink / raw) To: Christian König Cc: jani.saarinen, jani.nikula, tursulin, simona.vetter, tzimmermann, dri-devel On Fri, Jun 13, 2025 at 03:12:01PM +0200, Christian König wrote: > It is possible through flink or IOCTLs like MODE_GETFB2 to create > multiple handles for the same underlying GEM object. > > But in prime we explicitely don't want to have multiple handles for the > same DMA-buf. So just ignore it if a DMA-buf is exported with another > handle. > > This was made obvious by removing the extra check in > drm_gem_prime_handle_to_dmabuf() to not add the handle if we could already > find it in the housekeeping structures. > > Signed-off-by: Christian König <christian.koenig@amd.com> > --- > drivers/gpu/drm/drm_prime.c | 11 +++++++++++ > 1 file changed, 11 insertions(+) > > diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c > index 1d93b44c00c4..f5f30d947b61 100644 > --- a/drivers/gpu/drm/drm_prime.c > +++ b/drivers/gpu/drm/drm_prime.c > @@ -113,6 +113,17 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, > > rb = *p; > pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); > + > + /* > + * Just ignore the new handle if we already have an handle for > + * this DMA-buf. > + */ > + if (dma_buf == pos->dma_buf) { > + dma_buf_put(dma_buf); > + kfree(member); > + return 0; This feels a bit brittle, because this case should only be possible when called from drm_gem_prime_handle_to_dmabuf and not from drm_gem_prime_fd_to_handle() (where it would indicate a real race and hence bug in our code). I think drm_gem_prime_fd_to_handle() should WARN_ON if it hits this case. Otherwise yes this is the functional change that I've missed :-/ Note that there's no race in the original code, because it's all protected by the file_priv->prime.lock. Which means I think you're claim that you've only widened the race with your patch is wrong. Cheers, Sima > + > + } > if (dma_buf > pos->dma_buf) > p = &rb->rb_right; > else > -- > 2.34.1 > -- Simona Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-13 14:04 ` Simona Vetter @ 2025-06-13 14:10 ` Simona Vetter 2025-06-17 14:11 ` Simona Vetter 2025-06-13 14:12 ` Christian König 1 sibling, 1 reply; 13+ messages in thread From: Simona Vetter @ 2025-06-13 14:10 UTC (permalink / raw) To: Christian König Cc: jani.saarinen, jani.nikula, tursulin, simona.vetter, tzimmermann, dri-devel On Fri, Jun 13, 2025 at 04:04:46PM +0200, Simona Vetter wrote: > On Fri, Jun 13, 2025 at 03:12:01PM +0200, Christian König wrote: > > It is possible through flink or IOCTLs like MODE_GETFB2 to create > > multiple handles for the same underlying GEM object. > > > > But in prime we explicitely don't want to have multiple handles for the > > same DMA-buf. So just ignore it if a DMA-buf is exported with another > > handle. > > > > This was made obvious by removing the extra check in > > drm_gem_prime_handle_to_dmabuf() to not add the handle if we could already > > find it in the housekeeping structures. > > > > Signed-off-by: Christian König <christian.koenig@amd.com> > > --- > > drivers/gpu/drm/drm_prime.c | 11 +++++++++++ > > 1 file changed, 11 insertions(+) > > > > diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c > > index 1d93b44c00c4..f5f30d947b61 100644 > > --- a/drivers/gpu/drm/drm_prime.c > > +++ b/drivers/gpu/drm/drm_prime.c > > @@ -113,6 +113,17 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, > > > > rb = *p; > > pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); > > + > > + /* > > + * Just ignore the new handle if we already have an handle for > > + * this DMA-buf. > > + */ > > + if (dma_buf == pos->dma_buf) { > > + dma_buf_put(dma_buf); > > + kfree(member); > > + return 0; > > This feels a bit brittle, because this case should only be possible when > called from drm_gem_prime_handle_to_dmabuf and not from > drm_gem_prime_fd_to_handle() (where it would indicate a real race and > hence bug in our code). > > I think drm_gem_prime_fd_to_handle() should WARN_ON if it hits this case. Simplest would be to return -EEXISTS here and then either silence that errno or warn about it in the two call sites. Not pretty, but everything else looks worse. -Sima > > Otherwise yes this is the functional change that I've missed :-/ Note that > there's no race in the original code, because it's all protected by the > file_priv->prime.lock. Which means I think you're claim that you've only > widened the race with your patch is wrong. > > Cheers, Sima > > > + > > + } > > if (dma_buf > pos->dma_buf) > > p = &rb->rb_right; > > else > > -- > > 2.34.1 > > > > -- > Simona Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch -- Simona Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-13 14:10 ` Simona Vetter @ 2025-06-17 14:11 ` Simona Vetter 2025-06-17 14:29 ` Simona Vetter 0 siblings, 1 reply; 13+ messages in thread From: Simona Vetter @ 2025-06-17 14:11 UTC (permalink / raw) To: Christian König Cc: jani.saarinen, jani.nikula, tursulin, simona.vetter, tzimmermann, dri-devel On Fri, Jun 13, 2025 at 04:10:22PM +0200, Simona Vetter wrote: > On Fri, Jun 13, 2025 at 04:04:46PM +0200, Simona Vetter wrote: > > On Fri, Jun 13, 2025 at 03:12:01PM +0200, Christian König wrote: > > > It is possible through flink or IOCTLs like MODE_GETFB2 to create > > > multiple handles for the same underlying GEM object. > > > > > > But in prime we explicitely don't want to have multiple handles for the > > > same DMA-buf. So just ignore it if a DMA-buf is exported with another > > > handle. > > > > > > This was made obvious by removing the extra check in > > > drm_gem_prime_handle_to_dmabuf() to not add the handle if we could already > > > find it in the housekeeping structures. > > > > > > Signed-off-by: Christian König <christian.koenig@amd.com> > > > --- > > > drivers/gpu/drm/drm_prime.c | 11 +++++++++++ > > > 1 file changed, 11 insertions(+) > > > > > > diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c > > > index 1d93b44c00c4..f5f30d947b61 100644 > > > --- a/drivers/gpu/drm/drm_prime.c > > > +++ b/drivers/gpu/drm/drm_prime.c > > > @@ -113,6 +113,17 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, > > > > > > rb = *p; > > > pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); > > > + > > > + /* > > > + * Just ignore the new handle if we already have an handle for > > > + * this DMA-buf. > > > + */ > > > + if (dma_buf == pos->dma_buf) { > > > + dma_buf_put(dma_buf); > > > + kfree(member); > > > + return 0; > > > > This feels a bit brittle, because this case should only be possible when > > called from drm_gem_prime_handle_to_dmabuf and not from > > drm_gem_prime_fd_to_handle() (where it would indicate a real race and > > hence bug in our code). > > > > I think drm_gem_prime_fd_to_handle() should WARN_ON if it hits this case. > > Simplest would be to return -EEXISTS here and then either silence that > errno or warn about it in the two call sites. Not pretty, but everything > else looks worse. Did you send a v2 for this one? I think we should at least sort out the regression and then figure out the longer-standing issue. Not even sure that's a regression from the r-b tree conversion or whether that goes back to my original linke-list walk code. -Sima > > Otherwise yes this is the functional change that I've missed :-/ Note that > > there's no race in the original code, because it's all protected by the > > file_priv->prime.lock. Which means I think you're claim that you've only > > widened the race with your patch is wrong. > > > > Cheers, Sima > > > > > + > > > + } > > > if (dma_buf > pos->dma_buf) > > > p = &rb->rb_right; > > > else > > > -- > > > 2.34.1 > > > > > > > -- > > Simona Vetter > > Software Engineer, Intel Corporation > > http://blog.ffwll.ch > > -- > Simona Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch -- Simona Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-17 14:11 ` Simona Vetter @ 2025-06-17 14:29 ` Simona Vetter 0 siblings, 0 replies; 13+ messages in thread From: Simona Vetter @ 2025-06-17 14:29 UTC (permalink / raw) To: Christian König Cc: jani.saarinen, jani.nikula, tursulin, tzimmermann, dri-devel On Tue, 17 Jun 2025 at 16:11, Simona Vetter <simona.vetter@ffwll.ch> wrote: > > On Fri, Jun 13, 2025 at 04:10:22PM +0200, Simona Vetter wrote: > > On Fri, Jun 13, 2025 at 04:04:46PM +0200, Simona Vetter wrote: > > > On Fri, Jun 13, 2025 at 03:12:01PM +0200, Christian König wrote: > > > > It is possible through flink or IOCTLs like MODE_GETFB2 to create > > > > multiple handles for the same underlying GEM object. > > > > > > > > But in prime we explicitely don't want to have multiple handles for the > > > > same DMA-buf. So just ignore it if a DMA-buf is exported with another > > > > handle. > > > > > > > > This was made obvious by removing the extra check in > > > > drm_gem_prime_handle_to_dmabuf() to not add the handle if we could already > > > > find it in the housekeeping structures. > > > > > > > > Signed-off-by: Christian König <christian.koenig@amd.com> > > > > --- > > > > drivers/gpu/drm/drm_prime.c | 11 +++++++++++ > > > > 1 file changed, 11 insertions(+) > > > > > > > > diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c > > > > index 1d93b44c00c4..f5f30d947b61 100644 > > > > --- a/drivers/gpu/drm/drm_prime.c > > > > +++ b/drivers/gpu/drm/drm_prime.c > > > > @@ -113,6 +113,17 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, > > > > > > > > rb = *p; > > > > pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); > > > > + > > > > + /* > > > > + * Just ignore the new handle if we already have an handle for > > > > + * this DMA-buf. > > > > + */ > > > > + if (dma_buf == pos->dma_buf) { > > > > + dma_buf_put(dma_buf); > > > > + kfree(member); > > > > + return 0; > > > > > > This feels a bit brittle, because this case should only be possible when > > > called from drm_gem_prime_handle_to_dmabuf and not from > > > drm_gem_prime_fd_to_handle() (where it would indicate a real race and > > > hence bug in our code). > > > > > > I think drm_gem_prime_fd_to_handle() should WARN_ON if it hits this case. > > > > Simplest would be to return -EEXISTS here and then either silence that > > errno or warn about it in the two call sites. Not pretty, but everything > > else looks worse. > > Did you send a v2 for this one? I think we should at least sort out the > regression and then figure out the longer-standing issue. Not even sure > that's a regression from the r-b tree conversion or whether that goes back > to my original linke-list walk code. Yeah I think flink or any of the other buffer handle duplication tricks just mess things up in funny ways. But as long as userspace doesn't do those, it should be all fine I think ... -Sima > > > Otherwise yes this is the functional change that I've missed :-/ Note that > > > there's no race in the original code, because it's all protected by the > > > file_priv->prime.lock. Which means I think you're claim that you've only > > > widened the race with your patch is wrong. > > > > > > Cheers, Sima > > > > > > > + > > > > + } > > > > if (dma_buf > pos->dma_buf) > > > > p = &rb->rb_right; > > > > else > > > > -- > > > > 2.34.1 > > > > > > > > > > -- > > > Simona Vetter > > > Software Engineer, Intel Corporation > > > http://blog.ffwll.ch > > > > -- > > Simona Vetter > > Software Engineer, Intel Corporation > > http://blog.ffwll.ch > > -- > Simona Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch -- Simona Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-13 14:04 ` Simona Vetter 2025-06-13 14:10 ` Simona Vetter @ 2025-06-13 14:12 ` Christian König 2025-06-13 14:35 ` Simona Vetter 1 sibling, 1 reply; 13+ messages in thread From: Christian König @ 2025-06-13 14:12 UTC (permalink / raw) To: Simona Vetter Cc: jani.saarinen, jani.nikula, tursulin, tzimmermann, dri-devel On 6/13/25 16:04, Simona Vetter wrote: > On Fri, Jun 13, 2025 at 03:12:01PM +0200, Christian König wrote: >> It is possible through flink or IOCTLs like MODE_GETFB2 to create >> multiple handles for the same underlying GEM object. >> >> But in prime we explicitely don't want to have multiple handles for the >> same DMA-buf. So just ignore it if a DMA-buf is exported with another >> handle. >> >> This was made obvious by removing the extra check in >> drm_gem_prime_handle_to_dmabuf() to not add the handle if we could already >> find it in the housekeeping structures. >> >> Signed-off-by: Christian König <christian.koenig@amd.com> >> --- >> drivers/gpu/drm/drm_prime.c | 11 +++++++++++ >> 1 file changed, 11 insertions(+) >> >> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c >> index 1d93b44c00c4..f5f30d947b61 100644 >> --- a/drivers/gpu/drm/drm_prime.c >> +++ b/drivers/gpu/drm/drm_prime.c >> @@ -113,6 +113,17 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, >> >> rb = *p; >> pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); >> + >> + /* >> + * Just ignore the new handle if we already have an handle for >> + * this DMA-buf. >> + */ >> + if (dma_buf == pos->dma_buf) { >> + dma_buf_put(dma_buf); >> + kfree(member); >> + return 0; > > This feels a bit brittle, because this case should only be possible when > called from drm_gem_prime_handle_to_dmabuf and not from > drm_gem_prime_fd_to_handle() (where it would indicate a real race and > hence bug in our code). > > I think drm_gem_prime_fd_to_handle() should WARN_ON if it hits this case. > > Otherwise yes this is the functional change that I've missed :-/ Note that > there's no race in the original code, because it's all protected by the > file_priv->prime.lock. Which means I think you're claim that you've only > widened the race with your patch is wrong. Yeah, agree. I'm always confused that there are two locks to protect the data structures. But there is indeed a problem in the existing code. What happens if a GEM handle duplicate is exported with drm_prime_add_buf_handle()? E.g. something created by GETFB2? IIRC AMD once had a test case which exercised exactly that. I'm not 100% sure what would happen here, but it looks not correct to me. Regards, Christian. > > Cheers, Sima > >> + >> + } >> if (dma_buf > pos->dma_buf) >> p = &rb->rb_right; >> else >> -- >> 2.34.1 >> > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-13 14:12 ` Christian König @ 2025-06-13 14:35 ` Simona Vetter 2025-06-13 15:03 ` Christian König 0 siblings, 1 reply; 13+ messages in thread From: Simona Vetter @ 2025-06-13 14:35 UTC (permalink / raw) To: Christian König Cc: Simona Vetter, jani.saarinen, jani.nikula, tursulin, tzimmermann, dri-devel On Fri, Jun 13, 2025 at 04:12:47PM +0200, Christian König wrote: > On 6/13/25 16:04, Simona Vetter wrote: > > On Fri, Jun 13, 2025 at 03:12:01PM +0200, Christian König wrote: > >> It is possible through flink or IOCTLs like MODE_GETFB2 to create > >> multiple handles for the same underlying GEM object. > >> > >> But in prime we explicitely don't want to have multiple handles for the > >> same DMA-buf. So just ignore it if a DMA-buf is exported with another > >> handle. > >> > >> This was made obvious by removing the extra check in > >> drm_gem_prime_handle_to_dmabuf() to not add the handle if we could already > >> find it in the housekeeping structures. > >> > >> Signed-off-by: Christian König <christian.koenig@amd.com> > >> --- > >> drivers/gpu/drm/drm_prime.c | 11 +++++++++++ > >> 1 file changed, 11 insertions(+) > >> > >> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c > >> index 1d93b44c00c4..f5f30d947b61 100644 > >> --- a/drivers/gpu/drm/drm_prime.c > >> +++ b/drivers/gpu/drm/drm_prime.c > >> @@ -113,6 +113,17 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, > >> > >> rb = *p; > >> pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); > >> + > >> + /* > >> + * Just ignore the new handle if we already have an handle for > >> + * this DMA-buf. > >> + */ > >> + if (dma_buf == pos->dma_buf) { > >> + dma_buf_put(dma_buf); > >> + kfree(member); > >> + return 0; > > > > This feels a bit brittle, because this case should only be possible when > > called from drm_gem_prime_handle_to_dmabuf and not from > > drm_gem_prime_fd_to_handle() (where it would indicate a real race and > > hence bug in our code). > > > > I think drm_gem_prime_fd_to_handle() should WARN_ON if it hits this case. > > > > Otherwise yes this is the functional change that I've missed :-/ Note that > > there's no race in the original code, because it's all protected by the > > file_priv->prime.lock. Which means I think you're claim that you've only > > widened the race with your patch is wrong. > > Yeah, agree. I'm always confused that there are two locks to protect the data structures. > > But there is indeed a problem in the existing code. What happens if a > GEM handle duplicate is exported with drm_prime_add_buf_handle()? E.g. > something created by GETFB2? The uniqueness guarantee only extends to FB2HANDLE, because that's the case userspace cannot figure out any other way. For flink import you can compare the flink name (those are global), and for other ioctl like GETFB(2) you just always get a new name that you need to close() yourself. I guess if you want a unique name for these others you could do a rount-trip through a dma-buf :-P But the reaons dma-buf import was special was that before we had a real inode or the KMP syscall there was just no way to compare dma-buf for identity, and so we needed a special guarantee. Probably the funniest piece of uapi we have :-/ > IIRC AMD once had a test case which exercised exactly that. I'm not 100% > sure what would happen here, but it looks not correct to me. Yeah I think the real-world GETFB are only for when you know it's not one of your own buffers, so all fine. Or we haven't tested this stuff enough yet ... Either way, userpace can fix it with a round-trip through FD2HANDLE. Cheers, Sima > > Regards, > Christian. > > > > > Cheers, Sima > > > >> + > >> + } > >> if (dma_buf > pos->dma_buf) > >> p = &rb->rb_right; > >> else > >> -- > >> 2.34.1 > >> > > > -- Simona Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-13 14:35 ` Simona Vetter @ 2025-06-13 15:03 ` Christian König 2025-06-16 10:38 ` Simona Vetter 0 siblings, 1 reply; 13+ messages in thread From: Christian König @ 2025-06-13 15:03 UTC (permalink / raw) To: Simona Vetter Cc: jani.saarinen, jani.nikula, tursulin, tzimmermann, dri-devel On 6/13/25 16:35, Simona Vetter wrote: > On Fri, Jun 13, 2025 at 04:12:47PM +0200, Christian König wrote: >> On 6/13/25 16:04, Simona Vetter wrote: >>> On Fri, Jun 13, 2025 at 03:12:01PM +0200, Christian König wrote: >>>> It is possible through flink or IOCTLs like MODE_GETFB2 to create >>>> multiple handles for the same underlying GEM object. >>>> >>>> But in prime we explicitely don't want to have multiple handles for the >>>> same DMA-buf. So just ignore it if a DMA-buf is exported with another >>>> handle. >>>> >>>> This was made obvious by removing the extra check in >>>> drm_gem_prime_handle_to_dmabuf() to not add the handle if we could already >>>> find it in the housekeeping structures. >>>> >>>> Signed-off-by: Christian König <christian.koenig@amd.com> >>>> --- >>>> drivers/gpu/drm/drm_prime.c | 11 +++++++++++ >>>> 1 file changed, 11 insertions(+) >>>> >>>> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c >>>> index 1d93b44c00c4..f5f30d947b61 100644 >>>> --- a/drivers/gpu/drm/drm_prime.c >>>> +++ b/drivers/gpu/drm/drm_prime.c >>>> @@ -113,6 +113,17 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, >>>> >>>> rb = *p; >>>> pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); >>>> + >>>> + /* >>>> + * Just ignore the new handle if we already have an handle for >>>> + * this DMA-buf. >>>> + */ >>>> + if (dma_buf == pos->dma_buf) { >>>> + dma_buf_put(dma_buf); >>>> + kfree(member); >>>> + return 0; >>> >>> This feels a bit brittle, because this case should only be possible when >>> called from drm_gem_prime_handle_to_dmabuf and not from >>> drm_gem_prime_fd_to_handle() (where it would indicate a real race and >>> hence bug in our code). >>> >>> I think drm_gem_prime_fd_to_handle() should WARN_ON if it hits this case. >>> >>> Otherwise yes this is the functional change that I've missed :-/ Note that >>> there's no race in the original code, because it's all protected by the >>> file_priv->prime.lock. Which means I think you're claim that you've only >>> widened the race with your patch is wrong. >> >> Yeah, agree. I'm always confused that there are two locks to protect the data structures. >> >> But there is indeed a problem in the existing code. What happens if a >> GEM handle duplicate is exported with drm_prime_add_buf_handle()? E.g. >> something created by GETFB2? > > The uniqueness guarantee only extends to FB2HANDLE, because that's the > case userspace cannot figure out any other way. Well that sounds like you didn't understood what I meant. The problem here is that we mess up FD2HANDLE if I'm not completely mistaken. > For flink import you can > compare the flink name (those are global), and for other ioctl like > GETFB(2) you just always get a new name that you need to close() yourself. > > I guess if you want a unique name for these others you could do a > rount-trip through a dma-buf :-P I advised that before as well, but exactly that's what is not working as far as I can see. Let's go over this example: 1. We have GEM handle 8. 2. Export GEM handle 8 as DMA-buf and get an FD. 3. Import the DMA-buf FD again with FD2HANDLE and get 8. 4. Now 8 is used in a FB config. 5. Somebody calls GETFB2 and gets 10 instead 8 for the same BO. 6. Now FD2HANDLE is called with 10 and here is what happens: drm_prime_lookup_buf_by_handle() is called for handle 10, so we don't find anything. obj->dma_buf is true so we branch into the if and call drm_prime_add_buf_handle() with handle 10. Now we have called drm_prime_add_buf_handle() both for handle 8 and handle 10 and so we have both 8 and 10 for the same DMA-buf in our tree. So FD2HANDLE could return either 8 or 10 depending on which is looked up first. I'm not 100% sure if that has any bad consequences, but I'm pretty sure that this is not intentional. Should we fix that? If yes than how? Regards, Christian. > > But the reaons dma-buf import was special was that before we had a real > inode or the KMP syscall there was just no way to compare dma-buf for > identity, and so we needed a special guarantee. Probably the funniest > piece of uapi we have :-/ > >> IIRC AMD once had a test case which exercised exactly that. I'm not 100% >> sure what would happen here, but it looks not correct to me. > > Yeah I think the real-world GETFB are only for when you know it's not one > of your own buffers, so all fine. Or we haven't tested this stuff enough > yet ... Either way, userpace can fix it with a round-trip through > FD2HANDLE. > > Cheers, Sima > >> >> Regards, >> Christian. >> >>> >>> Cheers, Sima >>> >>>> + >>>> + } >>>> if (dma_buf > pos->dma_buf) >>>> p = &rb->rb_right; >>>> else >>>> -- >>>> 2.34.1 >>>> >>> >> > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-13 15:03 ` Christian König @ 2025-06-16 10:38 ` Simona Vetter 2025-06-16 11:38 ` Christian König 0 siblings, 1 reply; 13+ messages in thread From: Simona Vetter @ 2025-06-16 10:38 UTC (permalink / raw) To: Christian König Cc: Simona Vetter, jani.saarinen, jani.nikula, tursulin, tzimmermann, dri-devel On Fri, Jun 13, 2025 at 05:03:39PM +0200, Christian König wrote: > On 6/13/25 16:35, Simona Vetter wrote: > > On Fri, Jun 13, 2025 at 04:12:47PM +0200, Christian König wrote: > >> On 6/13/25 16:04, Simona Vetter wrote: > >>> On Fri, Jun 13, 2025 at 03:12:01PM +0200, Christian König wrote: > >>>> It is possible through flink or IOCTLs like MODE_GETFB2 to create > >>>> multiple handles for the same underlying GEM object. > >>>> > >>>> But in prime we explicitely don't want to have multiple handles for the > >>>> same DMA-buf. So just ignore it if a DMA-buf is exported with another > >>>> handle. > >>>> > >>>> This was made obvious by removing the extra check in > >>>> drm_gem_prime_handle_to_dmabuf() to not add the handle if we could already > >>>> find it in the housekeeping structures. > >>>> > >>>> Signed-off-by: Christian König <christian.koenig@amd.com> > >>>> --- > >>>> drivers/gpu/drm/drm_prime.c | 11 +++++++++++ > >>>> 1 file changed, 11 insertions(+) > >>>> > >>>> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c > >>>> index 1d93b44c00c4..f5f30d947b61 100644 > >>>> --- a/drivers/gpu/drm/drm_prime.c > >>>> +++ b/drivers/gpu/drm/drm_prime.c > >>>> @@ -113,6 +113,17 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, > >>>> > >>>> rb = *p; > >>>> pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); > >>>> + > >>>> + /* > >>>> + * Just ignore the new handle if we already have an handle for > >>>> + * this DMA-buf. > >>>> + */ > >>>> + if (dma_buf == pos->dma_buf) { > >>>> + dma_buf_put(dma_buf); > >>>> + kfree(member); > >>>> + return 0; > >>> > >>> This feels a bit brittle, because this case should only be possible when > >>> called from drm_gem_prime_handle_to_dmabuf and not from > >>> drm_gem_prime_fd_to_handle() (where it would indicate a real race and > >>> hence bug in our code). > >>> > >>> I think drm_gem_prime_fd_to_handle() should WARN_ON if it hits this case. > >>> > >>> Otherwise yes this is the functional change that I've missed :-/ Note that > >>> there's no race in the original code, because it's all protected by the > >>> file_priv->prime.lock. Which means I think you're claim that you've only > >>> widened the race with your patch is wrong. > >> > >> Yeah, agree. I'm always confused that there are two locks to protect the data structures. > >> > >> But there is indeed a problem in the existing code. What happens if a > >> GEM handle duplicate is exported with drm_prime_add_buf_handle()? E.g. > >> something created by GETFB2? > > > > The uniqueness guarantee only extends to FB2HANDLE, because that's the > > case userspace cannot figure out any other way. > > Well that sounds like you didn't understood what I meant. > > The problem here is that we mess up FD2HANDLE if I'm not completely mistaken. > > > For flink import you can > > compare the flink name (those are global), and for other ioctl like > > GETFB(2) you just always get a new name that you need to close() yourself. > > > > I guess if you want a unique name for these others you could do a > > rount-trip through a dma-buf :-P I guess I should have elaborated what I mean here with this off-hand remark, see below. > I advised that before as well, but exactly that's what is not working as far as I can see. > > Let's go over this example: > 1. We have GEM handle 8. > 2. Export GEM handle 8 as DMA-buf and get an FD. > 3. Import the DMA-buf FD again with FD2HANDLE and get 8. > 4. Now 8 is used in a FB config. > 5. Somebody calls GETFB2 and gets 10 instead 8 for the same BO. > > 6. Now FD2HANDLE is called with 10 and here is what happens: > > drm_prime_lookup_buf_by_handle() is called for handle 10, so we > don't find anything. > > obj->dma_buf is true so we branch into the if and call > drm_prime_add_buf_handle() with handle 10. > > Now we have called drm_prime_add_buf_handle() both for handle 8 and > handle 10 and so we have both 8 and 10 for the same DMA-buf in our tree. So this is the case that broke, and which the various igt prime tests actually had testcases for. Unless I'm completely confused here now. > So FD2HANDLE could return either 8 or 10 depending on which is looked up > first. > > I'm not 100% sure if that has any bad consequences, but I'm pretty sure > that this is not intentional. > > Should we fix that? If yes than how? I dont think there's an issue, all we guarantee is that if you call FD2HANDLE or HANDLE2FD, then you get something consistent back. From a userspace pov there's two cases: 1. We've already seen this buffer, it got handle 8, that's the one we've stored in the lookup caches. If you then do GETFB2 you get handle 10, which could be confusing. So you do temp_dmabuf_fd = ioctl(HANDLE2FD, 10); new_id = ioctl(FD2HANDLE, temp_dmabuf_fd); close(temp_dma_buf_fd); ioctl(GEM_CLOSE, 10); At this point new_id is 8, and you already have that in your userspace cache, so all is good. 2. Userspace doesn't have the buffer already, but it doesn't know that. It does the exact dance as above, except this time around it gets back the same gem_handle as it got from GETFB2 and knows that it does not have to close that handle (since it's the only one), and that it should add that handle to the userspace-side dma-buf import/export side. It's a bit a contrived dance, but I don't think we have an issue here. Cheers, Sima > > Regards, > Christian. > > > > > But the reaons dma-buf import was special was that before we had a real > > inode or the KMP syscall there was just no way to compare dma-buf for > > identity, and so we needed a special guarantee. Probably the funniest > > piece of uapi we have :-/ > > > >> IIRC AMD once had a test case which exercised exactly that. I'm not 100% > >> sure what would happen here, but it looks not correct to me. > > > > Yeah I think the real-world GETFB are only for when you know it's not one > > of your own buffers, so all fine. Or we haven't tested this stuff enough > > yet ... Either way, userpace can fix it with a round-trip through > > FD2HANDLE. > > > > Cheers, Sima > > > >> > >> Regards, > >> Christian. > >> > >>> > >>> Cheers, Sima > >>> > >>>> + > >>>> + } > >>>> if (dma_buf > pos->dma_buf) > >>>> p = &rb->rb_right; > >>>> else > >>>> -- > >>>> 2.34.1 > >>>> > >>> > >> > > > -- Simona Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-16 10:38 ` Simona Vetter @ 2025-06-16 11:38 ` Christian König 2025-06-17 13:55 ` Simona Vetter 0 siblings, 1 reply; 13+ messages in thread From: Christian König @ 2025-06-16 11:38 UTC (permalink / raw) To: Simona Vetter Cc: jani.saarinen, jani.nikula, tursulin, tzimmermann, dri-devel On 6/16/25 12:38, Simona Vetter wrote: >> 6. Now FD2HANDLE is called with 10 and here is what happens: >> >> drm_prime_lookup_buf_by_handle() is called for handle 10, so we >> don't find anything. >> >> obj->dma_buf is true so we branch into the if and call >> drm_prime_add_buf_handle() with handle 10. >> >> Now we have called drm_prime_add_buf_handle() both for handle 8 and >> handle 10 and so we have both 8 and 10 for the same DMA-buf in our tree. > > So this is the case that broke, and which the various igt prime tests > actually had testcases for. Unless I'm completely confused here now. > >> So FD2HANDLE could return either 8 or 10 depending on which is looked up >> first. >> >> I'm not 100% sure if that has any bad consequences, but I'm pretty sure >> that this is not intentional. >> >> Should we fix that? If yes than how? > > I dont think there's an issue, all we guarantee is that if you call > FD2HANDLE or HANDLE2FD, then you get something consistent back. From a > userspace pov there's two cases: > > 1. We've already seen this buffer, it got handle 8, that's the one we've > stored in the lookup caches. If you then do GETFB2 you get handle 10, > which could be confusing. So you do > > temp_dmabuf_fd = ioctl(HANDLE2FD, 10); > new_id = ioctl(FD2HANDLE, temp_dmabuf_fd); > close(temp_dma_buf_fd); > ioctl(GEM_CLOSE, 10); > > At this point new_id is 8, No, exactly that is not guaranteed. The previous call to HANDLE2FD stored 10 into the lookup cache additionally to 8 with the same dma_buf pointer. And if you now get 8 or 10 as return from FD2HANDLE depends on how the red/black tree is balanced. It can be that 8 comes first or it can be that 10 comes first because the tree is only sorted by dma_buf pointer and that criteria is identical for both 8 and 10. As far as I can see this case is not correctly handled. Regards, Christian. and you already have that in your userspace > cache, so all is good. > > 2. Userspace doesn't have the buffer already, but it doesn't know that. It > does the exact dance as above, except this time around it gets back the > same gem_handle as it got from GETFB2 and knows that it does not have to > close that handle (since it's the only one), and that it should add that > handle to the userspace-side dma-buf import/export side. > > It's a bit a contrived dance, but I don't think we have an issue here. > > Cheers, Sima > >> >> Regards, >> Christian. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] drm/prime: fix drm_prime_add_buf_handle 2025-06-16 11:38 ` Christian König @ 2025-06-17 13:55 ` Simona Vetter 0 siblings, 0 replies; 13+ messages in thread From: Simona Vetter @ 2025-06-17 13:55 UTC (permalink / raw) To: Christian König Cc: Simona Vetter, jani.saarinen, jani.nikula, tursulin, tzimmermann, dri-devel On Mon, Jun 16, 2025 at 01:38:17PM +0200, Christian König wrote: > On 6/16/25 12:38, Simona Vetter wrote: > >> 6. Now FD2HANDLE is called with 10 and here is what happens: > >> > >> drm_prime_lookup_buf_by_handle() is called for handle 10, so we > >> don't find anything. > >> > >> obj->dma_buf is true so we branch into the if and call > >> drm_prime_add_buf_handle() with handle 10. > >> > >> Now we have called drm_prime_add_buf_handle() both for handle 8 and > >> handle 10 and so we have both 8 and 10 for the same DMA-buf in our tree. > > > > So this is the case that broke, and which the various igt prime tests > > actually had testcases for. Unless I'm completely confused here now. > > > >> So FD2HANDLE could return either 8 or 10 depending on which is looked up > >> first. > >> > >> I'm not 100% sure if that has any bad consequences, but I'm pretty sure > >> that this is not intentional. > >> > >> Should we fix that? If yes than how? > > > > I dont think there's an issue, all we guarantee is that if you call > > FD2HANDLE or HANDLE2FD, then you get something consistent back. From a > > userspace pov there's two cases: > > > > 1. We've already seen this buffer, it got handle 8, that's the one we've > > stored in the lookup caches. If you then do GETFB2 you get handle 10, > > which could be confusing. So you do > > > > temp_dmabuf_fd = ioctl(HANDLE2FD, 10); > > new_id = ioctl(FD2HANDLE, temp_dmabuf_fd); > > close(temp_dma_buf_fd); > > ioctl(GEM_CLOSE, 10); > > > > At this point new_id is 8, > > No, exactly that is not guaranteed. > > The previous call to HANDLE2FD stored 10 into the lookup cache > additionally to 8 with the same dma_buf pointer. > > And if you now get 8 or 10 as return from FD2HANDLE depends on how the > red/black tree is balanced. It can be that 8 comes first or it can be > that 10 comes first because the tree is only sorted by dma_buf pointer > and that criteria is identical for both 8 and 10. > > As far as I can see this case is not correctly handled. Hm right, I did type some testcases with flink, but not one that does funny stuff like this :-/ -Sima > > Regards, > Christian. > > and you already have that in your userspace > > cache, so all is good. > > > > 2. Userspace doesn't have the buffer already, but it doesn't know that. It > > does the exact dance as above, except this time around it gets back the > > same gem_handle as it got from GETFB2 and knows that it does not have to > > close that handle (since it's the only one), and that it should add that > > handle to the userspace-side dma-buf import/export side. > > > > It's a bit a contrived dance, but I don't think we have an issue here. > > > > Cheers, Sima > > > >> > >> Regards, > >> Christian. -- Simona Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 13+ messages in thread
* RE: Trying to fix drm/prime: remove drm_prime_lookup_buf_by_handle 2025-06-13 13:12 Trying to fix drm/prime: remove drm_prime_lookup_buf_by_handle Christian König 2025-06-13 13:12 ` [PATCH] drm/prime: fix drm_prime_add_buf_handle Christian König @ 2025-06-13 14:32 ` Saarinen, Jani 1 sibling, 0 replies; 13+ messages in thread From: Saarinen, Jani @ 2025-06-13 14:32 UTC (permalink / raw) To: Christian König, jani.nikula@linux.intel.com, tursulin@ursulin.net, simona.vetter@ffwll.ch, tzimmermann@suse.de, dri-devel@lists.freedesktop.org Hi, > -----Original Message----- > From: Christian König <ckoenig.leichtzumerken@gmail.com> > Sent: Friday, 13 June 2025 16.12 > To: Saarinen, Jani <jani.saarinen@intel.com>; jani.nikula@linux.intel.com; > tursulin@ursulin.net; simona.vetter@ffwll.ch; tzimmermann@suse.de; dri- > devel@lists.freedesktop.org > Subject: Trying to fix drm/prime: remove drm_prime_lookup_buf_by_handle > > The problem with this patch is that we now don't check if the handle already > existed any more, but just blindly try to add it again. > > This obviously breaks re-exporting DMA-bufs but also surfaces an issue that > we don't seem to take into account that multiple handles can point to the > same GEM object. > > Try to fix this by just ignoring adding the same DMA-buf to the rb tree multiple > times. Not sure if that is the best approach, but it should fix the issue at hand. Please send also to intel gfx and xe mailing lists to see how that works as now both as as discussed broken I915: https://intel-gfx-ci.01.org/tree/drm-tip/index.html?testfilter=prime Xe: https://intel-gfx-ci.01.org/tree/intel-xe/index.html?testfilter=prime > > Regards, > Christian. > ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-06-17 14:29 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-06-13 13:12 Trying to fix drm/prime: remove drm_prime_lookup_buf_by_handle Christian König 2025-06-13 13:12 ` [PATCH] drm/prime: fix drm_prime_add_buf_handle Christian König 2025-06-13 14:04 ` Simona Vetter 2025-06-13 14:10 ` Simona Vetter 2025-06-17 14:11 ` Simona Vetter 2025-06-17 14:29 ` Simona Vetter 2025-06-13 14:12 ` Christian König 2025-06-13 14:35 ` Simona Vetter 2025-06-13 15:03 ` Christian König 2025-06-16 10:38 ` Simona Vetter 2025-06-16 11:38 ` Christian König 2025-06-17 13:55 ` Simona Vetter 2025-06-13 14:32 ` Trying to fix drm/prime: remove drm_prime_lookup_buf_by_handle Saarinen, Jani
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.