Commit 7b083b32 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] con_set_font sanitized

con_font_set() sanitized.  We are passing console_font and flags into
the method in separate arguments and we are not messing with
console_font_op->data anymore - it's a userland pointer (to be annotated
several patches later in the series, due to another abuse of console_font_op
that needs to be fixed first), while console_font->data is kernel one
and they don't mix anymore.

We also do a sanity check (font width > 0) in the caller instead of
method instances, since we are already checking for width <= 32 and
height <= 32 there; doesn't make sense leaving that one in method
instances.
Signed-off-by: default avatarAl Viro <viro@parcelfarce.linux.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5e190739
......@@ -3081,14 +3081,12 @@ int con_font_get(int currcons, struct console_font_op *op)
int con_font_set(int currcons, struct console_font_op *op)
{
struct console_font_op old_op;
struct console_font font;
int rc = -EINVAL;
int size;
u8 *temp;
if (vt_cons[currcons]->vc_mode != KD_TEXT)
return -EINVAL;
memcpy(&old_op, op, sizeof(old_op));
if (!op->data)
return -EINVAL;
if (op->charcount > 512)
......@@ -3113,28 +3111,28 @@ int con_font_set(int currcons, struct console_font_op *op)
nonzero:
op->height = h;
}
if (op->width > 32 || op->height > 32)
if (op->width <= 0 || op->width > 32 || op->height > 32)
return -EINVAL;
size = (op->width+7)/8 * 32 * op->charcount;
if (size > max_font_size)
return -ENOSPC;
temp = kmalloc(size, GFP_KERNEL);
if (!temp)
font.charcount = op->charcount;
font.height = op->height;
font.width = op->width;
font.data = kmalloc(size, GFP_KERNEL);
if (!font.data)
return -ENOMEM;
if (copy_from_user(temp, op->data, size)) {
rc = -EFAULT;
goto out;
if (copy_from_user(font.data, op->data, size)) {
kfree(font.data);
return -EFAULT;
}
op->data = temp;
acquire_console_sem();
if (sw->con_font_set)
rc = sw->con_font_set(vc_cons[currcons].d, op);
rc = sw->con_font_set(vc_cons[currcons].d, &font, op->flags);
else
rc = -ENOSYS;
release_console_sem();
op->data = old_op.data;
out:
kfree(temp);
kfree(font.data);
return rc;
}
......
......@@ -2180,16 +2180,25 @@ static int fbcon_copy_font(struct vc_data *vc, int con)
return fbcon_do_set_font(vc, &crap, od->fontdata, od->userfont);
}
static int fbcon_set_font(struct vc_data *vc, struct console_font_op *op)
/*
* User asked to set font; we are guaranteed that
* a) width and height are in range 1..32
* b) charcount does not exceed 512
*/
static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigned flags)
{
int w = op->width;
int h = op->height;
unsigned charcount = font->charcount;
int w = font->width;
int h = font->height;
int size = h;
int i, k;
u8 *new_data, *data = op->data, *p;
u8 *new_data, *data = font->data, *p;
struct console_font_op crap = {.width = font->width,
.height = font->height,
.op = KD_FONT_OP_SET};
if ((w <= 0) || (w > 32)
|| (op->charcount != 256 && op->charcount != 512))
if (charcount != 256 && charcount != 512)
return -EINVAL;
if (w > 8) {
......@@ -2198,32 +2207,33 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font_op *op)
else
size *= 4;
}
size *= op->charcount;
size *= charcount;
new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER);
if (!
(new_data =
kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER)))
if (!new_data)
return -ENOMEM;
new_data += FONT_EXTRA_WORDS * sizeof(int);
FNTSIZE(new_data) = size;
FNTCHARCNT(new_data) = op->charcount;
FNTCHARCNT(new_data) = charcount;
REFCOUNT(new_data) = 0; /* usage counter */
p = new_data;
if (w <= 8) {
for (i = 0; i < op->charcount; i++) {
for (i = 0; i < charcount; i++) {
memcpy(p, data, h);
data += 32;
p += h;
}
} else if (w <= 16) {
h *= 2;
for (i = 0; i < op->charcount; i++) {
for (i = 0; i < charcount; i++) {
memcpy(p, data, h);
data += 64;
p += h;
}
} else if (w <= 24) {
for (i = 0; i < op->charcount; i++) {
for (i = 0; i < charcount; i++) {
int j;
for (j = 0; j < h; j++) {
memcpy(p, data, 3);
......@@ -2235,7 +2245,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font_op *op)
}
} else {
h *= 4;
for (i = 0; i < op->charcount; i++) {
for (i = 0; i < charcount; i++) {
memcpy(p, data, h);
data += 128;
p += h;
......@@ -2265,7 +2275,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font_op *op)
break;
}
}
return fbcon_do_set_font(vc, op, new_data, 1);
return fbcon_do_set_font(vc, &crap, new_data, 1);
}
static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
......
......@@ -477,7 +477,7 @@ static int newport_blank(struct vc_data *c, int blank)
return 1;
}
static int newport_set_font(int unit, struct console_font_op *op)
static int newport_set_font(int unit, struct console_font *op)
{
int w = op->width;
int h = op->height;
......@@ -548,9 +548,9 @@ static int newport_font_default(struct vc_data *vc, struct console_font *op, cha
return newport_set_def_font(vc->vc_num, op);
}
static int newport_font_set(struct vc_data *vc, struct console_font_op *op)
static int newport_font_set(struct vc_data *vc, struct console_font *font, unsigned flags)
{
return newport_set_font(vc->vc_num, op);
return newport_set_font(vc->vc_num, font);
}
static int newport_set_palette(struct vc_data *vc, unsigned char *table)
......
......@@ -907,22 +907,23 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
return 0;
}
static int vgacon_font_set(struct vc_data *c, struct console_font_op *op)
static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigned flags)
{
unsigned charcount = font->charcount;
int rc;
if (vga_video_type < VIDEO_TYPE_EGAM)
return -EINVAL;
if (op->width != 8 || (op->charcount != 256 && op->charcount != 512))
if (font->width != 8 || (charcount != 256 && charcount != 512))
return -EINVAL;
rc = vgacon_do_font_op(&state, op->data, 1, op->charcount == 512);
rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512);
if (rc)
return rc;
if (!(op->flags & KD_FONT_FLAG_DONT_RECALC))
rc = vgacon_adjust_height(c, op->height);
if (!(flags & KD_FONT_FLAG_DONT_RECALC))
rc = vgacon_adjust_height(c, font->height);
return rc;
}
......
......@@ -41,7 +41,7 @@ struct consw {
void (*con_bmove)(struct vc_data *, int, int, int, int, int, int);
int (*con_switch)(struct vc_data *);
int (*con_blank)(struct vc_data *, int, int);
int (*con_font_set)(struct vc_data *, struct console_font_op *);
int (*con_font_set)(struct vc_data *, struct console_font *, unsigned);
int (*con_font_get)(struct vc_data *, struct console_font_op *);
int (*con_font_default)(struct vc_data *, struct console_font *, char *);
int (*con_font_copy)(struct vc_data *, int);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment