Commit e41456bf authored by Joonyoung Shim's avatar Joonyoung Shim Committed by Inki Dae

drm/exynos: g2d: prevent integer overflow in

The size computations done in the ioctl function use an integer.
If userspace submits a request with req->cmd_nr or req->cmd_buf_nr
set to INT_MAX, the integer computations overflow later, leading
to potential (kernel) memory corruption.

Prevent this issue by enforcing a limit on the number of submitted
commands, so that we have enough headroom later for the size
computations.

Note that this change has no impact on the currently available
users in userspace, like e.g. libdrm/exynos.

While at it, also make a comment about the size computation more
detailed.
Signed-off-by: default avatarJoonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: default avatarTobias Jakobi <tjakobi@math.uni-bielefeld.de>
Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
parent 8646dcb8
...@@ -1193,6 +1193,17 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, ...@@ -1193,6 +1193,17 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
if (!node) if (!node)
return -ENOMEM; return -ENOMEM;
/*
* To avoid an integer overflow for the later size computations, we
* enforce a maximum number of submitted commands here. This limit is
* sufficient for all conceivable usage cases of the G2D.
*/
if (req->cmd_nr > G2D_CMDLIST_DATA_NUM ||
req->cmd_buf_nr > G2D_CMDLIST_DATA_NUM) {
dev_err(dev, "number of submitted G2D commands exceeds limit\n");
return -EINVAL;
}
node->event = NULL; node->event = NULL;
if (req->event_type != G2D_EVENT_NOT) { if (req->event_type != G2D_EVENT_NOT) {
...@@ -1250,7 +1261,11 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, ...@@ -1250,7 +1261,11 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF; cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF;
} }
/* Check size of cmdlist: last 2 is about G2D_BITBLT_START */ /*
* Check the size of cmdlist. The 2 that is added last comes from
* the implicit G2D_BITBLT_START that is appended once we have
* checked all the submitted commands.
*/
size = cmdlist->last + req->cmd_nr * 2 + req->cmd_buf_nr * 2 + 2; size = cmdlist->last + req->cmd_nr * 2 + req->cmd_buf_nr * 2 + 2;
if (size > G2D_CMDLIST_DATA_NUM) { if (size > G2D_CMDLIST_DATA_NUM) {
dev_err(dev, "cmdlist size is too big\n"); dev_err(dev, "cmdlist size is too big\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment