summaryrefslogtreecommitdiff
path: root/drivers/tty/vt/selection.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-20 11:24:39 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-20 11:24:39 -0700
commit843ec558f91b8e8fdb6efc908f2c0506407cc750 (patch)
tree1866dccbc298390fc8686875942324075fd83f9d /drivers/tty/vt/selection.c
parent71e7ff2578c3bc67fd893a9ba7f69fd563f271de (diff)
parentfb8ebec00b04f921ea1614a7303f1a8e5e9e47c5 (diff)
downloadlinux-next-843ec558f91b8e8fdb6efc908f2c0506407cc750.tar.gz
Merge tag 'tty-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull TTY/serial patches from Greg KH: "tty and serial merge for 3.4-rc1 Here's the big serial and tty merge for the 3.4-rc1 tree. There's loads of fixes and reworks in here from Jiri for the tty layer, and a number of patches from Alan to help try to wrestle the vt layer into a sane model. Other than that, lots of driver updates and fixes, and other minor stuff, all detailed in the shortlog." * tag 'tty-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (132 commits) serial: pxa: add clk_prepare/clk_unprepare calls TTY: Wrong unicode value copied in con_set_unimap() serial: PL011: clear pending interrupts serial: bfin-uart: Don't access tty circular buffer in TX DMA interrupt after it is reset. vt: NULL dereference in vt_do_kdsk_ioctl() tty: serial: vt8500: fix annotations for probe/remove serial: remove back and forth conversions in serial_out_sync serial: use serial_port_in/out vs serial_in/out in 8250 serial: introduce generic port in/out helpers serial: reduce number of indirections in 8250 code serial: delete useless void casts in 8250.c serial: make 8250's serial_in shareable to other drivers. serial: delete last unused traces of pausing I/O in 8250 pch_uart: Add module parameter descriptions pch_uart: Use existing default_baud in setup_console pch_uart: Add user_uartclk parameter pch_uart: Add Fish River Island II uart clock quirks pch_uart: Use uartclk instead of base_baud mpc5200b/uart: select more tolerant uart prescaler on low baudrates tty: moxa: fix bit test in moxa_start() ...
Diffstat (limited to 'drivers/tty/vt/selection.c')
-rw-r--r--drivers/tty/vt/selection.c58
1 files changed, 43 insertions, 15 deletions
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 7a0a12ae5458..8e9b4be97a2d 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -30,6 +30,7 @@
extern void poke_blanked_console(void);
+/* FIXME: all this needs locking */
/* Variables for selection control. */
/* Use a dynamic buffer, instead of static (Dec 1994) */
struct vc_data *sel_cons; /* must not be deallocated */
@@ -61,10 +62,14 @@ sel_pos(int n)
use_unicode);
}
-/* remove the current selection highlight, if any,
- from the console holding the selection. */
-void
-clear_selection(void) {
+/**
+ * clear_selection - remove current selection
+ *
+ * Remove the current selection highlight, if any from the console
+ * holding the selection. The caller must hold the console lock.
+ */
+void clear_selection(void)
+{
highlight_pointer(-1); /* hide the pointer */
if (sel_start != -1) {
highlight(sel_start, sel_end);
@@ -74,7 +79,7 @@ clear_selection(void) {
/*
* User settable table: what characters are to be considered alphabetic?
- * 256 bits
+ * 256 bits. Locked by the console lock.
*/
static u32 inwordLut[8]={
0x00000000, /* control chars */
@@ -91,10 +96,20 @@ static inline int inword(const u16 c) {
return c > 0xff || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
}
-/* set inwordLut contents. Invoked by ioctl(). */
+/**
+ * set loadlut - load the LUT table
+ * @p: user table
+ *
+ * Load the LUT table from user space. The caller must hold the console
+ * lock. Make a temporary copy so a partial update doesn't make a mess.
+ */
int sel_loadlut(char __user *p)
{
- return copy_from_user(inwordLut, (u32 __user *)(p+4), 32) ? -EFAULT : 0;
+ u32 tmplut[8];
+ if (copy_from_user(tmplut, (u32 __user *)(p+4), 32))
+ return -EFAULT;
+ memcpy(inwordLut, tmplut, 32);
+ return 0;
}
/* does screen address p correspond to character at LH/RH edge of screen? */
@@ -130,7 +145,16 @@ static int store_utf8(u16 c, char *p)
}
}
-/* set the current selection. Invoked by ioctl() or by kernel code. */
+/**
+ * set_selection - set the current selection.
+ * @sel: user selection info
+ * @tty: the console tty
+ *
+ * Invoked by the ioctl handle for the vt layer.
+ *
+ * The entire selection process is managed under the console_lock. It's
+ * a lot under the lock but its hardly a performance path
+ */
int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
{
struct vc_data *vc = vc_cons[fg_console].d;
@@ -138,7 +162,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
char *bp, *obp;
int i, ps, pe, multiplier;
u16 c;
- struct kbd_struct *kbd = kbd_table + fg_console;
+ int mode;
poke_blanked_console();
@@ -182,7 +206,11 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
clear_selection();
sel_cons = vc_cons[fg_console].d;
}
- use_unicode = kbd && kbd->kbdmode == VC_UNICODE;
+ mode = vt_do_kdgkbmode(fg_console);
+ if (mode == K_UNICODE)
+ use_unicode = 1;
+ else
+ use_unicode = 0;
switch (sel_mode)
{
@@ -302,7 +330,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
* queue of the tty associated with the current console.
* Invoked by ioctl().
*
- * Locking: always called with BTM from vt_ioctl
+ * Locking: called without locks. Calls the ldisc wrongly with
+ * unsafe methods,
*/
int paste_selection(struct tty_struct *tty)
{
@@ -317,13 +346,12 @@ int paste_selection(struct tty_struct *tty)
poke_blanked_console();
console_unlock();
+ /* FIXME: wtf is this supposed to achieve ? */
ld = tty_ldisc_ref(tty);
- if (!ld) {
- tty_unlock();
+ if (!ld)
ld = tty_ldisc_ref_wait(tty);
- tty_lock();
- }
+ /* FIXME: this is completely unsafe */
add_wait_queue(&vc->paste_wait, &wait);
while (sel_buffer && sel_buffer_lth > pasted) {
set_current_state(TASK_INTERRUPTIBLE);