diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2009-08-07 17:38:08 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-08-07 17:38:08 -0700 |
| commit | 98eebe071f4248c493288c6cff9644d727b877d6 (patch) | |
| tree | 7fd334824692739541a7ed4af103a72ebab5c2f1 /tty | |
| parent | d418d1311f152accae0f6282994664adb1f82b17 (diff) | |
| download | patches-98eebe071f4248c493288c6cff9644d727b877d6.tar.gz | |
more staging and other patches
Diffstat (limited to 'tty')
3 files changed, 526 insertions, 0 deletions
diff --git a/tty/tty-handle-vt-specific-compat-ioctls-in-vt-driver.patch b/tty/tty-handle-vt-specific-compat-ioctls-in-vt-driver.patch new file mode 100644 index 00000000000000..a5e079672e3d3d --- /dev/null +++ b/tty/tty-handle-vt-specific-compat-ioctls-in-vt-driver.patch @@ -0,0 +1,265 @@ +From arnd@arndb.de Fri Aug 7 17:04:14 2009 +From: Arnd Bergmann <arnd@arndb.de> +Date: Thu, 6 Aug 2009 15:09:28 +0200 +Subject: tty: handle VT specific compat ioctls in vt driver +To: linux-kernel@vger.kernel.org +Cc: Christoph Hellwig <hch@lst.de>, Andi Kleen <andi@firstfloor.org>, Alexander Viro <viro@zeniv.linux.org.uk>, Arnd Bergmann <arnd@arndb.de>, Greg Kroah-Hartman <gregkh@suse.de> +Message-ID: <1249564170-18627-4-git-send-email-arnd@arndb.de> + + +The VT specific compat_ioctl handlers are the only ones +in common code that require the BKL. Moving them into +the vt driver lets us remove the BKL from the other handlers +and cleans up the code. + +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/char/vt.c | 3 + drivers/char/vt_ioctl.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/tty.h | 3 + 3 files changed, 209 insertions(+) + +--- a/drivers/char/vt.c ++++ b/drivers/char/vt.c +@@ -2910,6 +2910,9 @@ static const struct tty_operations con_o + .flush_chars = con_flush_chars, + .chars_in_buffer = con_chars_in_buffer, + .ioctl = vt_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = vt_compat_ioctl, ++#endif + .stop = con_stop, + .start = con_start, + .throttle = con_throttle, +--- a/drivers/char/vt_ioctl.c ++++ b/drivers/char/vt_ioctl.c +@@ -16,6 +16,7 @@ + #include <linux/tty.h> + #include <linux/timer.h> + #include <linux/kernel.h> ++#include <linux/compat.h> + #include <linux/module.h> + #include <linux/kd.h> + #include <linux/vt.h> +@@ -1376,6 +1377,208 @@ void vc_SAK(struct work_struct *work) + release_console_sem(); + } + ++#ifdef CONFIG_COMPAT ++ ++struct compat_consolefontdesc { ++ unsigned short charcount; /* characters in font (256 or 512) */ ++ unsigned short charheight; /* scan lines per character (1-32) */ ++ compat_caddr_t chardata; /* font data in expanded form */ ++}; ++ ++static inline int ++compat_fontx_ioctl(int cmd, struct compat_consolefontdesc __user *user_cfd, ++ int perm, struct console_font_op *op) ++{ ++ struct compat_consolefontdesc cfdarg; ++ int i; ++ ++ if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc))) ++ return -EFAULT; ++ ++ switch (cmd) { ++ case PIO_FONTX: ++ if (!perm) ++ return -EPERM; ++ op->op = KD_FONT_OP_SET; ++ op->flags = KD_FONT_FLAG_OLD; ++ op->width = 8; ++ op->height = cfdarg.charheight; ++ op->charcount = cfdarg.charcount; ++ op->data = compat_ptr(cfdarg.chardata); ++ return con_font_op(vc_cons[fg_console].d, op); ++ case GIO_FONTX: ++ op->op = KD_FONT_OP_GET; ++ op->flags = KD_FONT_FLAG_OLD; ++ op->width = 8; ++ op->height = cfdarg.charheight; ++ op->charcount = cfdarg.charcount; ++ op->data = compat_ptr(cfdarg.chardata); ++ i = con_font_op(vc_cons[fg_console].d, op); ++ if (i) ++ return i; ++ cfdarg.charheight = op->height; ++ cfdarg.charcount = op->charcount; ++ if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc))) ++ return -EFAULT; ++ return 0; ++ } ++ return -EINVAL; ++} ++ ++struct compat_console_font_op { ++ compat_uint_t op; /* operation code KD_FONT_OP_* */ ++ compat_uint_t flags; /* KD_FONT_FLAG_* */ ++ compat_uint_t width, height; /* font size */ ++ compat_uint_t charcount; ++ compat_caddr_t data; /* font data with height fixed to 32 */ ++}; ++ ++static inline int ++compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop, ++ int perm, struct console_font_op *op, struct vc_data *vc) ++{ ++ int i; ++ ++ if (copy_from_user(op, fontop, sizeof(struct compat_console_font_op))) ++ return -EFAULT; ++ if (!perm && op->op != KD_FONT_OP_GET) ++ return -EPERM; ++ op->data = compat_ptr(((struct compat_console_font_op *)op)->data); ++ op->flags |= KD_FONT_FLAG_OLD; ++ i = con_font_op(vc, op); ++ if (i) ++ return i; ++ ((struct compat_console_font_op *)op)->data = (unsigned long)op->data; ++ if (copy_to_user(fontop, op, sizeof(struct compat_console_font_op))) ++ return -EFAULT; ++ return 0; ++} ++ ++struct compat_unimapdesc { ++ unsigned short entry_ct; ++ compat_caddr_t entries; ++}; ++ ++static inline int ++compat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud, ++ int perm, struct vc_data *vc) ++{ ++ struct compat_unimapdesc tmp; ++ struct unipair __user *tmp_entries; ++ ++ if (copy_from_user(&tmp, user_ud, sizeof tmp)) ++ return -EFAULT; ++ tmp_entries = compat_ptr(tmp.entries); ++ if (tmp_entries) ++ if (!access_ok(VERIFY_WRITE, tmp_entries, ++ tmp.entry_ct*sizeof(struct unipair))) ++ return -EFAULT; ++ switch (cmd) { ++ case PIO_UNIMAP: ++ if (!perm) ++ return -EPERM; ++ return con_set_unimap(vc, tmp.entry_ct, tmp_entries); ++ case GIO_UNIMAP: ++ if (!perm && fg_console != vc->vc_num) ++ return -EPERM; ++ return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp_entries); ++ } ++ return 0; ++} ++ ++long vt_compat_ioctl(struct tty_struct *tty, struct file * file, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct vc_data *vc = tty->driver_data; ++ struct console_font_op op; /* used in multiple places here */ ++ struct kbd_struct *kbd; ++ unsigned int console; ++ void __user *up = (void __user *)arg; ++ int perm; ++ int ret = 0; ++ ++ console = vc->vc_num; ++ ++ lock_kernel(); ++ ++ if (!vc_cons_allocated(console)) { /* impossible? */ ++ ret = -ENOIOCTLCMD; ++ goto out; ++ } ++ ++ /* ++ * To have permissions to do most of the vt ioctls, we either have ++ * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. ++ */ ++ perm = 0; ++ if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) ++ perm = 1; ++ ++ kbd = kbd_table + console; ++ switch (cmd) { ++ /* ++ * these need special handlers for incompatible data structures ++ */ ++ case PIO_FONTX: ++ case GIO_FONTX: ++ ret = compat_fontx_ioctl(cmd, up, perm, &op); ++ break; ++ ++ case KDFONTOP: ++ ret = compat_kdfontop_ioctl(up, perm, &op, vc); ++ break; ++ ++ case PIO_UNIMAP: ++ case GIO_UNIMAP: ++ ret = do_unimap_ioctl(cmd, up, perm, vc); ++ break; ++ ++ /* ++ * all these treat 'arg' as an integer ++ */ ++ case KIOCSOUND: ++ case KDMKTONE: ++#ifdef CONFIG_X86 ++ case KDADDIO: ++ case KDDELIO: ++#endif ++ case KDSETMODE: ++ case KDMAPDISP: ++ case KDUNMAPDISP: ++ case KDSKBMODE: ++ case KDSKBMETA: ++ case KDSKBLED: ++ case KDSETLED: ++ case KDSIGACCEPT: ++ case VT_ACTIVATE: ++ case VT_WAITACTIVE: ++ case VT_RELDISP: ++ case VT_DISALLOCATE: ++ case VT_RESIZE: ++ case VT_RESIZEX: ++ goto fallback; ++ ++ /* ++ * the rest has a compatible data structure behind arg, ++ * but we have to convert it to a proper 64 bit pointer. ++ */ ++ default: ++ arg = (unsigned long)compat_ptr(arg); ++ goto fallback; ++ } ++out: ++ unlock_kernel(); ++ return ret; ++ ++fallback: ++ unlock_kernel(); ++ return vt_ioctl(tty, file, cmd, arg); ++} ++ ++ ++#endif /* CONFIG_COMPAT */ ++ ++ + /* + * Performs the back end of a vt switch. Called under the console + * semaphore. +--- a/include/linux/tty.h ++++ b/include/linux/tty.h +@@ -538,5 +538,8 @@ extern void console_print(const char *); + extern int vt_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); + ++extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file, ++ unsigned int cmd, unsigned long arg); ++ + #endif /* __KERNEL__ */ + #endif diff --git a/tty/tty-n_tty-honor-opost-flag-for-echoes.patch b/tty/tty-n_tty-honor-opost-flag-for-echoes.patch new file mode 100644 index 00000000000000..88c623c7bf269d --- /dev/null +++ b/tty/tty-n_tty-honor-opost-flag-for-echoes.patch @@ -0,0 +1,162 @@ +From akpm@linux-foundation.org Fri Aug 7 16:55:12 2009 +From: Joe Peterson <joe@skyrush.com> +Date: Thu, 06 Aug 2009 16:10:53 -0700 +Subject: tty: n_tty: honor opost flag for echoes +To: greg@kroah.com +Cc: akpm@linux-foundation.org, joe@skyrush.com +Message-ID: <200908062310.n76NArWa014111@imap1.linux-foundation.org> + + +From: Joe Peterson <joe@skyrush.com> + +Fixes the following bug: + + http://bugs.linuxbase.org/show_bug.cgi?id=2692 + +Causes processing of echoed characters (output from the echo buffer) to +honor the O_OPOST flag. This re-establishes this behavior. + +Note that this and the next patch ("n_tty: move echoctl check and clean up +logic") were verified together by the bug reporters, and all tty tests now +pass. + +The tty tests are from the "Linux Standard Base" test suite: + + http://www.linuxfoundation.org/collaborate/workgroups/lsb + +Signed-off-by: Joe Peterson <joe@skyrush.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + + drivers/char/n_tty.c | 100 +++++++++++++++++++++++++++------------------------ + 1 file changed, 53 insertions(+), 47 deletions(-) + +--- a/drivers/char/n_tty.c ++++ b/drivers/char/n_tty.c +@@ -292,54 +292,56 @@ static int do_output_char(unsigned char + if (!space) + return -1; + +- switch (c) { +- case '\n': +- if (O_ONLRET(tty)) +- tty->column = 0; +- if (O_ONLCR(tty)) { +- if (space < 2) +- return -1; +- tty->canon_column = tty->column = 0; +- tty_put_char(tty, '\r'); +- tty_put_char(tty, c); +- return 2; +- } +- tty->canon_column = tty->column; +- break; +- case '\r': +- if (O_ONOCR(tty) && tty->column == 0) +- return 0; +- if (O_OCRNL(tty)) { +- c = '\n'; ++ if (O_OPOST(tty)) { ++ switch (c) { ++ case '\n': + if (O_ONLRET(tty)) ++ tty->column = 0; ++ if (O_ONLCR(tty)) { ++ if (space < 2) ++ return -1; + tty->canon_column = tty->column = 0; ++ tty_put_char(tty, '\r'); ++ tty_put_char(tty, c); ++ return 2; ++ } ++ tty->canon_column = tty->column; + break; +- } +- tty->canon_column = tty->column = 0; +- break; +- case '\t': +- spaces = 8 - (tty->column & 7); +- if (O_TABDLY(tty) == XTABS) { +- if (space < spaces) +- return -1; ++ case '\r': ++ if (O_ONOCR(tty) && tty->column == 0) ++ return 0; ++ if (O_OCRNL(tty)) { ++ c = '\n'; ++ if (O_ONLRET(tty)) ++ tty->canon_column = tty->column = 0; ++ break; ++ } ++ tty->canon_column = tty->column = 0; ++ break; ++ case '\t': ++ spaces = 8 - (tty->column & 7); ++ if (O_TABDLY(tty) == XTABS) { ++ if (space < spaces) ++ return -1; ++ tty->column += spaces; ++ tty->ops->write(tty, " ", spaces); ++ return spaces; ++ } + tty->column += spaces; +- tty->ops->write(tty, " ", spaces); +- return spaces; +- } +- tty->column += spaces; +- break; +- case '\b': +- if (tty->column > 0) +- tty->column--; +- break; +- default: +- if (!iscntrl(c)) { +- if (O_OLCUC(tty)) +- c = toupper(c); +- if (!is_continuation(c, tty)) +- tty->column++; ++ break; ++ case '\b': ++ if (tty->column > 0) ++ tty->column--; ++ break; ++ default: ++ if (!iscntrl(c)) { ++ if (O_OLCUC(tty)) ++ c = toupper(c); ++ if (!is_continuation(c, tty)) ++ tty->column++; ++ } ++ break; + } +- break; + } + + tty_put_char(tty, c); +@@ -351,8 +353,9 @@ static int do_output_char(unsigned char + * @c: character (or partial unicode symbol) + * @tty: terminal device + * +- * Perform OPOST processing. Returns -1 when the output device is +- * full and the character must be retried. ++ * Output a character (with OPOST processing if enabled). ++ * Returns -1 if the output device is full and the character ++ * must be retried. + * + * Locking: output_lock to protect column state and space left + * (also, this is called from n_tty_write under the +@@ -378,8 +381,11 @@ static int process_output(unsigned char + /** + * process_output_block - block post processor + * @tty: terminal device +- * @inbuf: user buffer +- * @nr: number of bytes ++ * @buf: character buffer ++ * @nr: number of bytes to output ++ * ++ * Output a block of characters (with OPOST processing - assumed enabled). ++ * Returns the number of characters output. + * + * This path is used to speed up block console writes, among other + * things when processing blocks of output data. It handles only diff --git a/tty/tty-n_tty-move-echoctl-check-and-clean-up-logic.patch b/tty/tty-n_tty-move-echoctl-check-and-clean-up-logic.patch new file mode 100644 index 00000000000000..a2eacc471cba38 --- /dev/null +++ b/tty/tty-n_tty-move-echoctl-check-and-clean-up-logic.patch @@ -0,0 +1,99 @@ +From akpm@linux-foundation.org Fri Aug 7 16:55:36 2009 +From: Joe Peterson <joe@skyrush.com> +Date: Thu, 06 Aug 2009 16:10:54 -0700 +Subject: tty: n_tty: move echoctl check and clean up logic +To: greg@kroah.com +Cc: akpm@linux-foundation.org, joe@skyrush.com +Message-ID: <200908062310.n76NAsRp014115@imap1.linux-foundation.org> + + +From: Joe Peterson <joe@skyrush.com> + +Check L_ECHOCTL before insertting a character in the echo buffer (rather +than as the buffer is processed), to be more consistent with when all +other L_ flags are checked. Also cleaned up the related logic. + +Note that this and the previous patch ("n_tty: honor opost flag for +echoes") were verified together by the reporters of the bug that patch +addresses (http://bugs.linuxbase.org/show_bug.cgi?id=2692), and all tty +tests now pass. + +Signed-off-by: Joe Peterson <joe@skyrush.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + + drivers/char/n_tty.c | 46 ++++++++++++++++++---------------------------- + 1 file changed, 18 insertions(+), 28 deletions(-) + +--- a/drivers/char/n_tty.c ++++ b/drivers/char/n_tty.c +@@ -578,33 +578,23 @@ static void process_echoes(struct tty_st + break; + + default: +- if (iscntrl(op)) { +- if (L_ECHOCTL(tty)) { +- /* +- * Ensure there is enough space +- * for the whole ctrl pair. +- */ +- if (space < 2) { +- no_space_left = 1; +- break; +- } +- tty_put_char(tty, '^'); +- tty_put_char(tty, op ^ 0100); +- tty->column += 2; +- space -= 2; +- } else { +- if (!space) { +- no_space_left = 1; +- break; +- } +- tty_put_char(tty, op); +- space--; +- } +- } + /* +- * If above falls through, this was an +- * undefined op. ++ * If the op is not a special byte code, ++ * it is a ctrl char tagged to be echoed ++ * as "^X" (where X is the letter ++ * representing the control char). ++ * Note that we must ensure there is ++ * enough space for the whole ctrl pair. ++ * + */ ++ if (space < 2) { ++ no_space_left = 1; ++ break; ++ } ++ tty_put_char(tty, '^'); ++ tty_put_char(tty, op ^ 0100); ++ tty->column += 2; ++ space -= 2; + cp += 2; + nr -= 2; + } +@@ -805,8 +795,8 @@ static void echo_char_raw(unsigned char + * Echo user input back onto the screen. This must be called only when + * L_ECHO(tty) is true. Called from the driver receive_buf path. + * +- * This variant tags control characters to be possibly echoed as +- * as "^X" (where X is the letter representing the control char). ++ * This variant tags control characters to be echoed as "^X" ++ * (where X is the letter representing the control char). + * + * Locking: echo_lock to protect the echo buffer + */ +@@ -819,7 +809,7 @@ static void echo_char(unsigned char c, s + add_echo_byte(ECHO_OP_START, tty); + add_echo_byte(ECHO_OP_START, tty); + } else { +- if (iscntrl(c) && c != '\t') ++ if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') + add_echo_byte(ECHO_OP_START, tty); + add_echo_byte(c, tty); + } |
