]> git.hungrycats.org Git - linux/commitdiff
[PATCH] con_set_font sanitized
authorAlexander Viro <viro@www.linux.org.uk>
Thu, 29 Jul 2004 15:47:55 +0000 (08:47 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 29 Jul 2004 15:47:55 +0000 (08:47 -0700)
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: Al Viro <viro@parcelfarce.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/char/vt.c
drivers/video/console/fbcon.c
drivers/video/console/newport_con.c
drivers/video/console/vgacon.c
include/linux/console.h

index 7f3d93ba1e7a34cb7a13b4b7357b6aabde09325c..90395eed34a96e6ef5b5581de75f1bc2411a47ec 100644 (file)
@@ -3081,14 +3081,12 @@ out:
 
 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;
 }
 
index 40f3a0010300e2c4cd173d1b1f316dcbd98139bb..005c5eed4b4e646b01897ab20e07655ab59f6b27 100644 (file)
@@ -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)
index ad59eed1793e8c0776308adb010ac3e54bbf8efb..b30ae70cbafeb959c7d08aa57ba701a81a33bbf1 100644 (file)
@@ -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)
index c3af575de98c215441fff66acdab13180397752f..91a1d022d44ff939d146c2960e0246088e83a257 100644 (file)
@@ -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;
 }
 
index 02da3a451213eb353645023e4bef713ee02a09ad..4db1f52f69502605adaf8165c7968a7932c0f66d 100644 (file)
@@ -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);