Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
4 : *
5 : * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
6 : * which can be dynamically activated and de-activated by the line
7 : * discipline handling modules (like SLIP).
8 : */
9 :
10 : #include <linux/types.h>
11 : #include <linux/termios.h>
12 : #include <linux/errno.h>
13 : #include <linux/sched/signal.h>
14 : #include <linux/kernel.h>
15 : #include <linux/major.h>
16 : #include <linux/tty.h>
17 : #include <linux/fcntl.h>
18 : #include <linux/string.h>
19 : #include <linux/mm.h>
20 : #include <linux/module.h>
21 : #include <linux/bitops.h>
22 : #include <linux/mutex.h>
23 : #include <linux/compat.h>
24 : #include <linux/termios_internal.h>
25 : #include "tty.h"
26 :
27 : #include <asm/io.h>
28 : #include <linux/uaccess.h>
29 :
30 : #undef TTY_DEBUG_WAIT_UNTIL_SENT
31 :
32 : #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
33 : # define tty_debug_wait_until_sent(tty, f, args...) tty_debug(tty, f, ##args)
34 : #else
35 : # define tty_debug_wait_until_sent(tty, f, args...) do {} while (0)
36 : #endif
37 :
38 : #undef DEBUG
39 :
40 : /*
41 : * Internal flag options for termios setting behavior
42 : */
43 : #define TERMIOS_FLUSH 1
44 : #define TERMIOS_WAIT 2
45 : #define TERMIOS_TERMIO 4
46 : #define TERMIOS_OLD 8
47 :
48 :
49 : /**
50 : * tty_chars_in_buffer - characters pending
51 : * @tty: terminal
52 : *
53 : * Return the number of bytes of data in the device private
54 : * output queue. If no private method is supplied there is assumed
55 : * to be no queue on the device.
56 : */
57 :
58 0 : unsigned int tty_chars_in_buffer(struct tty_struct *tty)
59 : {
60 0 : if (tty->ops->chars_in_buffer)
61 0 : return tty->ops->chars_in_buffer(tty);
62 : return 0;
63 : }
64 : EXPORT_SYMBOL(tty_chars_in_buffer);
65 :
66 : /**
67 : * tty_write_room - write queue space
68 : * @tty: terminal
69 : *
70 : * Return the number of bytes that can be queued to this device
71 : * at the present time. The result should be treated as a guarantee
72 : * and the driver cannot offer a value it later shrinks by more than
73 : * the number of bytes written. If no method is provided 2K is always
74 : * returned and data may be lost as there will be no flow control.
75 : */
76 :
77 0 : unsigned int tty_write_room(struct tty_struct *tty)
78 : {
79 0 : if (tty->ops->write_room)
80 0 : return tty->ops->write_room(tty);
81 : return 2048;
82 : }
83 : EXPORT_SYMBOL(tty_write_room);
84 :
85 : /**
86 : * tty_driver_flush_buffer - discard internal buffer
87 : * @tty: terminal
88 : *
89 : * Discard the internal output buffer for this device. If no method
90 : * is provided then either the buffer cannot be hardware flushed or
91 : * there is no buffer driver side.
92 : */
93 0 : void tty_driver_flush_buffer(struct tty_struct *tty)
94 : {
95 0 : if (tty->ops->flush_buffer)
96 0 : tty->ops->flush_buffer(tty);
97 0 : }
98 : EXPORT_SYMBOL(tty_driver_flush_buffer);
99 :
100 : /**
101 : * tty_unthrottle - flow control
102 : * @tty: terminal
103 : *
104 : * Indicate that a tty may continue transmitting data down the stack.
105 : * Takes the termios rwsem to protect against parallel throttle/unthrottle
106 : * and also to ensure the driver can consistently reference its own
107 : * termios data at this point when implementing software flow control.
108 : *
109 : * Drivers should however remember that the stack can issue a throttle,
110 : * then change flow control method, then unthrottle.
111 : */
112 :
113 0 : void tty_unthrottle(struct tty_struct *tty)
114 : {
115 0 : down_write(&tty->termios_rwsem);
116 0 : if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
117 0 : tty->ops->unthrottle)
118 0 : tty->ops->unthrottle(tty);
119 0 : tty->flow_change = 0;
120 0 : up_write(&tty->termios_rwsem);
121 0 : }
122 : EXPORT_SYMBOL(tty_unthrottle);
123 :
124 : /**
125 : * tty_throttle_safe - flow control
126 : * @tty: terminal
127 : *
128 : * Indicate that a tty should stop transmitting data down the stack.
129 : * tty_throttle_safe will only attempt throttle if tty->flow_change is
130 : * TTY_THROTTLE_SAFE. Prevents an accidental throttle due to race
131 : * conditions when throttling is conditional on factors evaluated prior to
132 : * throttling.
133 : *
134 : * Returns 0 if tty is throttled (or was already throttled)
135 : */
136 :
137 0 : int tty_throttle_safe(struct tty_struct *tty)
138 : {
139 0 : int ret = 0;
140 :
141 0 : mutex_lock(&tty->throttle_mutex);
142 0 : if (!tty_throttled(tty)) {
143 0 : if (tty->flow_change != TTY_THROTTLE_SAFE)
144 : ret = 1;
145 : else {
146 0 : set_bit(TTY_THROTTLED, &tty->flags);
147 0 : if (tty->ops->throttle)
148 0 : tty->ops->throttle(tty);
149 : }
150 : }
151 0 : mutex_unlock(&tty->throttle_mutex);
152 :
153 0 : return ret;
154 : }
155 :
156 : /**
157 : * tty_unthrottle_safe - flow control
158 : * @tty: terminal
159 : *
160 : * Similar to tty_unthrottle() but will only attempt unthrottle
161 : * if tty->flow_change is TTY_UNTHROTTLE_SAFE. Prevents an accidental
162 : * unthrottle due to race conditions when unthrottling is conditional
163 : * on factors evaluated prior to unthrottling.
164 : *
165 : * Returns 0 if tty is unthrottled (or was already unthrottled)
166 : */
167 :
168 0 : int tty_unthrottle_safe(struct tty_struct *tty)
169 : {
170 0 : int ret = 0;
171 :
172 0 : mutex_lock(&tty->throttle_mutex);
173 0 : if (tty_throttled(tty)) {
174 0 : if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
175 : ret = 1;
176 : else {
177 0 : clear_bit(TTY_THROTTLED, &tty->flags);
178 0 : if (tty->ops->unthrottle)
179 0 : tty->ops->unthrottle(tty);
180 : }
181 : }
182 0 : mutex_unlock(&tty->throttle_mutex);
183 :
184 0 : return ret;
185 : }
186 :
187 : /**
188 : * tty_wait_until_sent - wait for I/O to finish
189 : * @tty: tty we are waiting for
190 : * @timeout: how long we will wait
191 : *
192 : * Wait for characters pending in a tty driver to hit the wire, or
193 : * for a timeout to occur (eg due to flow control)
194 : *
195 : * Locking: none
196 : */
197 :
198 0 : void tty_wait_until_sent(struct tty_struct *tty, long timeout)
199 : {
200 : tty_debug_wait_until_sent(tty, "wait until sent, timeout=%ld\n", timeout);
201 :
202 0 : if (!timeout)
203 0 : timeout = MAX_SCHEDULE_TIMEOUT;
204 :
205 0 : timeout = wait_event_interruptible_timeout(tty->write_wait,
206 : !tty_chars_in_buffer(tty), timeout);
207 0 : if (timeout <= 0)
208 : return;
209 :
210 0 : if (timeout == MAX_SCHEDULE_TIMEOUT)
211 0 : timeout = 0;
212 :
213 0 : if (tty->ops->wait_until_sent)
214 0 : tty->ops->wait_until_sent(tty, timeout);
215 : }
216 : EXPORT_SYMBOL(tty_wait_until_sent);
217 :
218 :
219 : /*
220 : * Termios Helper Methods
221 : */
222 :
223 0 : static void unset_locked_termios(struct tty_struct *tty, const struct ktermios *old)
224 : {
225 0 : struct ktermios *termios = &tty->termios;
226 0 : struct ktermios *locked = &tty->termios_locked;
227 : int i;
228 :
229 : #define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
230 :
231 0 : NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
232 0 : NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
233 0 : NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
234 0 : NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
235 0 : termios->c_line = locked->c_line ? old->c_line : termios->c_line;
236 0 : for (i = 0; i < NCCS; i++)
237 0 : termios->c_cc[i] = locked->c_cc[i] ?
238 : old->c_cc[i] : termios->c_cc[i];
239 : /* FIXME: What should we do for i/ospeed */
240 0 : }
241 :
242 : /**
243 : * tty_termios_copy_hw - copy hardware settings
244 : * @new: New termios
245 : * @old: Old termios
246 : *
247 : * Propagate the hardware specific terminal setting bits from
248 : * the old termios structure to the new one. This is used in cases
249 : * where the hardware does not support reconfiguration or as a helper
250 : * in some cases where only minimal reconfiguration is supported
251 : */
252 :
253 0 : void tty_termios_copy_hw(struct ktermios *new, const struct ktermios *old)
254 : {
255 : /* The bits a dumb device handles in software. Smart devices need
256 : to always provide a set_termios method */
257 0 : new->c_cflag &= HUPCL | CREAD | CLOCAL;
258 0 : new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
259 0 : new->c_ispeed = old->c_ispeed;
260 0 : new->c_ospeed = old->c_ospeed;
261 0 : }
262 : EXPORT_SYMBOL(tty_termios_copy_hw);
263 :
264 : /**
265 : * tty_termios_hw_change - check for setting change
266 : * @a: termios
267 : * @b: termios to compare
268 : *
269 : * Check if any of the bits that affect a dumb device have changed
270 : * between the two termios structures, or a speed change is needed.
271 : */
272 :
273 0 : bool tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b)
274 : {
275 0 : if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
276 : return true;
277 0 : if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
278 : return true;
279 0 : return false;
280 : }
281 : EXPORT_SYMBOL(tty_termios_hw_change);
282 :
283 : /**
284 : * tty_get_char_size - get size of a character
285 : * @cflag: termios cflag value
286 : *
287 : * Get the size (in bits) of a character depending on @cflag's %CSIZE
288 : * setting.
289 : */
290 0 : unsigned char tty_get_char_size(unsigned int cflag)
291 : {
292 0 : switch (cflag & CSIZE) {
293 : case CS5:
294 : return 5;
295 : case CS6:
296 0 : return 6;
297 : case CS7:
298 0 : return 7;
299 : case CS8:
300 : default:
301 0 : return 8;
302 : }
303 : }
304 : EXPORT_SYMBOL_GPL(tty_get_char_size);
305 :
306 : /**
307 : * tty_get_frame_size - get size of a frame
308 : * @cflag: termios cflag value
309 : *
310 : * Get the size (in bits) of a frame depending on @cflag's %CSIZE, %CSTOPB,
311 : * and %PARENB setting. The result is a sum of character size, start and
312 : * stop bits -- one bit each -- second stop bit (if set), and parity bit
313 : * (if set).
314 : */
315 0 : unsigned char tty_get_frame_size(unsigned int cflag)
316 : {
317 0 : unsigned char bits = 2 + tty_get_char_size(cflag);
318 :
319 0 : if (cflag & CSTOPB)
320 0 : bits++;
321 0 : if (cflag & PARENB)
322 0 : bits++;
323 0 : if (cflag & ADDRB)
324 0 : bits++;
325 :
326 0 : return bits;
327 : }
328 : EXPORT_SYMBOL_GPL(tty_get_frame_size);
329 :
330 : /**
331 : * tty_set_termios - update termios values
332 : * @tty: tty to update
333 : * @new_termios: desired new value
334 : *
335 : * Perform updates to the termios values set on this terminal.
336 : * A master pty's termios should never be set.
337 : *
338 : * Locking: termios_rwsem
339 : */
340 :
341 0 : int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
342 : {
343 : struct ktermios old_termios;
344 : struct tty_ldisc *ld;
345 :
346 0 : WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY &&
347 : tty->driver->subtype == PTY_TYPE_MASTER);
348 : /*
349 : * Perform the actual termios internal changes under lock.
350 : */
351 :
352 :
353 : /* FIXME: we need to decide on some locking/ordering semantics
354 : for the set_termios notification eventually */
355 0 : down_write(&tty->termios_rwsem);
356 0 : old_termios = tty->termios;
357 0 : tty->termios = *new_termios;
358 0 : unset_locked_termios(tty, &old_termios);
359 : /* Reset any ADDRB changes, ADDRB is changed through ->rs485_config() */
360 0 : tty->termios.c_cflag ^= (tty->termios.c_cflag ^ old_termios.c_cflag) & ADDRB;
361 :
362 0 : if (tty->ops->set_termios)
363 0 : tty->ops->set_termios(tty, &old_termios);
364 : else
365 0 : tty_termios_copy_hw(&tty->termios, &old_termios);
366 :
367 0 : ld = tty_ldisc_ref(tty);
368 0 : if (ld != NULL) {
369 0 : if (ld->ops->set_termios)
370 0 : ld->ops->set_termios(tty, &old_termios);
371 0 : tty_ldisc_deref(ld);
372 : }
373 0 : up_write(&tty->termios_rwsem);
374 0 : return 0;
375 : }
376 : EXPORT_SYMBOL_GPL(tty_set_termios);
377 :
378 :
379 : /*
380 : * Translate a "termio" structure into a "termios". Ugh.
381 : */
382 0 : __weak int user_termio_to_kernel_termios(struct ktermios *termios,
383 : struct termio __user *termio)
384 : {
385 : struct termio v;
386 :
387 0 : if (copy_from_user(&v, termio, sizeof(struct termio)))
388 : return -EFAULT;
389 :
390 0 : termios->c_iflag = (0xffff0000 & termios->c_iflag) | v.c_iflag;
391 0 : termios->c_oflag = (0xffff0000 & termios->c_oflag) | v.c_oflag;
392 0 : termios->c_cflag = (0xffff0000 & termios->c_cflag) | v.c_cflag;
393 0 : termios->c_lflag = (0xffff0000 & termios->c_lflag) | v.c_lflag;
394 0 : termios->c_line = (0xffff0000 & termios->c_lflag) | v.c_line;
395 0 : memcpy(termios->c_cc, v.c_cc, NCC);
396 0 : return 0;
397 : }
398 :
399 : /*
400 : * Translate a "termios" structure into a "termio". Ugh.
401 : */
402 0 : __weak int kernel_termios_to_user_termio(struct termio __user *termio,
403 : struct ktermios *termios)
404 : {
405 : struct termio v;
406 0 : memset(&v, 0, sizeof(struct termio));
407 0 : v.c_iflag = termios->c_iflag;
408 0 : v.c_oflag = termios->c_oflag;
409 0 : v.c_cflag = termios->c_cflag;
410 0 : v.c_lflag = termios->c_lflag;
411 0 : v.c_line = termios->c_line;
412 0 : memcpy(v.c_cc, termios->c_cc, NCC);
413 0 : return copy_to_user(termio, &v, sizeof(struct termio));
414 : }
415 :
416 : #ifdef TCGETS2
417 0 : __weak int user_termios_to_kernel_termios(struct ktermios *k,
418 : struct termios2 __user *u)
419 : {
420 0 : return copy_from_user(k, u, sizeof(struct termios2));
421 : }
422 0 : __weak int kernel_termios_to_user_termios(struct termios2 __user *u,
423 : struct ktermios *k)
424 : {
425 0 : return copy_to_user(u, k, sizeof(struct termios2));
426 : }
427 0 : __weak int user_termios_to_kernel_termios_1(struct ktermios *k,
428 : struct termios __user *u)
429 : {
430 0 : return copy_from_user(k, u, sizeof(struct termios));
431 : }
432 0 : __weak int kernel_termios_to_user_termios_1(struct termios __user *u,
433 : struct ktermios *k)
434 : {
435 0 : return copy_to_user(u, k, sizeof(struct termios));
436 : }
437 :
438 : #else
439 :
440 : __weak int user_termios_to_kernel_termios(struct ktermios *k,
441 : struct termios __user *u)
442 : {
443 : return copy_from_user(k, u, sizeof(struct termios));
444 : }
445 : __weak int kernel_termios_to_user_termios(struct termios __user *u,
446 : struct ktermios *k)
447 : {
448 : return copy_to_user(u, k, sizeof(struct termios));
449 : }
450 : #endif /* TCGETS2 */
451 :
452 : /**
453 : * set_termios - set termios values for a tty
454 : * @tty: terminal device
455 : * @arg: user data
456 : * @opt: option information
457 : *
458 : * Helper function to prepare termios data and run necessary other
459 : * functions before using tty_set_termios to do the actual changes.
460 : *
461 : * Locking:
462 : * Called functions take ldisc and termios_rwsem locks
463 : */
464 :
465 0 : static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
466 : {
467 : struct ktermios tmp_termios;
468 : struct tty_ldisc *ld;
469 0 : int retval = tty_check_change(tty);
470 :
471 0 : if (retval)
472 : return retval;
473 :
474 0 : down_read(&tty->termios_rwsem);
475 0 : tmp_termios = tty->termios;
476 0 : up_read(&tty->termios_rwsem);
477 :
478 0 : if (opt & TERMIOS_TERMIO) {
479 0 : if (user_termio_to_kernel_termios(&tmp_termios,
480 : (struct termio __user *)arg))
481 : return -EFAULT;
482 : #ifdef TCGETS2
483 0 : } else if (opt & TERMIOS_OLD) {
484 0 : if (user_termios_to_kernel_termios_1(&tmp_termios,
485 : (struct termios __user *)arg))
486 : return -EFAULT;
487 : } else {
488 0 : if (user_termios_to_kernel_termios(&tmp_termios,
489 : (struct termios2 __user *)arg))
490 : return -EFAULT;
491 : }
492 : #else
493 : } else if (user_termios_to_kernel_termios(&tmp_termios,
494 : (struct termios __user *)arg))
495 : return -EFAULT;
496 : #endif
497 :
498 : /* If old style Bfoo values are used then load c_ispeed/c_ospeed
499 : * with the real speed so its unconditionally usable */
500 0 : tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
501 0 : tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
502 :
503 0 : ld = tty_ldisc_ref(tty);
504 :
505 0 : if (ld != NULL) {
506 0 : if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
507 0 : ld->ops->flush_buffer(tty);
508 0 : tty_ldisc_deref(ld);
509 : }
510 :
511 0 : if (opt & TERMIOS_WAIT) {
512 0 : tty_wait_until_sent(tty, 0);
513 0 : if (signal_pending(current))
514 : return -ERESTARTSYS;
515 : }
516 :
517 0 : tty_set_termios(tty, &tmp_termios);
518 :
519 : /* FIXME: Arguably if tmp_termios == tty->termios AND the
520 : actual requested termios was not tmp_termios then we may
521 : want to return an error as no user requested change has
522 : succeeded */
523 0 : return 0;
524 : }
525 :
526 0 : static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
527 : {
528 0 : down_read(&tty->termios_rwsem);
529 0 : *kterm = tty->termios;
530 0 : up_read(&tty->termios_rwsem);
531 0 : }
532 :
533 0 : static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
534 : {
535 0 : down_read(&tty->termios_rwsem);
536 0 : *kterm = tty->termios_locked;
537 0 : up_read(&tty->termios_rwsem);
538 0 : }
539 :
540 0 : static int get_termio(struct tty_struct *tty, struct termio __user *termio)
541 : {
542 : struct ktermios kterm;
543 0 : copy_termios(tty, &kterm);
544 0 : if (kernel_termios_to_user_termio(termio, &kterm))
545 : return -EFAULT;
546 0 : return 0;
547 : }
548 :
549 : #ifdef TIOCGETP
550 : /*
551 : * These are deprecated, but there is limited support..
552 : *
553 : * The "sg_flags" translation is a joke..
554 : */
555 : static int get_sgflags(struct tty_struct *tty)
556 : {
557 : int flags = 0;
558 :
559 : if (!L_ICANON(tty)) {
560 : if (L_ISIG(tty))
561 : flags |= 0x02; /* cbreak */
562 : else
563 : flags |= 0x20; /* raw */
564 : }
565 : if (L_ECHO(tty))
566 : flags |= 0x08; /* echo */
567 : if (O_OPOST(tty))
568 : if (O_ONLCR(tty))
569 : flags |= 0x10; /* crmod */
570 : return flags;
571 : }
572 :
573 : static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
574 : {
575 : struct sgttyb tmp;
576 :
577 : down_read(&tty->termios_rwsem);
578 : tmp.sg_ispeed = tty->termios.c_ispeed;
579 : tmp.sg_ospeed = tty->termios.c_ospeed;
580 : tmp.sg_erase = tty->termios.c_cc[VERASE];
581 : tmp.sg_kill = tty->termios.c_cc[VKILL];
582 : tmp.sg_flags = get_sgflags(tty);
583 : up_read(&tty->termios_rwsem);
584 :
585 : return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
586 : }
587 :
588 : static void set_sgflags(struct ktermios *termios, int flags)
589 : {
590 : termios->c_iflag = ICRNL | IXON;
591 : termios->c_oflag = 0;
592 : termios->c_lflag = ISIG | ICANON;
593 : if (flags & 0x02) { /* cbreak */
594 : termios->c_iflag = 0;
595 : termios->c_lflag &= ~ICANON;
596 : }
597 : if (flags & 0x08) { /* echo */
598 : termios->c_lflag |= ECHO | ECHOE | ECHOK |
599 : ECHOCTL | ECHOKE | IEXTEN;
600 : }
601 : if (flags & 0x10) { /* crmod */
602 : termios->c_oflag |= OPOST | ONLCR;
603 : }
604 : if (flags & 0x20) { /* raw */
605 : termios->c_iflag = 0;
606 : termios->c_lflag &= ~(ISIG | ICANON);
607 : }
608 : if (!(termios->c_lflag & ICANON)) {
609 : termios->c_cc[VMIN] = 1;
610 : termios->c_cc[VTIME] = 0;
611 : }
612 : }
613 :
614 : /**
615 : * set_sgttyb - set legacy terminal values
616 : * @tty: tty structure
617 : * @sgttyb: pointer to old style terminal structure
618 : *
619 : * Updates a terminal from the legacy BSD style terminal information
620 : * structure.
621 : *
622 : * Locking: termios_rwsem
623 : */
624 :
625 : static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
626 : {
627 : int retval;
628 : struct sgttyb tmp;
629 : struct ktermios termios;
630 :
631 : retval = tty_check_change(tty);
632 : if (retval)
633 : return retval;
634 :
635 : if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
636 : return -EFAULT;
637 :
638 : down_write(&tty->termios_rwsem);
639 : termios = tty->termios;
640 : termios.c_cc[VERASE] = tmp.sg_erase;
641 : termios.c_cc[VKILL] = tmp.sg_kill;
642 : set_sgflags(&termios, tmp.sg_flags);
643 : /* Try and encode into Bfoo format */
644 : tty_termios_encode_baud_rate(&termios, termios.c_ispeed,
645 : termios.c_ospeed);
646 : up_write(&tty->termios_rwsem);
647 : tty_set_termios(tty, &termios);
648 : return 0;
649 : }
650 : #endif
651 :
652 : #ifdef TIOCGETC
653 : static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
654 : {
655 : struct tchars tmp;
656 :
657 : down_read(&tty->termios_rwsem);
658 : tmp.t_intrc = tty->termios.c_cc[VINTR];
659 : tmp.t_quitc = tty->termios.c_cc[VQUIT];
660 : tmp.t_startc = tty->termios.c_cc[VSTART];
661 : tmp.t_stopc = tty->termios.c_cc[VSTOP];
662 : tmp.t_eofc = tty->termios.c_cc[VEOF];
663 : tmp.t_brkc = tty->termios.c_cc[VEOL2]; /* what is brkc anyway? */
664 : up_read(&tty->termios_rwsem);
665 : return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
666 : }
667 :
668 : static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
669 : {
670 : struct tchars tmp;
671 :
672 : if (copy_from_user(&tmp, tchars, sizeof(tmp)))
673 : return -EFAULT;
674 : down_write(&tty->termios_rwsem);
675 : tty->termios.c_cc[VINTR] = tmp.t_intrc;
676 : tty->termios.c_cc[VQUIT] = tmp.t_quitc;
677 : tty->termios.c_cc[VSTART] = tmp.t_startc;
678 : tty->termios.c_cc[VSTOP] = tmp.t_stopc;
679 : tty->termios.c_cc[VEOF] = tmp.t_eofc;
680 : tty->termios.c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
681 : up_write(&tty->termios_rwsem);
682 : return 0;
683 : }
684 : #endif
685 :
686 : #ifdef TIOCGLTC
687 : static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
688 : {
689 : struct ltchars tmp;
690 :
691 : down_read(&tty->termios_rwsem);
692 : tmp.t_suspc = tty->termios.c_cc[VSUSP];
693 : /* what is dsuspc anyway? */
694 : tmp.t_dsuspc = tty->termios.c_cc[VSUSP];
695 : tmp.t_rprntc = tty->termios.c_cc[VREPRINT];
696 : /* what is flushc anyway? */
697 : tmp.t_flushc = tty->termios.c_cc[VEOL2];
698 : tmp.t_werasc = tty->termios.c_cc[VWERASE];
699 : tmp.t_lnextc = tty->termios.c_cc[VLNEXT];
700 : up_read(&tty->termios_rwsem);
701 : return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
702 : }
703 :
704 : static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
705 : {
706 : struct ltchars tmp;
707 :
708 : if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
709 : return -EFAULT;
710 :
711 : down_write(&tty->termios_rwsem);
712 : tty->termios.c_cc[VSUSP] = tmp.t_suspc;
713 : /* what is dsuspc anyway? */
714 : tty->termios.c_cc[VEOL2] = tmp.t_dsuspc;
715 : tty->termios.c_cc[VREPRINT] = tmp.t_rprntc;
716 : /* what is flushc anyway? */
717 : tty->termios.c_cc[VEOL2] = tmp.t_flushc;
718 : tty->termios.c_cc[VWERASE] = tmp.t_werasc;
719 : tty->termios.c_cc[VLNEXT] = tmp.t_lnextc;
720 : up_write(&tty->termios_rwsem);
721 : return 0;
722 : }
723 : #endif
724 :
725 : /**
726 : * tty_change_softcar - carrier change ioctl helper
727 : * @tty: tty to update
728 : * @arg: enable/disable CLOCAL
729 : *
730 : * Perform a change to the CLOCAL state and call into the driver
731 : * layer to make it visible. All done with the termios rwsem
732 : */
733 :
734 0 : static int tty_change_softcar(struct tty_struct *tty, int arg)
735 : {
736 0 : int ret = 0;
737 0 : int bit = arg ? CLOCAL : 0;
738 : struct ktermios old;
739 :
740 0 : down_write(&tty->termios_rwsem);
741 0 : old = tty->termios;
742 0 : tty->termios.c_cflag &= ~CLOCAL;
743 0 : tty->termios.c_cflag |= bit;
744 0 : if (tty->ops->set_termios)
745 0 : tty->ops->set_termios(tty, &old);
746 0 : if (C_CLOCAL(tty) != bit)
747 0 : ret = -EINVAL;
748 0 : up_write(&tty->termios_rwsem);
749 0 : return ret;
750 : }
751 :
752 : /**
753 : * tty_mode_ioctl - mode related ioctls
754 : * @tty: tty for the ioctl
755 : * @cmd: command
756 : * @arg: ioctl argument
757 : *
758 : * Perform non line discipline specific mode control ioctls. This
759 : * is designed to be called by line disciplines to ensure they provide
760 : * consistent mode setting.
761 : */
762 :
763 0 : int tty_mode_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
764 : {
765 : struct tty_struct *real_tty;
766 0 : void __user *p = (void __user *)arg;
767 0 : int ret = 0;
768 : struct ktermios kterm;
769 :
770 0 : if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
771 : tty->driver->subtype == PTY_TYPE_MASTER)
772 0 : real_tty = tty->link;
773 : else
774 : real_tty = tty;
775 :
776 0 : switch (cmd) {
777 : #ifdef TIOCGETP
778 : case TIOCGETP:
779 : return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
780 : case TIOCSETP:
781 : case TIOCSETN:
782 : return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
783 : #endif
784 : #ifdef TIOCGETC
785 : case TIOCGETC:
786 : return get_tchars(real_tty, p);
787 : case TIOCSETC:
788 : return set_tchars(real_tty, p);
789 : #endif
790 : #ifdef TIOCGLTC
791 : case TIOCGLTC:
792 : return get_ltchars(real_tty, p);
793 : case TIOCSLTC:
794 : return set_ltchars(real_tty, p);
795 : #endif
796 : case TCSETSF:
797 0 : return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
798 : case TCSETSW:
799 0 : return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
800 : case TCSETS:
801 0 : return set_termios(real_tty, p, TERMIOS_OLD);
802 : #ifndef TCGETS2
803 : case TCGETS:
804 : copy_termios(real_tty, &kterm);
805 : if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
806 : ret = -EFAULT;
807 : return ret;
808 : #else
809 : case TCGETS:
810 0 : copy_termios(real_tty, &kterm);
811 0 : if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
812 0 : ret = -EFAULT;
813 : return ret;
814 : case TCGETS2:
815 0 : copy_termios(real_tty, &kterm);
816 0 : if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
817 0 : ret = -EFAULT;
818 : return ret;
819 : case TCSETSF2:
820 0 : return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT);
821 : case TCSETSW2:
822 0 : return set_termios(real_tty, p, TERMIOS_WAIT);
823 : case TCSETS2:
824 0 : return set_termios(real_tty, p, 0);
825 : #endif
826 : case TCGETA:
827 0 : return get_termio(real_tty, p);
828 : case TCSETAF:
829 0 : return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
830 : case TCSETAW:
831 0 : return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
832 : case TCSETA:
833 0 : return set_termios(real_tty, p, TERMIOS_TERMIO);
834 : #ifndef TCGETS2
835 : case TIOCGLCKTRMIOS:
836 : copy_termios_locked(real_tty, &kterm);
837 : if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
838 : ret = -EFAULT;
839 : return ret;
840 : case TIOCSLCKTRMIOS:
841 : if (!capable(CAP_SYS_ADMIN))
842 : return -EPERM;
843 : copy_termios_locked(real_tty, &kterm);
844 : if (user_termios_to_kernel_termios(&kterm,
845 : (struct termios __user *) arg))
846 : return -EFAULT;
847 : down_write(&real_tty->termios_rwsem);
848 : real_tty->termios_locked = kterm;
849 : up_write(&real_tty->termios_rwsem);
850 : return 0;
851 : #else
852 : case TIOCGLCKTRMIOS:
853 0 : copy_termios_locked(real_tty, &kterm);
854 0 : if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
855 0 : ret = -EFAULT;
856 : return ret;
857 : case TIOCSLCKTRMIOS:
858 0 : if (!capable(CAP_SYS_ADMIN))
859 : return -EPERM;
860 0 : copy_termios_locked(real_tty, &kterm);
861 0 : if (user_termios_to_kernel_termios_1(&kterm,
862 : (struct termios __user *) arg))
863 : return -EFAULT;
864 0 : down_write(&real_tty->termios_rwsem);
865 0 : real_tty->termios_locked = kterm;
866 0 : up_write(&real_tty->termios_rwsem);
867 0 : return ret;
868 : #endif
869 : #ifdef TCGETX
870 : case TCGETX:
871 : case TCSETX:
872 : case TCSETXW:
873 : case TCSETXF:
874 : return -ENOTTY;
875 : #endif
876 : case TIOCGSOFTCAR:
877 0 : copy_termios(real_tty, &kterm);
878 0 : ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
879 : (int __user *)arg);
880 : return ret;
881 : case TIOCSSOFTCAR:
882 0 : if (get_user(arg, (unsigned int __user *) arg))
883 : return -EFAULT;
884 0 : return tty_change_softcar(real_tty, arg);
885 : default:
886 0 : return -ENOIOCTLCMD;
887 : }
888 : }
889 : EXPORT_SYMBOL_GPL(tty_mode_ioctl);
890 :
891 :
892 : /* Caller guarantees ldisc reference is held */
893 0 : static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
894 : {
895 0 : struct tty_ldisc *ld = tty->ldisc;
896 :
897 0 : switch (arg) {
898 : case TCIFLUSH:
899 0 : if (ld && ld->ops->flush_buffer) {
900 0 : ld->ops->flush_buffer(tty);
901 0 : tty_unthrottle(tty);
902 : }
903 : break;
904 : case TCIOFLUSH:
905 0 : if (ld && ld->ops->flush_buffer) {
906 0 : ld->ops->flush_buffer(tty);
907 0 : tty_unthrottle(tty);
908 : }
909 : fallthrough;
910 : case TCOFLUSH:
911 : tty_driver_flush_buffer(tty);
912 : break;
913 : default:
914 : return -EINVAL;
915 : }
916 : return 0;
917 : }
918 :
919 0 : int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
920 : {
921 : struct tty_ldisc *ld;
922 0 : int retval = tty_check_change(tty);
923 0 : if (retval)
924 : return retval;
925 :
926 0 : ld = tty_ldisc_ref_wait(tty);
927 0 : retval = __tty_perform_flush(tty, arg);
928 0 : if (ld)
929 0 : tty_ldisc_deref(ld);
930 : return retval;
931 : }
932 : EXPORT_SYMBOL_GPL(tty_perform_flush);
933 :
934 0 : int n_tty_ioctl_helper(struct tty_struct *tty, unsigned int cmd,
935 : unsigned long arg)
936 : {
937 : int retval;
938 :
939 0 : switch (cmd) {
940 : case TCXONC:
941 0 : retval = tty_check_change(tty);
942 0 : if (retval)
943 : return retval;
944 0 : switch (arg) {
945 : case TCOOFF:
946 0 : spin_lock_irq(&tty->flow.lock);
947 0 : if (!tty->flow.tco_stopped) {
948 0 : tty->flow.tco_stopped = true;
949 0 : __stop_tty(tty);
950 : }
951 0 : spin_unlock_irq(&tty->flow.lock);
952 : break;
953 : case TCOON:
954 0 : spin_lock_irq(&tty->flow.lock);
955 0 : if (tty->flow.tco_stopped) {
956 0 : tty->flow.tco_stopped = false;
957 0 : __start_tty(tty);
958 : }
959 0 : spin_unlock_irq(&tty->flow.lock);
960 : break;
961 : case TCIOFF:
962 0 : if (STOP_CHAR(tty) != __DISABLED_CHAR)
963 0 : retval = tty_send_xchar(tty, STOP_CHAR(tty));
964 : break;
965 : case TCION:
966 0 : if (START_CHAR(tty) != __DISABLED_CHAR)
967 0 : retval = tty_send_xchar(tty, START_CHAR(tty));
968 : break;
969 : default:
970 : return -EINVAL;
971 : }
972 : return retval;
973 : case TCFLSH:
974 0 : retval = tty_check_change(tty);
975 0 : if (retval)
976 : return retval;
977 0 : return __tty_perform_flush(tty, arg);
978 : default:
979 : /* Try the mode commands */
980 0 : return tty_mode_ioctl(tty, cmd, arg);
981 : }
982 : }
983 : EXPORT_SYMBOL(n_tty_ioctl_helper);
|