mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
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>
This commit is contained in:
parent
ef4f9d4f09
commit
871bdea6f8
@ -3893,36 +3893,6 @@ static void set_palette(struct vc_data *vc)
|
|||||||
vc->vc_sw->con_set_palette(vc, color_table);
|
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
|
* Load palette into the DAC registers. arg points to a colour
|
||||||
* map, 3 bytes per colour, 16 colours, range from 0 to 255.
|
* 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)
|
|||||||
|
|
||||||
int con_set_cmap(unsigned char __user *arg)
|
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();
|
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();
|
console_unlock();
|
||||||
|
|
||||||
return rc;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int con_get_cmap(unsigned char __user *arg)
|
int con_get_cmap(unsigned char __user *arg)
|
||||||
{
|
{
|
||||||
int rc;
|
int i, k;
|
||||||
|
unsigned char colormap[3*16];
|
||||||
|
|
||||||
console_lock();
|
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();
|
console_unlock();
|
||||||
|
|
||||||
return rc;
|
if (copy_to_user(arg, colormap, sizeof(colormap)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_palette(struct vc_data *vc)
|
void reset_palette(struct vc_data *vc)
|
||||||
|
Loading…
Reference in New Issue
Block a user