aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorJoonyoung Shim <jy0922.shim@samsung.com>2017-01-23 04:13:54 -0500
committerInki Dae <inki.dae@samsung.com>2017-01-30 18:50:35 -0500
commite41456bfc811f12b5dcda6f2d6849bdff68f6c0a (patch)
tree4403954b52737f4e9a46bc746859a0109b766af0 /drivers/gpu
parent8646dcb8a0def1c1cd4c855e08b17abce0cdc5d1 (diff)
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: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index fbd13fabdf2d..603d8425cca6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -1193,6 +1193,17 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
1193 if (!node) 1193 if (!node)
1194 return -ENOMEM; 1194 return -ENOMEM;
1195 1195
1196 /*
1197 * To avoid an integer overflow for the later size computations, we
1198 * enforce a maximum number of submitted commands here. This limit is
1199 * sufficient for all conceivable usage cases of the G2D.
1200 */
1201 if (req->cmd_nr > G2D_CMDLIST_DATA_NUM ||
1202 req->cmd_buf_nr > G2D_CMDLIST_DATA_NUM) {
1203 dev_err(dev, "number of submitted G2D commands exceeds limit\n");
1204 return -EINVAL;
1205 }
1206
1196 node->event = NULL; 1207 node->event = NULL;
1197 1208
1198 if (req->event_type != G2D_EVENT_NOT) { 1209 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 cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF; 1261 cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF;
1251 } 1262 }
1252 1263
1253 /* Check size of cmdlist: last 2 is about G2D_BITBLT_START */ 1264 /*
1265 * Check the size of cmdlist. The 2 that is added last comes from
1266 * the implicit G2D_BITBLT_START that is appended once we have
1267 * checked all the submitted commands.
1268 */
1254 size = cmdlist->last + req->cmd_nr * 2 + req->cmd_buf_nr * 2 + 2; 1269 size = cmdlist->last + req->cmd_nr * 2 + req->cmd_buf_nr * 2 + 2;
1255 if (size > G2D_CMDLIST_DATA_NUM) { 1270 if (size > G2D_CMDLIST_DATA_NUM) {
1256 dev_err(dev, "cmdlist size is too big\n"); 1271 dev_err(dev, "cmdlist size is too big\n");