aboutsummaryrefslogtreecommitdiffstats
path: root/tty
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2009-08-07 17:38:08 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2009-08-07 17:38:08 -0700
commit98eebe071f4248c493288c6cff9644d727b877d6 (patch)
tree7fd334824692739541a7ed4af103a72ebab5c2f1 /tty
parentd418d1311f152accae0f6282994664adb1f82b17 (diff)
downloadpatches-98eebe071f4248c493288c6cff9644d727b877d6.tar.gz
more staging and other patches
Diffstat (limited to 'tty')
-rw-r--r--tty/tty-handle-vt-specific-compat-ioctls-in-vt-driver.patch265
-rw-r--r--tty/tty-n_tty-honor-opost-flag-for-echoes.patch162
-rw-r--r--tty/tty-n_tty-move-echoctl-check-and-clean-up-logic.patch99
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);
+ }