Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 871bdea6 authored by Michael Gehring's avatar Michael Gehring Committed by Greg Kroah-Hartman
Browse files

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: default avatarMichael Gehring <mg@ebfe.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent ef4f9d4f
Loading
Loading
Loading
Loading
+32 −36
Original line number Diff line number Diff line
@@ -3893,25 +3893,28 @@ 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)
/*
 * Load palette into the DAC registers. arg points to a colour
 * map, 3 bytes per colour, 16 colours, range from 0 to 255.
 */

int con_set_cmap(unsigned char __user *arg)
{
	int i, j, k;
	unsigned char colormap[3*16];

    WARN_CONSOLE_UNLOCKED();
	if (copy_from_user(colormap, arg, sizeof(colormap)))
		return -EFAULT;

    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++);
	console_lock();
	for (i = k = 0; i < 16; i++) {
		default_red[i] = colormap[k++];
		default_grn[i] = colormap[k++];
		default_blu[i] = colormap[k++];
	}
    if (set) {
	for (i = 0; i < MAX_NR_CONSOLES; i++)
	    if (vc_cons_allocated(i)) {
	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];
@@ -3919,35 +3922,28 @@ static int set_get_cmap(unsigned char __user *arg, int set)
		}
		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.
 */

int con_set_cmap(unsigned char __user *arg)
{
	int rc;

	console_lock();
	rc = set_get_cmap (arg,1);
	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)