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