diff options
Diffstat (limited to 'drivers/tty/vt')
-rw-r--r-- | drivers/tty/vt/consolemap.c | 1 | ||||
-rw-r--r-- | drivers/tty/vt/keyboard.c | 5 | ||||
-rw-r--r-- | drivers/tty/vt/selection.c | 50 | ||||
-rw-r--r-- | drivers/tty/vt/vt.c | 113 | ||||
-rw-r--r-- | drivers/tty/vt/vt_ioctl.c | 68 |
5 files changed, 112 insertions, 125 deletions
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c index a5f88cf0f61d..722a6690c70d 100644 --- a/drivers/tty/vt/consolemap.c +++ b/drivers/tty/vt/consolemap.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * consolemap.c * diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index f4166263bb3a..5d412df8e943 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Written for linux by Johan Myreen as a translation from * the assembly version by Linus (with diacriticals added) @@ -243,14 +244,14 @@ static int kd_sound_helper(struct input_handle *handle, void *data) return 0; } -static void kd_nosound(unsigned long ignored) +static void kd_nosound(struct timer_list *unused) { static unsigned int zero; input_handler_for_each_handle(&kbd_handler, &zero, kd_sound_helper); } -static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0); +static DEFINE_TIMER(kd_mksound_timer, kd_nosound); void kd_mksound(unsigned int hz, unsigned int ticks) { diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 7a4c8022c023..af4da9507180 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -156,42 +156,34 @@ static int store_utf8(u16 c, char *p) int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) { struct vc_data *vc = vc_cons[fg_console].d; - int sel_mode, new_sel_start, new_sel_end, spc; + int new_sel_start, new_sel_end, spc; + struct tiocl_selection v; char *bp, *obp; int i, ps, pe, multiplier; u16 c; int mode; poke_blanked_console(); + if (copy_from_user(&v, sel, sizeof(*sel))) + return -EFAULT; - { unsigned short xs, ys, xe, ye; + v.xs = limit(v.xs - 1, vc->vc_cols - 1); + v.ys = limit(v.ys - 1, vc->vc_rows - 1); + v.xe = limit(v.xe - 1, vc->vc_cols - 1); + v.ye = limit(v.ye - 1, vc->vc_rows - 1); + ps = v.ys * vc->vc_size_row + (v.xs << 1); + pe = v.ye * vc->vc_size_row + (v.xe << 1); - if (!access_ok(VERIFY_READ, sel, sizeof(*sel))) - return -EFAULT; - __get_user(xs, &sel->xs); - __get_user(ys, &sel->ys); - __get_user(xe, &sel->xe); - __get_user(ye, &sel->ye); - __get_user(sel_mode, &sel->sel_mode); - xs--; ys--; xe--; ye--; - xs = limit(xs, vc->vc_cols - 1); - ys = limit(ys, vc->vc_rows - 1); - xe = limit(xe, vc->vc_cols - 1); - ye = limit(ye, vc->vc_rows - 1); - ps = ys * vc->vc_size_row + (xs << 1); - pe = ye * vc->vc_size_row + (xe << 1); - - if (sel_mode == TIOCL_SELCLEAR) { - /* useful for screendump without selection highlights */ - clear_selection(); - return 0; - } - - if (mouse_reporting() && (sel_mode & TIOCL_SELMOUSEREPORT)) { - mouse_report(tty, sel_mode & TIOCL_SELBUTTONMASK, xs, ys); - return 0; - } - } + if (v.sel_mode == TIOCL_SELCLEAR) { + /* useful for screendump without selection highlights */ + clear_selection(); + return 0; + } + + if (mouse_reporting() && (v.sel_mode & TIOCL_SELMOUSEREPORT)) { + mouse_report(tty, v.sel_mode & TIOCL_SELBUTTONMASK, v.xs, v.ys); + return 0; + } if (ps > pe) /* make sel_start <= sel_end */ { @@ -210,7 +202,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t else use_unicode = 0; - switch (sel_mode) + switch (v.sel_mode) { case TIOCL_SELCHAR: /* character-by-character selection */ new_sel_start = ps; diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 2ebaba16f785..88b902c525d7 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 1991, 1992 Linus Torvalds */ @@ -102,6 +103,7 @@ #include <linux/uaccess.h> #include <linux/kdb.h> #include <linux/ctype.h> +#include <linux/bsearch.h> #define MAX_NR_CON_DRIVER 16 @@ -156,7 +158,7 @@ static void set_cursor(struct vc_data *vc); static void hide_cursor(struct vc_data *vc); static void console_callback(struct work_struct *ignored); static void con_driver_unregister_callback(struct work_struct *ignored); -static void blank_screen_t(unsigned long dummy); +static void blank_screen_t(struct timer_list *unused); static void set_palette(struct vc_data *vc); #define vt_get_kmsg_redirect() vt_kmsg_redirect(-1) @@ -228,7 +230,7 @@ static int scrollback_delta; */ int (*console_blank_hook)(int); -static DEFINE_TIMER(console_timer, blank_screen_t, 0, 0); +static DEFINE_TIMER(console_timer, blank_screen_t); static int blank_state; static int blank_timer_expired; enum { @@ -2142,22 +2144,15 @@ struct interval { uint32_t last; }; -static int bisearch(uint32_t ucs, const struct interval *table, int max) +static int ucs_cmp(const void *key, const void *elt) { - int min = 0; - int mid; + uint32_t ucs = *(uint32_t *)key; + struct interval e = *(struct interval *) elt; - if (ucs < table[0].first || ucs > table[max].last) - return 0; - while (max >= min) { - mid = (min + max) / 2; - if (ucs > table[mid].last) - min = mid + 1; - else if (ucs < table[mid].first) - max = mid - 1; - else - return 1; - } + if (ucs > e.last) + return 1; + else if (ucs < e.first) + return -1; return 0; } @@ -2169,7 +2164,12 @@ static int is_double_width(uint32_t ucs) { 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 }, { 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD } }; - return bisearch(ucs, double_width, ARRAY_SIZE(double_width) - 1); + if (ucs < double_width[0].first || + ucs > double_width[ARRAY_SIZE(double_width) - 1].last) + return 0; + + return bsearch(&ucs, double_width, ARRAY_SIZE(double_width), + sizeof(struct interval), ucs_cmp) != NULL; } static void con_flush(struct vc_data *vc, unsigned long draw_from, @@ -2205,7 +2205,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co console_lock(); vc = tty->driver_data; if (vc == NULL) { - printk(KERN_ERR "vt: argh, driver_data is NULL !\n"); + pr_err("vt: argh, driver_data is NULL !\n"); console_unlock(); return 0; } @@ -3190,20 +3190,21 @@ static int do_bind_con_driver(const struct consw *csw, int first, int last, pr_info("Console: switching "); if (!deflt) - printk(KERN_CONT "consoles %d-%d ", first+1, last+1); + pr_cont("consoles %d-%d ", first + 1, last + 1); if (j >= 0) { struct vc_data *vc = vc_cons[j].d; - printk(KERN_CONT "to %s %s %dx%d\n", - vc->vc_can_do_color ? "colour" : "mono", - desc, vc->vc_cols, vc->vc_rows); + pr_cont("to %s %s %dx%d\n", + vc->vc_can_do_color ? "colour" : "mono", + desc, vc->vc_cols, vc->vc_rows); if (k >= 0) { vc = vc_cons[k].d; update_screen(vc); } - } else - printk(KERN_CONT "to %s\n", desc); + } else { + pr_cont("to %s\n", desc); + } retval = 0; err: @@ -3622,9 +3623,8 @@ static int do_register_con_driver(const struct consw *csw, int first, int last) con_driver, con_dev_groups, "vtcon%i", con_driver->node); if (IS_ERR(con_driver->dev)) { - printk(KERN_WARNING "Unable to create device for %s; " - "errno = %ld\n", con_driver->desc, - PTR_ERR(con_driver->dev)); + pr_warn("Unable to create device for %s; errno = %ld\n", + con_driver->desc, PTR_ERR(con_driver->dev)); con_driver->dev = NULL; } else { vtconsole_init_device(con_driver); @@ -3761,8 +3761,8 @@ static int __init vtconsole_class_init(void) vtconsole_class = class_create(THIS_MODULE, "vtconsole"); if (IS_ERR(vtconsole_class)) { - printk(KERN_WARNING "Unable to create vt console class; " - "errno = %ld\n", PTR_ERR(vtconsole_class)); + pr_warn("Unable to create vt console class; errno = %ld\n", + PTR_ERR(vtconsole_class)); vtconsole_class = NULL; } @@ -3778,9 +3778,8 @@ static int __init vtconsole_class_init(void) "vtcon%i", con->node); if (IS_ERR(con->dev)) { - printk(KERN_WARNING "Unable to create " - "device for %s; errno = %ld\n", - con->desc, PTR_ERR(con->dev)); + pr_warn("Unable to create device for %s; errno = %ld\n", + con->desc, PTR_ERR(con->dev)); con->dev = NULL; } else { vtconsole_init_device(con); @@ -3930,7 +3929,7 @@ void unblank_screen(void) * (console operations can still happen at irq time, but only from printk which * has the console mutex. Not perfect yet, but better than no locking */ -static void blank_screen_t(unsigned long dummy) +static void blank_screen_t(struct timer_list *unused) { blank_timer_expired = 1; schedule_work(&console_work); @@ -4121,37 +4120,45 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op) return -EINVAL; if (op->charcount > 512) return -EINVAL; + 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; + + font.data = memdup_user(op->data, size); + if (IS_ERR(font.data)) + return PTR_ERR(font.data); + if (!op->height) { /* Need to guess font height [compat] */ int h, i; - u8 __user *charmap = op->data; - u8 tmp; - - /* If from KDFONTOP ioctl, don't allow things which can be done in userland, - so that we can get rid of this soon */ - if (!(op->flags & KD_FONT_FLAG_OLD)) + u8 *charmap = font.data; + + /* + * If from KDFONTOP ioctl, don't allow things which can be done + * in userland,so that we can get rid of this soon + */ + if (!(op->flags & KD_FONT_FLAG_OLD)) { + kfree(font.data); return -EINVAL; + } + for (h = 32; h > 0; h--) - for (i = 0; i < op->charcount; i++) { - if (get_user(tmp, &charmap[32*i+h-1])) - return -EFAULT; - if (tmp) + for (i = 0; i < op->charcount; i++) + if (charmap[32*i+h-1]) goto nonzero; - } + + kfree(font.data); return -EINVAL; + nonzero: op->height = h; } - 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; + font.charcount = op->charcount; - font.height = op->height; font.width = op->width; - font.data = memdup_user(op->data, size); - if (IS_ERR(font.data)) - return PTR_ERR(font.data); + font.height = op->height; + console_lock(); if (vc->vc_mode != KD_TEXT) rc = -EINVAL; diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 2d2b420598b2..d61be307256a 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -843,58 +843,44 @@ int vt_ioctl(struct tty_struct *tty, case VT_RESIZEX: { - struct vt_consize __user *vtconsize = up; - ushort ll,cc,vlin,clin,vcol,ccol; + struct vt_consize v; if (!perm) return -EPERM; - if (!access_ok(VERIFY_READ, vtconsize, - sizeof(struct vt_consize))) { - ret = -EFAULT; - break; - } + if (copy_from_user(&v, up, sizeof(struct vt_consize))) + return -EFAULT; /* FIXME: Should check the copies properly */ - __get_user(ll, &vtconsize->v_rows); - __get_user(cc, &vtconsize->v_cols); - __get_user(vlin, &vtconsize->v_vlin); - __get_user(clin, &vtconsize->v_clin); - __get_user(vcol, &vtconsize->v_vcol); - __get_user(ccol, &vtconsize->v_ccol); - vlin = vlin ? vlin : vc->vc_scan_lines; - if (clin) { - if (ll) { - if (ll != vlin/clin) { - /* Parameters don't add up */ - ret = -EINVAL; - break; - } - } else - ll = vlin/clin; + if (!v.v_vlin) + v.v_vlin = vc->vc_scan_lines; + if (v.v_clin) { + int rows = v.v_vlin/v.v_clin; + if (v.v_rows != rows) { + if (v.v_rows) /* Parameters don't add up */ + return -EINVAL; + v.v_rows = rows; + } } - if (vcol && ccol) { - if (cc) { - if (cc != vcol/ccol) { - ret = -EINVAL; - break; - } - } else - cc = vcol/ccol; + if (v.v_vcol && v.v_ccol) { + int cols = v.v_vcol/v.v_ccol; + if (v.v_cols != cols) { + if (v.v_cols) + return -EINVAL; + v.v_cols = cols; + } } - if (clin > 32) { - ret = -EINVAL; - break; - } - + if (v.v_clin > 32) + return -EINVAL; + for (i = 0; i < MAX_NR_CONSOLES; i++) { if (!vc_cons[i].d) continue; console_lock(); - if (vlin) - vc_cons[i].d->vc_scan_lines = vlin; - if (clin) - vc_cons[i].d->vc_font.height = clin; + if (v.v_vlin) + vc_cons[i].d->vc_scan_lines = v.v_vlin; + if (v.v_clin) + vc_cons[i].d->vc_font.height = v.v_clin; vc_cons[i].d->vc_resize_user = 1; - vc_resize(vc_cons[i].d, cc, ll); + vc_resize(vc_cons[i].d, v.v_cols, v.v_rows); console_unlock(); } break; |