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