summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_modes.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2019-11-18 16:51:22 +0100
committerHans de Goede <hdegoede@redhat.com>2019-12-16 12:13:17 +0100
commit8582e244e5fe72d2e9ace186fa8f3ed3bb4122e1 (patch)
treed4320f21786b04080144a502d8c7826f5062cc25 /drivers/gpu/drm/drm_modes.c
parentdrm/rockchip: dsi: add px30 support (diff)
downloadlinux-8582e244e5fe72d2e9ace186fa8f3ed3bb4122e1.tar.xz
linux-8582e244e5fe72d2e9ace186fa8f3ed3bb4122e1.zip
drm/modes: parse_cmdline: Fix possible reference past end of string
Before this commit, if the last option of a video=... option is for example "rotate" without a "=<value>" after it then delim will point to the terminating 0 of the string, and value which is sets to <delim + 1> will point one position past the end of the string. This commit fixes this by enforcing that the contents of delim equals '=' as it should be for options which take a value, this check is done in a new drm_mode_parse_cmdline_int helper function which factors out the common integer parsing code for all the options which take an int. Acked-by: Maxime Ripard <mripard@kernel.org> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-1-hdegoede@redhat.com
Diffstat (limited to 'drivers/gpu/drm/drm_modes.c')
-rw-r--r--drivers/gpu/drm/drm_modes.c68
1 files changed, 30 insertions, 38 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 88232698d7a0..3c3c7435225f 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1568,11 +1568,34 @@ static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
return 0;
}
+static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret)
+{
+ const char *value;
+ char *endp;
+
+ /*
+ * delim must point to the '=', otherwise it is a syntax error and
+ * if delim points to the terminating zero, then delim + 1 wil point
+ * past the end of the string.
+ */
+ if (*delim != '=')
+ return -EINVAL;
+
+ value = delim + 1;
+ *int_ret = simple_strtol(value, &endp, 10);
+
+ /* Make sure we have parsed something */
+ if (endp == value)
+ return -EINVAL;
+
+ return 0;
+}
+
static int drm_mode_parse_cmdline_options(char *str, size_t len,
const struct drm_connector *connector,
struct drm_cmdline_mode *mode)
{
- unsigned int rotation = 0;
+ unsigned int deg, margin, rotation = 0;
char *sep = str;
while ((sep = strchr(sep, ','))) {
@@ -1588,13 +1611,7 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
}
if (!strncmp(option, "rotate", delim - option)) {
- const char *value = delim + 1;
- unsigned int deg;
-
- deg = simple_strtol(value, &sep, 10);
-
- /* Make sure we have parsed something */
- if (sep == value)
+ if (drm_mode_parse_cmdline_int(delim, &deg))
return -EINVAL;
switch (deg) {
@@ -1619,57 +1636,32 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
}
} else if (!strncmp(option, "reflect_x", delim - option)) {
rotation |= DRM_MODE_REFLECT_X;
- sep = delim;
} else if (!strncmp(option, "reflect_y", delim - option)) {
rotation |= DRM_MODE_REFLECT_Y;
- sep = delim;
} else if (!strncmp(option, "margin_right", delim - option)) {
- const char *value = delim + 1;
- unsigned int margin;
-
- margin = simple_strtol(value, &sep, 10);
-
- /* Make sure we have parsed something */
- if (sep == value)
+ if (drm_mode_parse_cmdline_int(delim, &margin))
return -EINVAL;
mode->tv_margins.right = margin;
} else if (!strncmp(option, "margin_left", delim - option)) {
- const char *value = delim + 1;
- unsigned int margin;
-
- margin = simple_strtol(value, &sep, 10);
-
- /* Make sure we have parsed something */
- if (sep == value)
+ if (drm_mode_parse_cmdline_int(delim, &margin))
return -EINVAL;
mode->tv_margins.left = margin;
} else if (!strncmp(option, "margin_top", delim - option)) {
- const char *value = delim + 1;
- unsigned int margin;
-
- margin = simple_strtol(value, &sep, 10);
-
- /* Make sure we have parsed something */
- if (sep == value)
+ if (drm_mode_parse_cmdline_int(delim, &margin))
return -EINVAL;
mode->tv_margins.top = margin;
} else if (!strncmp(option, "margin_bottom", delim - option)) {
- const char *value = delim + 1;
- unsigned int margin;
-
- margin = simple_strtol(value, &sep, 10);
-
- /* Make sure we have parsed something */
- if (sep == value)
+ if (drm_mode_parse_cmdline_int(delim, &margin))
return -EINVAL;
mode->tv_margins.bottom = margin;
} else {
return -EINVAL;
}
+ sep = delim;
}
mode->rotation_reflection = rotation;