File Index
Files and directories
Sign in
FILE

tty_ioctl.c

File preview with syntax highlighting.

linux-6.19.14/drivers/tty/tty_ioctl.c C
  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/bits.h>
 11#include <linux/types.h>
 12#include <linux/termios.h>
 13#include <linux/errno.h>
 14#include <linux/sched/signal.h>
 15#include <linux/kernel.h>
 16#include <linux/major.h>
 17#include <linux/tty.h>
 18#include <linux/fcntl.h>
 19#include <linux/string.h>
 20#include <linux/mm.h>
 21#include <linux/module.h>
 22#include <linux/bitops.h>
 23#include <linux/mutex.h>
 24#include <linux/compat.h>
 25#include <linux/termios_internal.h>
 26#include "tty.h"
 27
 28#include <asm/io.h>
 29#include <linux/uaccess.h>
 30
 31#undef	DEBUG
 32
 33/*
 34 * Internal flag options for termios setting behavior
 35 */
 36#define TERMIOS_FLUSH	BIT(0)
 37#define TERMIOS_WAIT	BIT(1)
 38#define TERMIOS_TERMIO	BIT(2)
 39#define TERMIOS_OLD	BIT(3)
 40
 41/**
 42 * tty_chars_in_buffer - characters pending
 43 * @tty: terminal
 44 *
 45 * Returns: the number of bytes of data in the device private output queue. If
 46 * no private method is supplied there is assumed to be no queue on the device.
 47 */
 48unsigned int tty_chars_in_buffer(struct tty_struct *tty)
 49{
 50	if (tty->ops->chars_in_buffer)
 51		return tty->ops->chars_in_buffer(tty);
 52	return 0;
 53}
 54EXPORT_SYMBOL(tty_chars_in_buffer);
 55
 56/**
 57 * tty_write_room - write queue space
 58 * @tty: terminal
 59 *
 60 * Returns: the number of bytes that can be queued to this device at the present
 61 * time. The result should be treated as a guarantee and the driver cannot
 62 * offer a value it later shrinks by more than the number of bytes written. If
 63 * no method is provided, 2K is always returned and data may be lost as there
 64 * will be no flow control.
 65 */
 66unsigned int tty_write_room(struct tty_struct *tty)
 67{
 68	if (tty->ops->write_room)
 69		return tty->ops->write_room(tty);
 70	return 2048;
 71}
 72EXPORT_SYMBOL(tty_write_room);
 73
 74/**
 75 * tty_driver_flush_buffer - discard internal buffer
 76 * @tty: terminal
 77 *
 78 * Discard the internal output buffer for this device. If no method is provided,
 79 * then either the buffer cannot be hardware flushed or there is no buffer
 80 * driver side.
 81 */
 82void tty_driver_flush_buffer(struct tty_struct *tty)
 83{
 84	if (tty->ops->flush_buffer)
 85		tty->ops->flush_buffer(tty);
 86}
 87EXPORT_SYMBOL(tty_driver_flush_buffer);
 88
 89/**
 90 * tty_unthrottle - flow control
 91 * @tty: terminal
 92 *
 93 * Indicate that a @tty may continue transmitting data down the stack. Takes
 94 * the &tty_struct->termios_rwsem to protect against parallel
 95 * throttle/unthrottle and also to ensure the driver can consistently reference
 96 * its own termios data at this point when implementing software flow control.
 97 *
 98 * Drivers should however remember that the stack can issue a throttle, then
 99 * change flow control method, then unthrottle.
100 */
101void tty_unthrottle(struct tty_struct *tty)
102{
103	down_write(&tty->termios_rwsem);
104	if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
105	    tty->ops->unthrottle)
106		tty->ops->unthrottle(tty);
107	tty->flow_change = TTY_FLOW_NO_CHANGE;
108	up_write(&tty->termios_rwsem);
109}
110EXPORT_SYMBOL(tty_unthrottle);
111
112/**
113 * tty_throttle_safe - flow control
114 * @tty: terminal
115 *
116 * Indicate that a @tty should stop transmitting data down the stack.
117 * tty_throttle_safe() will only attempt throttle if @tty->flow_change is
118 * %TTY_THROTTLE_SAFE. Prevents an accidental throttle due to race conditions
119 * when throttling is conditional on factors evaluated prior to throttling.
120 *
121 * Returns: %true if @tty is throttled (or was already throttled)
122 */
123bool tty_throttle_safe(struct tty_struct *tty)
124{
125	guard(mutex)(&tty->throttle_mutex);
126
127	if (tty_throttled(tty))
128		return true;
129
130	if (tty->flow_change != TTY_THROTTLE_SAFE)
131		return false;
132
133	set_bit(TTY_THROTTLED, &tty->flags);
134	if (tty->ops->throttle)
135		tty->ops->throttle(tty);
136
137	return true;
138}
139
140/**
141 * tty_unthrottle_safe - flow control
142 * @tty: terminal
143 *
144 * Similar to tty_unthrottle() but will only attempt unthrottle if
145 * @tty->flow_change is %TTY_UNTHROTTLE_SAFE. Prevents an accidental unthrottle
146 * due to race conditions when unthrottling is conditional on factors evaluated
147 * prior to unthrottling.
148 *
149 * Returns: %true if @tty is unthrottled (or was already unthrottled)
150 */
151bool tty_unthrottle_safe(struct tty_struct *tty)
152{
153	guard(mutex)(&tty->throttle_mutex);
154
155	if (!tty_throttled(tty))
156		return true;
157
158	if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
159		return false;
160
161	clear_bit(TTY_THROTTLED, &tty->flags);
162	if (tty->ops->unthrottle)
163		tty->ops->unthrottle(tty);
164
165	return true;
166}
167
168/**
169 * tty_wait_until_sent - wait for I/O to finish
170 * @tty: tty we are waiting for
171 * @timeout: how long we will wait
172 *
173 * Wait for characters pending in a tty driver to hit the wire, or for a
174 * timeout to occur (eg due to flow control).
175 *
176 * Locking: none
177 */
178
179void tty_wait_until_sent(struct tty_struct *tty, long timeout)
180{
181	if (!timeout)
182		timeout = MAX_SCHEDULE_TIMEOUT;
183
184	timeout = wait_event_interruptible_timeout(tty->write_wait,
185			!tty_chars_in_buffer(tty), timeout);
186	if (timeout <= 0)
187		return;
188
189	if (timeout == MAX_SCHEDULE_TIMEOUT)
190		timeout = 0;
191
192	if (tty->ops->wait_until_sent)
193		tty->ops->wait_until_sent(tty, timeout);
194}
195EXPORT_SYMBOL(tty_wait_until_sent);
196
197
198/*
199 *		Termios Helper Methods
200 */
201
202static void unset_locked_termios(struct tty_struct *tty, const struct ktermios *old)
203{
204	struct ktermios *termios = &tty->termios;
205	struct ktermios *locked  = &tty->termios_locked;
206	int	i;
207
208#define NOSET_MASK(x, y, z) (x = ((x) & ~(z)) | ((y) & (z)))
209
210	NOSET_MASK(termios->c_iflag, old->c_iflag, locked->c_iflag);
211	NOSET_MASK(termios->c_oflag, old->c_oflag, locked->c_oflag);
212	NOSET_MASK(termios->c_cflag, old->c_cflag, locked->c_cflag);
213	NOSET_MASK(termios->c_lflag, old->c_lflag, locked->c_lflag);
214	termios->c_line = locked->c_line ? old->c_line : termios->c_line;
215	for (i = 0; i < NCCS; i++)
216		termios->c_cc[i] = locked->c_cc[i] ?
217			old->c_cc[i] : termios->c_cc[i];
218	/* FIXME: What should we do for i/ospeed */
219}
220
221/**
222 * tty_termios_copy_hw - copy hardware settings
223 * @new: new termios
224 * @old: old termios
225 *
226 * Propagate the hardware specific terminal setting bits from the @old termios
227 * structure to the @new one. This is used in cases where the hardware does not
228 * support reconfiguration or as a helper in some cases where only minimal
229 * reconfiguration is supported.
230 */
231void tty_termios_copy_hw(struct ktermios *new, const struct ktermios *old)
232{
233	/* The bits a dumb device handles in software. Smart devices need
234	   to always provide a set_termios method */
235	new->c_cflag &= HUPCL | CREAD | CLOCAL;
236	new->c_cflag |= old->c_cflag & ~(HUPCL | CREAD | CLOCAL);
237	new->c_ispeed = old->c_ispeed;
238	new->c_ospeed = old->c_ospeed;
239}
240EXPORT_SYMBOL(tty_termios_copy_hw);
241
242/**
243 * tty_termios_hw_change - check for setting change
244 * @a: termios
245 * @b: termios to compare
246 *
247 * Check if any of the bits that affect a dumb device have changed between the
248 * two termios structures, or a speed change is needed.
249 *
250 * Returns: %true if change is needed
251 */
252bool tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b)
253{
254	if (a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed)
255		return true;
256	if ((a->c_cflag ^ b->c_cflag) & ~(HUPCL | CREAD | CLOCAL))
257		return true;
258	return false;
259}
260EXPORT_SYMBOL(tty_termios_hw_change);
261
262/**
263 * tty_get_char_size - get size of a character
264 * @cflag: termios cflag value
265 *
266 * Returns: size (in bits) of a character depending on @cflag's %CSIZE setting
267 */
268unsigned char tty_get_char_size(unsigned int cflag)
269{
270	switch (cflag & CSIZE) {
271	case CS5:
272		return 5;
273	case CS6:
274		return 6;
275	case CS7:
276		return 7;
277	case CS8:
278	default:
279		return 8;
280	}
281}
282EXPORT_SYMBOL_GPL(tty_get_char_size);
283
284/**
285 * tty_get_frame_size - get size of a frame
286 * @cflag: termios cflag value
287 *
288 * Get the size (in bits) of a frame depending on @cflag's %CSIZE, %CSTOPB, and
289 * %PARENB setting. The result is a sum of character size, start and stop bits
290 * -- one bit each -- second stop bit (if set), and parity bit (if set).
291 *
292 * Returns: size (in bits) of a frame depending on @cflag's setting.
293 */
294unsigned char tty_get_frame_size(unsigned int cflag)
295{
296	unsigned char bits = 2 + tty_get_char_size(cflag);
297
298	if (cflag & CSTOPB)
299		bits++;
300	if (cflag & PARENB)
301		bits++;
302	if (cflag & ADDRB)
303		bits++;
304
305	return bits;
306}
307EXPORT_SYMBOL_GPL(tty_get_frame_size);
308
309/**
310 * tty_set_termios - update termios values
311 * @tty: tty to update
312 * @new_termios: desired new value
313 *
314 * Perform updates to the termios values set on this @tty. A master pty's
315 * termios should never be set.
316 *
317 * Locking: &tty_struct->termios_rwsem
318 */
319int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
320{
321	struct ktermios old_termios;
322	struct tty_ldisc *ld;
323
324	WARN_ON(tty->driver->type == TTY_DRIVER_TYPE_PTY &&
325		tty->driver->subtype == PTY_TYPE_MASTER);
326	/*
327	 *	Perform the actual termios internal changes under lock.
328	 */
329
330
331	/* FIXME: we need to decide on some locking/ordering semantics
332	   for the set_termios notification eventually */
333	down_write(&tty->termios_rwsem);
334	old_termios = tty->termios;
335	tty->termios = *new_termios;
336	unset_locked_termios(tty, &old_termios);
337	/* Reset any ADDRB changes, ADDRB is changed through ->rs485_config() */
338	tty->termios.c_cflag ^= (tty->termios.c_cflag ^ old_termios.c_cflag) & ADDRB;
339
340	if (tty->ops->set_termios)
341		tty->ops->set_termios(tty, &old_termios);
342	else
343		tty_termios_copy_hw(&tty->termios, &old_termios);
344
345	ld = tty_ldisc_ref(tty);
346	if (ld != NULL) {
347		if (ld->ops->set_termios)
348			ld->ops->set_termios(tty, &old_termios);
349		tty_ldisc_deref(ld);
350	}
351	up_write(&tty->termios_rwsem);
352	return 0;
353}
354EXPORT_SYMBOL_GPL(tty_set_termios);
355
356
357/*
358 * Translate a "termio" structure into a "termios". Ugh.
359 */
360__weak int user_termio_to_kernel_termios(struct ktermios *termios,
361						struct termio __user *termio)
362{
363	struct termio v;
364
365	if (copy_from_user(&v, termio, sizeof(struct termio)))
366		return -EFAULT;
367
368	termios->c_iflag = (0xffff0000 & termios->c_iflag) | v.c_iflag;
369	termios->c_oflag = (0xffff0000 & termios->c_oflag) | v.c_oflag;
370	termios->c_cflag = (0xffff0000 & termios->c_cflag) | v.c_cflag;
371	termios->c_lflag = (0xffff0000 & termios->c_lflag) | v.c_lflag;
372	termios->c_line = (0xffff0000 & termios->c_lflag) | v.c_line;
373	memcpy(termios->c_cc, v.c_cc, NCC);
374	return 0;
375}
376
377/*
378 * Translate a "termios" structure into a "termio". Ugh.
379 */
380__weak int kernel_termios_to_user_termio(struct termio __user *termio,
381						struct ktermios *termios)
382{
383	struct termio v;
384	memset(&v, 0, sizeof(struct termio));
385	v.c_iflag = termios->c_iflag;
386	v.c_oflag = termios->c_oflag;
387	v.c_cflag = termios->c_cflag;
388	v.c_lflag = termios->c_lflag;
389	v.c_line = termios->c_line;
390	memcpy(v.c_cc, termios->c_cc, NCC);
391	return copy_to_user(termio, &v, sizeof(struct termio));
392}
393
394#ifdef TCGETS2
395__weak int user_termios_to_kernel_termios(struct ktermios *k,
396						 struct termios2 __user *u)
397{
398	return copy_from_user(k, u, sizeof(struct termios2));
399}
400__weak int kernel_termios_to_user_termios(struct termios2 __user *u,
401						 struct ktermios *k)
402{
403	return copy_to_user(u, k, sizeof(struct termios2));
404}
405__weak int user_termios_to_kernel_termios_1(struct ktermios *k,
406						   struct termios __user *u)
407{
408	return copy_from_user(k, u, sizeof(struct termios));
409}
410__weak int kernel_termios_to_user_termios_1(struct termios __user *u,
411						   struct ktermios *k)
412{
413	return copy_to_user(u, k, sizeof(struct termios));
414}
415
416#else
417
418__weak int user_termios_to_kernel_termios(struct ktermios *k,
419						 struct termios __user *u)
420{
421	return copy_from_user(k, u, sizeof(struct termios));
422}
423__weak int kernel_termios_to_user_termios(struct termios __user *u,
424						 struct ktermios *k)
425{
426	return copy_to_user(u, k, sizeof(struct termios));
427}
428#endif /* TCGETS2 */
429
430/**
431 * set_termios - set termios values for a tty
432 * @tty: terminal device
433 * @arg: user data
434 * @opt: option information
435 *
436 * Helper function to prepare termios data and run necessary other functions
437 * before using tty_set_termios() to do the actual changes.
438 *
439 * Locking: called functions take &tty_struct->ldisc_sem and
440 * &tty_struct->termios_rwsem locks
441 *
442 * Returns: 0 on success, an error otherwise
443 */
444static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
445{
446	struct ktermios tmp_termios;
447	struct tty_ldisc *ld;
448	int retval = tty_check_change(tty);
449
450	if (retval)
451		return retval;
452
453	down_read(&tty->termios_rwsem);
454	tmp_termios = tty->termios;
455	up_read(&tty->termios_rwsem);
456
457	if (opt & TERMIOS_TERMIO) {
458		if (user_termio_to_kernel_termios(&tmp_termios,
459						(struct termio __user *)arg))
460			return -EFAULT;
461#ifdef TCGETS2
462	} else if (opt & TERMIOS_OLD) {
463		if (user_termios_to_kernel_termios_1(&tmp_termios,
464						(struct termios __user *)arg))
465			return -EFAULT;
466	} else {
467		if (user_termios_to_kernel_termios(&tmp_termios,
468						(struct termios2 __user *)arg))
469			return -EFAULT;
470	}
471#else
472	} else if (user_termios_to_kernel_termios(&tmp_termios,
473					(struct termios __user *)arg))
474		return -EFAULT;
475#endif
476
477	/* If old style Bfoo values are used then load c_ispeed/c_ospeed
478	 * with the real speed so its unconditionally usable */
479	tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
480	tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
481
482	if (opt & (TERMIOS_FLUSH|TERMIOS_WAIT)) {
483retry_write_wait:
484		retval = wait_event_interruptible(tty->write_wait, !tty_chars_in_buffer(tty));
485		if (retval < 0)
486			return retval;
487
488		if (tty_write_lock(tty, false) < 0)
489			goto retry_write_wait;
490
491		/* Racing writer? */
492		if (tty_chars_in_buffer(tty)) {
493			tty_write_unlock(tty);
494			goto retry_write_wait;
495		}
496
497		ld = tty_ldisc_ref(tty);
498		if (ld != NULL) {
499			if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
500				ld->ops->flush_buffer(tty);
501			tty_ldisc_deref(ld);
502		}
503
504		if ((opt & TERMIOS_WAIT) && tty->ops->wait_until_sent) {
505			tty->ops->wait_until_sent(tty, 0);
506			if (signal_pending(current)) {
507				tty_write_unlock(tty);
508				return -ERESTARTSYS;
509			}
510		}
511
512		tty_set_termios(tty, &tmp_termios);
513
514		tty_write_unlock(tty);
515	} else {
516		tty_set_termios(tty, &tmp_termios);
517	}
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	return 0;
524}
525
526static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
527{
528	down_read(&tty->termios_rwsem);
529	*kterm = tty->termios;
530	up_read(&tty->termios_rwsem);
531}
532
533static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
534{
535	down_read(&tty->termios_rwsem);
536	*kterm = tty->termios_locked;
537	up_read(&tty->termios_rwsem);
538}
539
540static int get_termio(struct tty_struct *tty, struct termio __user *termio)
541{
542	struct ktermios kterm;
543	copy_termios(tty, &kterm);
544	if (kernel_termios_to_user_termio(termio, &kterm))
545		return -EFAULT;
546	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 */
555static 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
573static 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
588static 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 structure.
620 *
621 * Locking: &tty_struct->termios_rwsem
622 *
623 * Returns: 0 on success, an error otherwise
624 */
625static 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
653static 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
668static 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
687static 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
704static 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 * @enable: enable/disable %CLOCAL
729 *
730 * Perform a change to the %CLOCAL state and call into the driver layer to make
731 * it visible.
732 *
733 * Locking: &tty_struct->termios_rwsem.
734 *
735 * Returns: 0 on success, an error otherwise
736 */
737static int tty_change_softcar(struct tty_struct *tty, bool enable)
738{
739	int ret = 0;
740	struct ktermios old;
741	tcflag_t bit = enable ? CLOCAL : 0;
742
743	down_write(&tty->termios_rwsem);
744	old = tty->termios;
745	tty->termios.c_cflag &= ~CLOCAL;
746	tty->termios.c_cflag |= bit;
747	if (tty->ops->set_termios)
748		tty->ops->set_termios(tty, &old);
749	if (C_CLOCAL(tty) != bit)
750		ret = -EINVAL;
751	up_write(&tty->termios_rwsem);
752	return ret;
753}
754
755/**
756 * tty_mode_ioctl - mode related ioctls
757 * @tty: tty for the ioctl
758 * @cmd: command
759 * @arg: ioctl argument
760 *
761 * Perform non-line discipline specific mode control ioctls. This is designed
762 * to be called by line disciplines to ensure they provide consistent mode
763 * setting.
764 */
765int tty_mode_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
766{
767	struct tty_struct *real_tty;
768	void __user *p = (void __user *)arg;
769	int ret = 0;
770	struct ktermios kterm;
771
772	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
773	    tty->driver->subtype == PTY_TYPE_MASTER)
774		real_tty = tty->link;
775	else
776		real_tty = tty;
777
778	switch (cmd) {
779#ifdef TIOCGETP
780	case TIOCGETP:
781		return get_sgttyb(real_tty, (struct sgttyb __user *) arg);
782	case TIOCSETP:
783	case TIOCSETN:
784		return set_sgttyb(real_tty, (struct sgttyb __user *) arg);
785#endif
786#ifdef TIOCGETC
787	case TIOCGETC:
788		return get_tchars(real_tty, p);
789	case TIOCSETC:
790		return set_tchars(real_tty, p);
791#endif
792#ifdef TIOCGLTC
793	case TIOCGLTC:
794		return get_ltchars(real_tty, p);
795	case TIOCSLTC:
796		return set_ltchars(real_tty, p);
797#endif
798	case TCSETSF:
799		return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
800	case TCSETSW:
801		return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
802	case TCSETS:
803		return set_termios(real_tty, p, TERMIOS_OLD);
804#ifndef TCGETS2
805	case TCGETS:
806		copy_termios(real_tty, &kterm);
807		if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
808			ret = -EFAULT;
809		return ret;
810#else
811	case TCGETS:
812		copy_termios(real_tty, &kterm);
813		if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
814			ret = -EFAULT;
815		return ret;
816	case TCGETS2:
817		copy_termios(real_tty, &kterm);
818		if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm))
819			ret = -EFAULT;
820		return ret;
821	case TCSETSF2:
822		return set_termios(real_tty, p,  TERMIOS_FLUSH | TERMIOS_WAIT);
823	case TCSETSW2:
824		return set_termios(real_tty, p, TERMIOS_WAIT);
825	case TCSETS2:
826		return set_termios(real_tty, p, 0);
827#endif
828	case TCGETA:
829		return get_termio(real_tty, p);
830	case TCSETAF:
831		return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
832	case TCSETAW:
833		return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
834	case TCSETA:
835		return set_termios(real_tty, p, TERMIOS_TERMIO);
836#ifndef TCGETS2
837	case TIOCGLCKTRMIOS:
838		copy_termios_locked(real_tty, &kterm);
839		if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm))
840			ret = -EFAULT;
841		return ret;
842	case TIOCSLCKTRMIOS:
843		if (!checkpoint_restore_ns_capable(&init_user_ns))
844			return -EPERM;
845		copy_termios_locked(real_tty, &kterm);
846		if (user_termios_to_kernel_termios(&kterm,
847					       (struct termios __user *) arg))
848			return -EFAULT;
849		down_write(&real_tty->termios_rwsem);
850		real_tty->termios_locked = kterm;
851		up_write(&real_tty->termios_rwsem);
852		return 0;
853#else
854	case TIOCGLCKTRMIOS:
855		copy_termios_locked(real_tty, &kterm);
856		if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm))
857			ret = -EFAULT;
858		return ret;
859	case TIOCSLCKTRMIOS:
860		if (!checkpoint_restore_ns_capable(&init_user_ns))
861			return -EPERM;
862		copy_termios_locked(real_tty, &kterm);
863		if (user_termios_to_kernel_termios_1(&kterm,
864					       (struct termios __user *) arg))
865			return -EFAULT;
866		down_write(&real_tty->termios_rwsem);
867		real_tty->termios_locked = kterm;
868		up_write(&real_tty->termios_rwsem);
869		return ret;
870#endif
871#ifdef TCGETX
872	case TCGETX:
873	case TCSETX:
874	case TCSETXW:
875	case TCSETXF:
876		return -ENOTTY;
877#endif
878	case TIOCGSOFTCAR:
879		copy_termios(real_tty, &kterm);
880		ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0,
881						(int __user *)arg);
882		return ret;
883	case TIOCSSOFTCAR:
884		if (get_user(arg, (unsigned int __user *) arg))
885			return -EFAULT;
886		return tty_change_softcar(real_tty, arg);
887	default:
888		return -ENOIOCTLCMD;
889	}
890}
891EXPORT_SYMBOL_GPL(tty_mode_ioctl);
892
893
894/* Caller guarantees ldisc reference is held */
895static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
896{
897	struct tty_ldisc *ld = tty->ldisc;
898
899	switch (arg) {
900	case TCIFLUSH:
901		if (ld && ld->ops->flush_buffer) {
902			ld->ops->flush_buffer(tty);
903			tty_unthrottle(tty);
904		}
905		break;
906	case TCIOFLUSH:
907		if (ld && ld->ops->flush_buffer) {
908			ld->ops->flush_buffer(tty);
909			tty_unthrottle(tty);
910		}
911		fallthrough;
912	case TCOFLUSH:
913		tty_driver_flush_buffer(tty);
914		break;
915	default:
916		return -EINVAL;
917	}
918	return 0;
919}
920
921int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
922{
923	struct tty_ldisc *ld;
924	int retval = tty_check_change(tty);
925	if (retval)
926		return retval;
927
928	ld = tty_ldisc_ref_wait(tty);
929	retval = __tty_perform_flush(tty, arg);
930	if (ld)
931		tty_ldisc_deref(ld);
932	return retval;
933}
934EXPORT_SYMBOL_GPL(tty_perform_flush);
935
936int n_tty_ioctl_helper(struct tty_struct *tty, unsigned int cmd,
937		unsigned long arg)
938{
939	int retval;
940
941	switch (cmd) {
942	case TCXONC:
943		retval = tty_check_change(tty);
944		if (retval)
945			return retval;
946		switch (arg) {
947		case TCOOFF:
948			spin_lock_irq(&tty->flow.lock);
949			if (!tty->flow.tco_stopped) {
950				tty->flow.tco_stopped = true;
951				__stop_tty(tty);
952			}
953			spin_unlock_irq(&tty->flow.lock);
954			break;
955		case TCOON:
956			spin_lock_irq(&tty->flow.lock);
957			if (tty->flow.tco_stopped) {
958				tty->flow.tco_stopped = false;
959				__start_tty(tty);
960			}
961			spin_unlock_irq(&tty->flow.lock);
962			break;
963		case TCIOFF:
964			if (STOP_CHAR(tty) != __DISABLED_CHAR)
965				retval = tty_send_xchar(tty, STOP_CHAR(tty));
966			break;
967		case TCION:
968			if (START_CHAR(tty) != __DISABLED_CHAR)
969				retval = tty_send_xchar(tty, START_CHAR(tty));
970			break;
971		default:
972			return -EINVAL;
973		}
974		return retval;
975	case TCFLSH:
976		retval = tty_check_change(tty);
977		if (retval)
978			return retval;
979		return __tty_perform_flush(tty, arg);
980	default:
981		/* Try the mode commands */
982		return tty_mode_ioctl(tty, cmd, arg);
983	}
984}
985EXPORT_SYMBOL(n_tty_ioctl_helper);
~/ Read-only file preview.