aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/vt_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/vt_ioctl.c')
-rw-r--r--drivers/char/vt_ioctl.c484
1 files changed, 433 insertions, 51 deletions
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 95189f288f8c..6aa10284104a 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -16,6 +16,8 @@
16#include <linux/tty.h> 16#include <linux/tty.h>
17#include <linux/timer.h> 17#include <linux/timer.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/compat.h>
20#include <linux/module.h>
19#include <linux/kd.h> 21#include <linux/kd.h>
20#include <linux/vt.h> 22#include <linux/vt.h>
21#include <linux/string.h> 23#include <linux/string.h>
@@ -62,6 +64,133 @@ extern struct tty_driver *console_driver;
62static void complete_change_console(struct vc_data *vc); 64static void complete_change_console(struct vc_data *vc);
63 65
64/* 66/*
67 * User space VT_EVENT handlers
68 */
69
70struct vt_event_wait {
71 struct list_head list;
72 struct vt_event event;
73 int done;
74};
75
76static LIST_HEAD(vt_events);
77static DEFINE_SPINLOCK(vt_event_lock);
78static DECLARE_WAIT_QUEUE_HEAD(vt_event_waitqueue);
79
80/**
81 * vt_event_post
82 * @event: the event that occurred
83 * @old: old console
84 * @new: new console
85 *
86 * Post an VT event to interested VT handlers
87 */
88
89void vt_event_post(unsigned int event, unsigned int old, unsigned int new)
90{
91 struct list_head *pos, *head;
92 unsigned long flags;
93 int wake = 0;
94
95 spin_lock_irqsave(&vt_event_lock, flags);
96 head = &vt_events;
97
98 list_for_each(pos, head) {
99 struct vt_event_wait *ve = list_entry(pos,
100 struct vt_event_wait, list);
101 if (!(ve->event.event & event))
102 continue;
103 ve->event.event = event;
104 /* kernel view is consoles 0..n-1, user space view is
105 console 1..n with 0 meaning current, so we must bias */
106 ve->event.oldev = old + 1;
107 ve->event.newev = new + 1;
108 wake = 1;
109 ve->done = 1;
110 }
111 spin_unlock_irqrestore(&vt_event_lock, flags);
112 if (wake)
113 wake_up_interruptible(&vt_event_waitqueue);
114}
115
116/**
117 * vt_event_wait - wait for an event
118 * @vw: our event
119 *
120 * Waits for an event to occur which completes our vt_event_wait
121 * structure. On return the structure has wv->done set to 1 for success
122 * or 0 if some event such as a signal ended the wait.
123 */
124
125static void vt_event_wait(struct vt_event_wait *vw)
126{
127 unsigned long flags;
128 /* Prepare the event */
129 INIT_LIST_HEAD(&vw->list);
130 vw->done = 0;
131 /* Queue our event */
132 spin_lock_irqsave(&vt_event_lock, flags);
133 list_add(&vw->list, &vt_events);
134 spin_unlock_irqrestore(&vt_event_lock, flags);
135 /* Wait for it to pass */
136 wait_event_interruptible(vt_event_waitqueue, vw->done);
137 /* Dequeue it */
138 spin_lock_irqsave(&vt_event_lock, flags);
139 list_del(&vw->list);
140 spin_unlock_irqrestore(&vt_event_lock, flags);
141}
142
143/**
144 * vt_event_wait_ioctl - event ioctl handler
145 * @arg: argument to ioctl
146 *
147 * Implement the VT_WAITEVENT ioctl using the VT event interface
148 */
149
150static int vt_event_wait_ioctl(struct vt_event __user *event)
151{
152 struct vt_event_wait vw;
153
154 if (copy_from_user(&vw.event, event, sizeof(struct vt_event)))
155 return -EFAULT;
156 /* Highest supported event for now */
157 if (vw.event.event & ~VT_MAX_EVENT)
158 return -EINVAL;
159
160 vt_event_wait(&vw);
161 /* If it occurred report it */
162 if (vw.done) {
163 if (copy_to_user(event, &vw.event, sizeof(struct vt_event)))
164 return -EFAULT;
165 return 0;
166 }
167 return -EINTR;
168}
169
170/**
171 * vt_waitactive - active console wait
172 * @event: event code
173 * @n: new console
174 *
175 * Helper for event waits. Used to implement the legacy
176 * event waiting ioctls in terms of events
177 */
178
179int vt_waitactive(int n)
180{
181 struct vt_event_wait vw;
182 do {
183 if (n == fg_console + 1)
184 break;
185 vw.event.event = VT_EVENT_SWITCH;
186 vt_event_wait(&vw);
187 if (vw.done == 0)
188 return -EINTR;
189 } while (vw.event.newev != n);
190 return 0;
191}
192
193/*
65 * these are the valid i/o ports we're allowed to change. they map all the 194 * these are the valid i/o ports we're allowed to change. they map all the
66 * video ports 195 * video ports
67 */ 196 */
@@ -360,6 +489,8 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_
360 return 0; 489 return 0;
361} 490}
362 491
492
493
363/* 494/*
364 * We handle the console-specific ioctl's here. We allow the 495 * We handle the console-specific ioctl's here. We allow the
365 * capability to modify any console, not just the fg_console. 496 * capability to modify any console, not just the fg_console.
@@ -842,6 +973,43 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
842 } 973 }
843 break; 974 break;
844 975
976 case VT_SETACTIVATE:
977 {
978 struct vt_setactivate vsa;
979
980 if (!perm)
981 goto eperm;
982
983 if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg,
984 sizeof(struct vt_setactivate))) {
985 ret = -EFAULT;
986 goto out;
987 }
988 if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
989 ret = -ENXIO;
990 else {
991 vsa.console--;
992 acquire_console_sem();
993 ret = vc_allocate(vsa.console);
994 if (ret == 0) {
995 struct vc_data *nvc;
996 /* This is safe providing we don't drop the
997 console sem between vc_allocate and
998 finishing referencing nvc */
999 nvc = vc_cons[vsa.console].d;
1000 nvc->vt_mode = vsa.mode;
1001 nvc->vt_mode.frsig = 0;
1002 put_pid(nvc->vt_pid);
1003 nvc->vt_pid = get_pid(task_pid(current));
1004 }
1005 release_console_sem();
1006 if (ret)
1007 break;
1008 /* Commence switch and lock */
1009 set_console(arg);
1010 }
1011 }
1012
845 /* 1013 /*
846 * wait until the specified VT has been activated 1014 * wait until the specified VT has been activated
847 */ 1015 */
@@ -851,7 +1019,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
851 if (arg == 0 || arg > MAX_NR_CONSOLES) 1019 if (arg == 0 || arg > MAX_NR_CONSOLES)
852 ret = -ENXIO; 1020 ret = -ENXIO;
853 else 1021 else
854 ret = vt_waitactive(arg - 1); 1022 ret = vt_waitactive(arg);
855 break; 1023 break;
856 1024
857 /* 1025 /*
@@ -1159,6 +1327,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
1159 ret = put_user(vc->vc_hi_font_mask, 1327 ret = put_user(vc->vc_hi_font_mask,
1160 (unsigned short __user *)arg); 1328 (unsigned short __user *)arg);
1161 break; 1329 break;
1330 case VT_WAITEVENT:
1331 ret = vt_event_wait_ioctl((struct vt_event __user *)arg);
1332 break;
1162 default: 1333 default:
1163 ret = -ENOIOCTLCMD; 1334 ret = -ENOIOCTLCMD;
1164 } 1335 }
@@ -1170,54 +1341,6 @@ eperm:
1170 goto out; 1341 goto out;
1171} 1342}
1172 1343
1173/*
1174 * Sometimes we want to wait until a particular VT has been activated. We
1175 * do it in a very simple manner. Everybody waits on a single queue and
1176 * get woken up at once. Those that are satisfied go on with their business,
1177 * while those not ready go back to sleep. Seems overkill to add a wait
1178 * to each vt just for this - usually this does nothing!
1179 */
1180static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue);
1181
1182/*
1183 * Sleeps until a vt is activated, or the task is interrupted. Returns
1184 * 0 if activation, -EINTR if interrupted by a signal handler.
1185 */
1186int vt_waitactive(int vt)
1187{
1188 int retval;
1189 DECLARE_WAITQUEUE(wait, current);
1190
1191 add_wait_queue(&vt_activate_queue, &wait);
1192 for (;;) {
1193 retval = 0;
1194
1195 /*
1196 * Synchronize with redraw_screen(). By acquiring the console
1197 * semaphore we make sure that the console switch is completed
1198 * before we return. If we didn't wait for the semaphore, we
1199 * could return at a point where fg_console has already been
1200 * updated, but the console switch hasn't been completed.
1201 */
1202 acquire_console_sem();
1203 set_current_state(TASK_INTERRUPTIBLE);
1204 if (vt == fg_console) {
1205 release_console_sem();
1206 break;
1207 }
1208 release_console_sem();
1209 retval = -ERESTARTNOHAND;
1210 if (signal_pending(current))
1211 break;
1212 schedule();
1213 }
1214 remove_wait_queue(&vt_activate_queue, &wait);
1215 __set_current_state(TASK_RUNNING);
1216 return retval;
1217}
1218
1219#define vt_wake_waitactive() wake_up(&vt_activate_queue)
1220
1221void reset_vc(struct vc_data *vc) 1344void reset_vc(struct vc_data *vc)
1222{ 1345{
1223 vc->vc_mode = KD_TEXT; 1346 vc->vc_mode = KD_TEXT;
@@ -1256,12 +1379,216 @@ void vc_SAK(struct work_struct *work)
1256 release_console_sem(); 1379 release_console_sem();
1257} 1380}
1258 1381
1382#ifdef CONFIG_COMPAT
1383
1384struct compat_consolefontdesc {
1385 unsigned short charcount; /* characters in font (256 or 512) */
1386 unsigned short charheight; /* scan lines per character (1-32) */
1387 compat_caddr_t chardata; /* font data in expanded form */
1388};
1389
1390static inline int
1391compat_fontx_ioctl(int cmd, struct compat_consolefontdesc __user *user_cfd,
1392 int perm, struct console_font_op *op)
1393{
1394 struct compat_consolefontdesc cfdarg;
1395 int i;
1396
1397 if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc)))
1398 return -EFAULT;
1399
1400 switch (cmd) {
1401 case PIO_FONTX:
1402 if (!perm)
1403 return -EPERM;
1404 op->op = KD_FONT_OP_SET;
1405 op->flags = KD_FONT_FLAG_OLD;
1406 op->width = 8;
1407 op->height = cfdarg.charheight;
1408 op->charcount = cfdarg.charcount;
1409 op->data = compat_ptr(cfdarg.chardata);
1410 return con_font_op(vc_cons[fg_console].d, op);
1411 case GIO_FONTX:
1412 op->op = KD_FONT_OP_GET;
1413 op->flags = KD_FONT_FLAG_OLD;
1414 op->width = 8;
1415 op->height = cfdarg.charheight;
1416 op->charcount = cfdarg.charcount;
1417 op->data = compat_ptr(cfdarg.chardata);
1418 i = con_font_op(vc_cons[fg_console].d, op);
1419 if (i)
1420 return i;
1421 cfdarg.charheight = op->height;
1422 cfdarg.charcount = op->charcount;
1423 if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc)))
1424 return -EFAULT;
1425 return 0;
1426 }
1427 return -EINVAL;
1428}
1429
1430struct compat_console_font_op {
1431 compat_uint_t op; /* operation code KD_FONT_OP_* */
1432 compat_uint_t flags; /* KD_FONT_FLAG_* */
1433 compat_uint_t width, height; /* font size */
1434 compat_uint_t charcount;
1435 compat_caddr_t data; /* font data with height fixed to 32 */
1436};
1437
1438static inline int
1439compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,
1440 int perm, struct console_font_op *op, struct vc_data *vc)
1441{
1442 int i;
1443
1444 if (copy_from_user(op, fontop, sizeof(struct compat_console_font_op)))
1445 return -EFAULT;
1446 if (!perm && op->op != KD_FONT_OP_GET)
1447 return -EPERM;
1448 op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
1449 op->flags |= KD_FONT_FLAG_OLD;
1450 i = con_font_op(vc, op);
1451 if (i)
1452 return i;
1453 ((struct compat_console_font_op *)op)->data = (unsigned long)op->data;
1454 if (copy_to_user(fontop, op, sizeof(struct compat_console_font_op)))
1455 return -EFAULT;
1456 return 0;
1457}
1458
1459struct compat_unimapdesc {
1460 unsigned short entry_ct;
1461 compat_caddr_t entries;
1462};
1463
1464static inline int
1465compat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud,
1466 int perm, struct vc_data *vc)
1467{
1468 struct compat_unimapdesc tmp;
1469 struct unipair __user *tmp_entries;
1470
1471 if (copy_from_user(&tmp, user_ud, sizeof tmp))
1472 return -EFAULT;
1473 tmp_entries = compat_ptr(tmp.entries);
1474 if (tmp_entries)
1475 if (!access_ok(VERIFY_WRITE, tmp_entries,
1476 tmp.entry_ct*sizeof(struct unipair)))
1477 return -EFAULT;
1478 switch (cmd) {
1479 case PIO_UNIMAP:
1480 if (!perm)
1481 return -EPERM;
1482 return con_set_unimap(vc, tmp.entry_ct, tmp_entries);
1483 case GIO_UNIMAP:
1484 if (!perm && fg_console != vc->vc_num)
1485 return -EPERM;
1486 return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp_entries);
1487 }
1488 return 0;
1489}
1490
1491long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
1492 unsigned int cmd, unsigned long arg)
1493{
1494 struct vc_data *vc = tty->driver_data;
1495 struct console_font_op op; /* used in multiple places here */
1496 struct kbd_struct *kbd;
1497 unsigned int console;
1498 void __user *up = (void __user *)arg;
1499 int perm;
1500 int ret = 0;
1501
1502 console = vc->vc_num;
1503
1504 lock_kernel();
1505
1506 if (!vc_cons_allocated(console)) { /* impossible? */
1507 ret = -ENOIOCTLCMD;
1508 goto out;
1509 }
1510
1511 /*
1512 * To have permissions to do most of the vt ioctls, we either have
1513 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
1514 */
1515 perm = 0;
1516 if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
1517 perm = 1;
1518
1519 kbd = kbd_table + console;
1520 switch (cmd) {
1521 /*
1522 * these need special handlers for incompatible data structures
1523 */
1524 case PIO_FONTX:
1525 case GIO_FONTX:
1526 ret = compat_fontx_ioctl(cmd, up, perm, &op);
1527 break;
1528
1529 case KDFONTOP:
1530 ret = compat_kdfontop_ioctl(up, perm, &op, vc);
1531 break;
1532
1533 case PIO_UNIMAP:
1534 case GIO_UNIMAP:
1535 ret = compat_unimap_ioctl(cmd, up, perm, vc);
1536 break;
1537
1538 /*
1539 * all these treat 'arg' as an integer
1540 */
1541 case KIOCSOUND:
1542 case KDMKTONE:
1543#ifdef CONFIG_X86
1544 case KDADDIO:
1545 case KDDELIO:
1546#endif
1547 case KDSETMODE:
1548 case KDMAPDISP:
1549 case KDUNMAPDISP:
1550 case KDSKBMODE:
1551 case KDSKBMETA:
1552 case KDSKBLED:
1553 case KDSETLED:
1554 case KDSIGACCEPT:
1555 case VT_ACTIVATE:
1556 case VT_WAITACTIVE:
1557 case VT_RELDISP:
1558 case VT_DISALLOCATE:
1559 case VT_RESIZE:
1560 case VT_RESIZEX:
1561 goto fallback;
1562
1563 /*
1564 * the rest has a compatible data structure behind arg,
1565 * but we have to convert it to a proper 64 bit pointer.
1566 */
1567 default:
1568 arg = (unsigned long)compat_ptr(arg);
1569 goto fallback;
1570 }
1571out:
1572 unlock_kernel();
1573 return ret;
1574
1575fallback:
1576 unlock_kernel();
1577 return vt_ioctl(tty, file, cmd, arg);
1578}
1579
1580
1581#endif /* CONFIG_COMPAT */
1582
1583
1259/* 1584/*
1260 * Performs the back end of a vt switch 1585 * Performs the back end of a vt switch. Called under the console
1586 * semaphore.
1261 */ 1587 */
1262static void complete_change_console(struct vc_data *vc) 1588static void complete_change_console(struct vc_data *vc)
1263{ 1589{
1264 unsigned char old_vc_mode; 1590 unsigned char old_vc_mode;
1591 int old = fg_console;
1265 1592
1266 last_console = fg_console; 1593 last_console = fg_console;
1267 1594
@@ -1325,7 +1652,7 @@ static void complete_change_console(struct vc_data *vc)
1325 /* 1652 /*
1326 * Wake anyone waiting for their VT to activate 1653 * Wake anyone waiting for their VT to activate
1327 */ 1654 */
1328 vt_wake_waitactive(); 1655 vt_event_post(VT_EVENT_SWITCH, old, vc->vc_num);
1329 return; 1656 return;
1330} 1657}
1331 1658
@@ -1398,3 +1725,58 @@ void change_console(struct vc_data *new_vc)
1398 1725
1399 complete_change_console(new_vc); 1726 complete_change_console(new_vc);
1400} 1727}
1728
1729/* Perform a kernel triggered VT switch for suspend/resume */
1730
1731static int disable_vt_switch;
1732
1733int vt_move_to_console(unsigned int vt, int alloc)
1734{
1735 int prev;
1736
1737 acquire_console_sem();
1738 /* Graphics mode - up to X */
1739 if (disable_vt_switch) {
1740 release_console_sem();
1741 return 0;
1742 }
1743 prev = fg_console;
1744
1745 if (alloc && vc_allocate(vt)) {
1746 /* we can't have a free VC for now. Too bad,
1747 * we don't want to mess the screen for now. */
1748 release_console_sem();
1749 return -ENOSPC;
1750 }
1751
1752 if (set_console(vt)) {
1753 /*
1754 * We're unable to switch to the SUSPEND_CONSOLE.
1755 * Let the calling function know so it can decide
1756 * what to do.
1757 */
1758 release_console_sem();
1759 return -EIO;
1760 }
1761 release_console_sem();
1762 if (vt_waitactive(vt + 1)) {
1763 pr_debug("Suspend: Can't switch VCs.");
1764 return -EINTR;
1765 }
1766 return prev;
1767}
1768
1769/*
1770 * Normally during a suspend, we allocate a new console and switch to it.
1771 * When we resume, we switch back to the original console. This switch
1772 * can be slow, so on systems where the framebuffer can handle restoration
1773 * of video registers anyways, there's little point in doing the console
1774 * switch. This function allows you to disable it by passing it '0'.
1775 */
1776void pm_set_vt_switch(int do_switch)
1777{
1778 acquire_console_sem();
1779 disable_vt_switch = !do_switch;
1780 release_console_sem();
1781}
1782EXPORT_SYMBOL(pm_set_vt_switch);