lkml.org 
[lkml]   [2012]   [Mar]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH] 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>
    ---
    drivers/tty/vt/vt.c | 68 ++++++++++++++++++++++++---------------------------
    1 file changed, 32 insertions(+), 36 deletions(-)

    diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
    index e716839..49c2dec 100644
    --- a/drivers/tty/vt/vt.c
    +++ b/drivers/tty/vt/vt.c
    @@ -3891,36 +3891,6 @@ static void set_palette(struct vc_data *vc)
    vc->vc_sw->con_set_palette(vc, color_table);
    }

    -static int set_get_cmap(unsigned char __user *arg, int set)
    -{
    - int i, j, k;
    -
    - WARN_CONSOLE_UNLOCKED();
    -
    - for (i = 0; i < 16; i++)
    - if (set) {
    - get_user(default_red[i], arg++);
    - get_user(default_grn[i], arg++);
    - get_user(default_blu[i], arg++);
    - } else {
    - put_user(default_red[i], arg++);
    - put_user(default_grn[i], arg++);
    - put_user(default_blu[i], arg++);
    - }
    - if (set) {
    - for (i = 0; i < MAX_NR_CONSOLES; i++)
    - if (vc_cons_allocated(i)) {
    - for (j = k = 0; j < 16; j++) {
    - vc_cons[i].d->vc_palette[k++] = default_red[j];
    - vc_cons[i].d->vc_palette[k++] = default_grn[j];
    - vc_cons[i].d->vc_palette[k++] = default_blu[j];
    - }
    - set_palette(vc_cons[i].d);
    - }
    - }
    - return 0;
    -}
    -
    /*
    * Load palette into the DAC registers. arg points to a colour
    * map, 3 bytes per colour, 16 colours, range from 0 to 255.
    @@ -3928,24 +3898,50 @@ static int set_get_cmap(unsigned char __user *arg, int set)

    int con_set_cmap(unsigned char __user *arg)
    {
    - int rc;
    + int i, j, k;
    + unsigned char colormap[3*16];
    +
    + if (copy_from_user(colormap, arg, sizeof(colormap)))
    + return -EFAULT;

    console_lock();
    - rc = set_get_cmap (arg,1);
    + for (i = k = 0; i < 16; i++) {
    + default_red[i] = colormap[k++];
    + default_grn[i] = colormap[k++];
    + default_blu[i] = colormap[k++];
    + }
    + for (i = 0; i < MAX_NR_CONSOLES; i++) {
    + if (!vc_cons_allocated(i))
    + continue;
    + for (j = k = 0; j < 16; j++) {
    + vc_cons[i].d->vc_palette[k++] = default_red[j];
    + vc_cons[i].d->vc_palette[k++] = default_grn[j];
    + vc_cons[i].d->vc_palette[k++] = default_blu[j];
    + }
    + set_palette(vc_cons[i].d);
    + }
    console_unlock();

    - return rc;
    + return 0;
    }

    int con_get_cmap(unsigned char __user *arg)
    {
    - int rc;
    + int i, k;
    + unsigned char colormap[3*16];

    console_lock();
    - rc = set_get_cmap (arg,0);
    + for (i = k = 0; i < 16; i++) {
    + colormap[k++] = default_red[i];
    + colormap[k++] = default_grn[i];
    + colormap[k++] = default_blu[i];
    + }
    console_unlock();

    - return rc;
    + if (copy_to_user(arg, colormap, sizeof(colormap)))
    + return -EFAULT;
    +
    + return 0;
    }

    void reset_palette(struct vc_data *vc)
    --
    1.7.9.4


    \
     
     \ /
      Last update: 2012-03-21 01:29    [W:0.034 / U:1.436 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site