diff options
author | Michael Gehring <mg@ebfe.org> | 2012-03-20 20:26:45 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-09 15:10:23 -0400 |
commit | 871bdea6f8c64517635bec352b8bec6b72a26d80 (patch) | |
tree | 786a6dede8222338409a05e316cf58435ee97e72 /drivers/tty/vt/vt.c | |
parent | ef4f9d4f09265b60fcb6bfa31a614ea84a72b7a8 (diff) |
tty/vt: handle bad user buffer in {G,P}IO_CMAP ioctl
set_get_cmap() ignored the result of {get,put}_user(), causing ioctl(vt,
{G,P}IO_CMAP, 0xdeadbeef) to silently fail.
Another side effect of this: calling the PIO_CMAP ioctl with an invalid
buffer would zero the default colormap and the palette for all vts (all
colors set to black).
Leave the default colormap intact and return -EFAULT when
reading/writing to the userspace buffer fails.
Signed-off-by: Michael Gehring <mg@ebfe.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/vt/vt.c')
-rw-r--r-- | drivers/tty/vt/vt.c | 68 |
1 files changed, 32 insertions, 36 deletions
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 3bdd4b19dd06..5836289bd861 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c | |||
@@ -3893,36 +3893,6 @@ static void set_palette(struct vc_data *vc) | |||
3893 | vc->vc_sw->con_set_palette(vc, color_table); | 3893 | vc->vc_sw->con_set_palette(vc, color_table); |
3894 | } | 3894 | } |
3895 | 3895 | ||
3896 | static int set_get_cmap(unsigned char __user *arg, int set) | ||
3897 | { | ||
3898 | int i, j, k; | ||
3899 | |||
3900 | WARN_CONSOLE_UNLOCKED(); | ||
3901 | |||
3902 | for (i = 0; i < 16; i++) | ||
3903 | if (set) { | ||
3904 | get_user(default_red[i], arg++); | ||
3905 | get_user(default_grn[i], arg++); | ||
3906 | get_user(default_blu[i], arg++); | ||
3907 | } else { | ||
3908 | put_user(default_red[i], arg++); | ||
3909 | put_user(default_grn[i], arg++); | ||
3910 | put_user(default_blu[i], arg++); | ||
3911 | } | ||
3912 | if (set) { | ||
3913 | for (i = 0; i < MAX_NR_CONSOLES; i++) | ||
3914 | if (vc_cons_allocated(i)) { | ||
3915 | for (j = k = 0; j < 16; j++) { | ||
3916 | vc_cons[i].d->vc_palette[k++] = default_red[j]; | ||
3917 | vc_cons[i].d->vc_palette[k++] = default_grn[j]; | ||
3918 | vc_cons[i].d->vc_palette[k++] = default_blu[j]; | ||
3919 | } | ||
3920 | set_palette(vc_cons[i].d); | ||
3921 | } | ||
3922 | } | ||
3923 | return 0; | ||
3924 | } | ||
3925 | |||
3926 | /* | 3896 | /* |
3927 | * Load palette into the DAC registers. arg points to a colour | 3897 | * Load palette into the DAC registers. arg points to a colour |
3928 | * map, 3 bytes per colour, 16 colours, range from 0 to 255. | 3898 | * map, 3 bytes per colour, 16 colours, range from 0 to 255. |
@@ -3930,24 +3900,50 @@ static int set_get_cmap(unsigned char __user *arg, int set) | |||
3930 | 3900 | ||
3931 | int con_set_cmap(unsigned char __user *arg) | 3901 | int con_set_cmap(unsigned char __user *arg) |
3932 | { | 3902 | { |
3933 | int rc; | 3903 | int i, j, k; |
3904 | unsigned char colormap[3*16]; | ||
3905 | |||
3906 | if (copy_from_user(colormap, arg, sizeof(colormap))) | ||
3907 | return -EFAULT; | ||
3934 | 3908 | ||
3935 | console_lock(); | 3909 | console_lock(); |
3936 | rc = set_get_cmap (arg,1); | 3910 | for (i = k = 0; i < 16; i++) { |
3911 | default_red[i] = colormap[k++]; | ||
3912 | default_grn[i] = colormap[k++]; | ||
3913 | default_blu[i] = colormap[k++]; | ||
3914 | } | ||
3915 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | ||
3916 | if (!vc_cons_allocated(i)) | ||
3917 | continue; | ||
3918 | for (j = k = 0; j < 16; j++) { | ||
3919 | vc_cons[i].d->vc_palette[k++] = default_red[j]; | ||
3920 | vc_cons[i].d->vc_palette[k++] = default_grn[j]; | ||
3921 | vc_cons[i].d->vc_palette[k++] = default_blu[j]; | ||
3922 | } | ||
3923 | set_palette(vc_cons[i].d); | ||
3924 | } | ||
3937 | console_unlock(); | 3925 | console_unlock(); |
3938 | 3926 | ||
3939 | return rc; | 3927 | return 0; |
3940 | } | 3928 | } |
3941 | 3929 | ||
3942 | int con_get_cmap(unsigned char __user *arg) | 3930 | int con_get_cmap(unsigned char __user *arg) |
3943 | { | 3931 | { |
3944 | int rc; | 3932 | int i, k; |
3933 | unsigned char colormap[3*16]; | ||
3945 | 3934 | ||
3946 | console_lock(); | 3935 | console_lock(); |
3947 | rc = set_get_cmap (arg,0); | 3936 | for (i = k = 0; i < 16; i++) { |
3937 | colormap[k++] = default_red[i]; | ||
3938 | colormap[k++] = default_grn[i]; | ||
3939 | colormap[k++] = default_blu[i]; | ||
3940 | } | ||
3948 | console_unlock(); | 3941 | console_unlock(); |
3949 | 3942 | ||
3950 | return rc; | 3943 | if (copy_to_user(arg, colormap, sizeof(colormap))) |
3944 | return -EFAULT; | ||
3945 | |||
3946 | return 0; | ||
3951 | } | 3947 | } |
3952 | 3948 | ||
3953 | void reset_palette(struct vc_data *vc) | 3949 | void reset_palette(struct vc_data *vc) |