drm/tegra: Check size of a submitted command buffer
PATCH 3/3 drm/tegra: Check size of a submitted command buffer
If command buffer claims a number of words that is higher than its BO can fit and a relocation lays past the BO, a kernel OOPS will be fired on that relocation address patching. This was triggered by an opentegra Xorg driver that erroneously pushed too many commands to the pushbuf.
[ 46.829393] Unable to handle kernel paging request at virtual address f09b2000
...
[<c04a3ba4>] (host1x_job_pin) from [<c04dfcd0>] (tegra_drm_submit+0x474/0x510) [<c04dfcd0>] (tegra_drm_submit) from [<c04deea0>] (tegra_submit+0x50/0x6c) [<c04deea0>] (tegra_submit) from [<c04c07c0>] (drm_ioctl+0x1e4/0x3ec) [<c04c07c0>] (drm_ioctl) from [<c02541a0>] (do_vfs_ioctl+0x9c/0x8e4) [<c02541a0>] (do_vfs_ioctl) from [<c0254a1c>] (SyS_ioctl+0x34/0x5c) [<c0254a1c>] (SyS_ioctl) from [<c0107640>] (ret_fast_syscall+0x0/0x3c)
--- drivers/gpu/drm/tegra/drm.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
drivers/gpu/drm/tegra/drm.c +14 -4
@@ -361,20 +361,30 @@ int tegra_drm_submit(struct tegra_drm_context *context,while (num_cmdbufs) {struct drm_tegra_cmdbuf cmdbuf; -struct host1x_bo *bo; +struct drm_gem_object *gem; +struct tegra_bo *bo;if (copy_from_user (&cmdbuf, cmdbufs,sizeof (cmdbuf))) { err = -EFAULT ; goto fail; } - bo =host1x_bo_lookup (file, cmdbuf.handle); -if (!bo) { + gem =drm_gem_object_lookup (file, cmdbuf.handle); +if (!gem) { err = -ENOENT ; goto fail; } -host1x_job_add_gather (job, bo, cmdbuf.words, cmdbuf.offset); +drm_gem_object_unreference_unlocked (gem); + +if (cmdbuf.words *4 > gem->size) { + err = -EINVAL ; + goto fail; + } + + bo =to_tegra_bo (gem); +host1x_job_add_gather (job, &bo->base, + cmdbuf.words, cmdbuf.offset); num_cmdbufs--; cmdbufs++; }
Signature · 1 line
2.12.2
Quoted 38 lines · Dmitry Osipenko
If command buffer claims a number of words that is higher than its BO can fit and a relocation lays past the BO, a kernel OOPS will be fired on that relocation address patching. This was triggered by an opentegra Xorg driver that erroneously pushed too many commands to the pushbuf.
[ 46.829393] Unable to handle kernel paging request at virtual address f09b2000...
[<c04a3ba4>] (host1x_job_pin) from [<c04dfcd0>] (tegra_drm_submit+0x474/0x510) [<c04dfcd0>] (tegra_drm_submit) from [<c04deea0>] (tegra_submit+0x50/0x6c) [<c04deea0>] (tegra_submit) from [<c04c07c0>] (drm_ioctl+0x1e4/0x3ec) [<c04c07c0>] (drm_ioctl) from [<c02541a0>] (do_vfs_ioctl+0x9c/0x8e4) [<c02541a0>] (do_vfs_ioctl) from [<c0254a1c>] (SyS_ioctl+0x34/0x5c) [<c0254a1c>] (SyS_ioctl) from [<c0107640>] (ret_fast_syscall+0x0/0x3c)Signed-off-by Dmitry Osipenko <[email protected]>--- drivers/gpu/drm/tegra/drm.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)drivers/gpu/drm/tegra/drm.c +2
-3@@ -361,20 +361,30 @@ int tegra_drm_submit(struct tegra_drm_context *context,while (num_cmdbufs) {struct drm_tegra_cmdbuf cmdbuf; -struct host1x_bo *bo; +struct drm_gem_object *gem; +struct tegra_bo *bo;if (copy_from_user (&cmdbuf, cmdbufs,sizeof (cmdbuf))) { err = -EFAULT ; goto fail; } - bo =host1x_bo_lookup (file, cmdbuf.handle); -if (!bo) {
drivers/gpu/drm/tegra/drm.c int tegra_drm_submit(struct tegra_drm_context *context, · line 380
Quoted 10 lines
drivers/gpu/drm/tegra/drm.c +5
-1+ gem =drm_gem_object_lookup (file, cmdbuf.handle); +if (!gem) { err = -ENOENT ; goto fail; } -host1x_job_add_gather (job, bo, cmdbuf.words, cmdbuf.offset); +drm_gem_object_unreference_unlocked (gem); + +if (cmdbuf.words *4 > gem->size) {
Shouldn't this be "cmdbuf.offset + cmdbuf.words * 4 > gem->size"?
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
A message that is not in the archive (sent off-list or not yet received): CABPQNSa8d+ZUpNFiLFdNhnYiQ+dE9=0GQdouCWxX=6C9je9zcw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Quoted 5 lines · Erik Faye-Lund
Quoted 1 line · Dmitry Osipenko
+ if (cmdbuf.words * 4 >
gem->size) {Shouldn't this be "cmdbuf.offset + cmdbuf.words * 4 >
gem->size"?
Seems yes, good catch. Thank you :)
Signature · 1 line
Dmitry