Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amdgpu/vcn4: Prevent OOB reads when parsing dec msg

Check bounds against the end of the BO whenever we access the msg.

Signed-off-by: Benjamin Cheng <benjamin.cheng@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org

authored by

Benjamin Cheng and committed by
Alex Deucher
0a78f2ba b1930198

+18 -3
+18 -3
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
··· 1826 1826 struct ttm_operation_ctx ctx = { false, false }; 1827 1827 struct amdgpu_device *adev = p->adev; 1828 1828 struct amdgpu_bo_va_mapping *map; 1829 - uint32_t *msg, num_buffers; 1829 + uint32_t *msg, num_buffers, len_dw; 1830 1830 struct amdgpu_bo *bo; 1831 1831 uint64_t start, end; 1832 1832 unsigned int i; ··· 1847 1847 return -EINVAL; 1848 1848 } 1849 1849 1850 + if (end - addr < 16) { 1851 + DRM_ERROR("VCN messages must be at least 4 DWORDs!\n"); 1852 + return -EINVAL; 1853 + } 1854 + 1850 1855 bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; 1851 1856 amdgpu_bo_placement_from_domain(bo, bo->allowed_domains); 1852 1857 r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); ··· 1868 1863 1869 1864 msg = ptr + addr - start; 1870 1865 1871 - /* Check length */ 1872 1866 if (msg[1] > end - addr) { 1867 + DRM_ERROR("VCN message header does not fit in BO!\n"); 1873 1868 r = -EINVAL; 1874 1869 goto out; 1875 1870 } ··· 1877 1872 if (msg[3] != RDECODE_MSG_CREATE) 1878 1873 goto out; 1879 1874 1875 + len_dw = msg[1] / 4; 1880 1876 num_buffers = msg[2]; 1877 + 1878 + /* Verify that all indices fit within the claimed length. Each index is 4 DWORDs */ 1879 + if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) { 1880 + DRM_ERROR("VCN message has too many buffers!\n"); 1881 + r = -EINVAL; 1882 + goto out; 1883 + } 1884 + 1881 1885 for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) { 1882 1886 uint32_t offset, size, *create; 1883 1887 ··· 1896 1882 offset = msg[1]; 1897 1883 size = msg[2]; 1898 1884 1899 - if (offset + size > end) { 1885 + if (size < 4 || offset + size > end - addr) { 1886 + DRM_ERROR("VCN message buffer exceeds BO bounds!\n"); 1900 1887 r = -EINVAL; 1901 1888 goto out; 1902 1889 }