Patch "drm/radeon: make VCE handle check more strict" has been added to the 4.0-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
drm/radeon: make VCE handle check more strict
to the 4.0-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
drm-radeon-make-vce-handle-check-more-strict.patch
and it can be found in the queue-4.0 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
29c63fe22a17c64e54016040cd882481bd45ee5aMon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20K=C3=B6nig?= <[email protected]>
Date: Thu, 7 May 2015 15:19:22 +0200
Subject: drm/radeon: make VCE handle check more strict
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
From: =?UTF-8?q?Christian=20K=C3=B6nig?= <[email protected]>
commit 29c63fe22a17c64e54016040cd882481bd45ee5a upstream.
Invalid handles can crash the hw.
--- drivers/gpu/drm/radeon/radeon_vce.c | 65 ++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 17 deletions(-)
drivers/gpu/drm/radeon/radeon_vce.c +48 -17
@@ -493,18 +493,27 @@ int radeon_vce_cs_reloc(struct radeon_cs* * @p: parser context * @handle: handle to validate +* @allocated: allocated a new handle? * * Validates the handle and return the found session index or -EINVAL * we we don't have another free session index. */ -int radeon_vce_validate_handle (struct radeon_cs_parser *p,uint32_t handle) +static int radeon_vce_validate_handle (struct radeon_cs_parser *p, +uint32_t handle,bool *allocated) {unsigned i; + *allocated = false; +/* validate the handle */ for (i =0 ; i <RADEON_MAX_VCE_HANDLES ; ++i) { -if (atomic_read (&p->rdev->vce.handles[i]) == handle) +if (atomic_read (&p->rdev->vce.handles[i]) == handle) { +if (p->rdev->vce.filp[i] != p->filp) { +DRM_ERROR ("VCE handle collision detected!\n" ); +return -EINVAL ; + }return i; + } }/* handle not found try to alloc a new one */
@@ -512,6 +521,7 @@ int radeon_vce_validate_handle(struct raif (!atomic_cmpxchg (&p->rdev->vce.handles[i],0 , handle)) { p->rdev->vce.filp[i] = p->filp; p->rdev->vce.img_size[i] =0 ; + *allocated = true;return i; } }
@@ -529,10 +539,10 @@ int radeon_vce_validate_handle(struct raint radeon_vce_cs_parse (struct radeon_cs_parser *p) {int session_idx =-1 ; -bool destroyed = false; +bool destroyed = false, created = false, allocated = false;uint32_t tmp, handle =0 ;uint32_t *size = &tmp; -int i, r; +int i, r =0 ;while (p->idx < p->chunk_ib->length_dw) {uint32_t len =radeon_get_ib_value (p, p->idx);
@@ -540,18 +550,21 @@ int radeon_vce_cs_parse(struct radeon_csif ((len <8 ) || (len &3 )) {DRM_ERROR ("invalid VCE command length (%d)!\n" , len); -return -EINVAL ; + r = -EINVAL ; + goto out; }if (destroyed) {DRM_ERROR ("No other command allowed after destroy!\n" ); -return -EINVAL ; + r = -EINVAL ; + goto out; }switch (cmd) {case 0x00000001 :// session handle =radeon_get_ib_value (p, p->idx +2 ); - session_idx =radeon_vce_validate_handle (p, handle); + session_idx =radeon_vce_validate_handle (p, handle, + &allocated);if (session_idx <0 )return session_idx; size = &p->rdev->vce.img_size[session_idx];
@@ -561,6 +574,13 @@ int radeon_vce_cs_parse(struct radeon_csbreak ;case 0x01000001 :// create + created = true; +if (!allocated) { +DRM_ERROR ("Handle already in use!\n" ); + r = -EINVAL ; + goto out; + } + *size =radeon_get_ib_value (p, p->idx +8 ) *radeon_get_ib_value (p, p->idx +10 ) *8 *3 /2 ;
@@ -577,12 +597,12 @@ int radeon_vce_cs_parse(struct radeon_cs r =radeon_vce_cs_reloc (p, p->idx +10 , p->idx +9 , *size);if (r) -return r; + goto out; r =radeon_vce_cs_reloc (p, p->idx +12 , p->idx +11 , *size /3 );if (r) -return r; + goto out;break ;case 0x02000001 :// destroy
@@ -593,7 +613,7 @@ int radeon_vce_cs_parse(struct radeon_cs r =radeon_vce_cs_reloc (p, p->idx +3 , p->idx +2 , *size *2 );if (r) -return r; + goto out;break ;case 0x05000004 :// video bitstream buffer
@@ -601,36 +621,47 @@ int radeon_vce_cs_parse(struct radeon_cs r =radeon_vce_cs_reloc (p, p->idx +3 , p->idx +2 , tmp);if (r) -return r; + goto out;break ;case 0x05000005 :// feedback buffer r =radeon_vce_cs_reloc (p, p->idx +3 , p->idx +2 ,4096 );if (r) -return r; + goto out;break ;default :DRM_ERROR ("invalid VCE command (0x%x)!\n" , cmd); -return -EINVAL ; + r = -EINVAL ; + goto out; }if (session_idx ==-1 ) {DRM_ERROR ("no session command at start of IB\n" ); -return -EINVAL ; + r = -EINVAL ; + goto out; } p->idx += len /4 ; } -if (destroyed) { -/* IB contains a destroy msg, free the handle */ +if (allocated && !created) { +DRM_ERROR ("New session without create command!\n" ); + r = -ENOENT ; + } + +out: +if ((!r && destroyed) || (r && allocated)) { +/* +* IB contains a destroy msg or we have allocated an +* handle and got an error, anyway free the handle +*/ for (i =0 ; i <RADEON_MAX_VCE_HANDLES ; ++i)atomic_cmpxchg (&p->rdev->vce.handles[i], handle,0 ); } -return 0 ; +return r; }/**
Patches currently in stable-queue which might be from [email protected] are
queue-4.0/drm-radeon-more-strictly-validate-the-uvd-codec.patch queue-4.0/drm-radeon-make-vce-handle-check-more-strict.patch queue-4.0/drm-radeon-fix-userptr-bo-unpin-bug-v3.patch queue-4.0/drm-radeon-make-uvd-handle-checking-more-strict.patch queue-4.0/drm-radeon-disable-semaphores-for-uvd-v1-v2.patch