1#include <linux/types.h>
2#include <linux/errno.h>
3#include <linux/kmod.h>
4#include <linux/sched.h>
5#include <linux/interrupt.h>
6#include <linux/tty.h>
7#include <linux/tty_driver.h>
8#include <linux/file.h>
9#include <linux/mm.h>
10#include <linux/string.h>
11#include <linux/slab.h>
12#include <linux/poll.h>
13#include <linux/proc_fs.h>
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/wait.h>
17#include <linux/bitops.h>
18#include <linux/seq_file.h>
19#include <linux/uaccess.h>
20#include <linux/ratelimit.h>
21
22#undef LDISC_DEBUG_HANGUP
23
24#ifdef LDISC_DEBUG_HANGUP
25#define tty_ldisc_debug(tty, f, args...) tty_debug(tty, f, ##args)
26#else
27#define tty_ldisc_debug(tty, f, args...)
28#endif
29
30
31enum {
32 LDISC_SEM_NORMAL,
33 LDISC_SEM_OTHER,
34};
35
36
37
38
39
40
41
42
43static DEFINE_RAW_SPINLOCK(tty_ldiscs_lock);
44
45static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
61{
62 unsigned long flags;
63 int ret = 0;
64
65 if (disc < N_TTY || disc >= NR_LDISCS)
66 return -EINVAL;
67
68 raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
69 tty_ldiscs[disc] = new_ldisc;
70 new_ldisc->num = disc;
71 new_ldisc->refcount = 0;
72 raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
73
74 return ret;
75}
76EXPORT_SYMBOL(tty_register_ldisc);
77
78
79
80
81
82
83
84
85
86
87
88
89
90int tty_unregister_ldisc(int disc)
91{
92 unsigned long flags;
93 int ret = 0;
94
95 if (disc < N_TTY || disc >= NR_LDISCS)
96 return -EINVAL;
97
98 raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
99 if (tty_ldiscs[disc]->refcount)
100 ret = -EBUSY;
101 else
102 tty_ldiscs[disc] = NULL;
103 raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
104
105 return ret;
106}
107EXPORT_SYMBOL(tty_unregister_ldisc);
108
109static struct tty_ldisc_ops *get_ldops(int disc)
110{
111 unsigned long flags;
112 struct tty_ldisc_ops *ldops, *ret;
113
114 raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
115 ret = ERR_PTR(-EINVAL);
116 ldops = tty_ldiscs[disc];
117 if (ldops) {
118 ret = ERR_PTR(-EAGAIN);
119 if (try_module_get(ldops->owner)) {
120 ldops->refcount++;
121 ret = ldops;
122 }
123 }
124 raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
125 return ret;
126}
127
128static void put_ldops(struct tty_ldisc_ops *ldops)
129{
130 unsigned long flags;
131
132 raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
133 ldops->refcount--;
134 module_put(ldops->owner);
135 raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
136}
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
159{
160 struct tty_ldisc *ld;
161 struct tty_ldisc_ops *ldops;
162
163 if (disc < N_TTY || disc >= NR_LDISCS)
164 return ERR_PTR(-EINVAL);
165
166
167
168
169
170 ldops = get_ldops(disc);
171 if (IS_ERR(ldops)) {
172 request_module("tty-ldisc-%d", disc);
173 ldops = get_ldops(disc);
174 if (IS_ERR(ldops))
175 return ERR_CAST(ldops);
176 }
177
178 ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL);
179 if (ld == NULL) {
180 put_ldops(ldops);
181 return ERR_PTR(-ENOMEM);
182 }
183
184 ld->ops = ldops;
185 ld->tty = tty;
186
187 return ld;
188}
189
190
191
192
193
194
195static void tty_ldisc_put(struct tty_ldisc *ld)
196{
197 if (WARN_ON_ONCE(!ld))
198 return;
199
200 put_ldops(ld->ops);
201 kfree(ld);
202}
203
204static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
205{
206 return (*pos < NR_LDISCS) ? pos : NULL;
207}
208
209static void *tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
210{
211 (*pos)++;
212 return (*pos < NR_LDISCS) ? pos : NULL;
213}
214
215static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
216{
217}
218
219static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
220{
221 int i = *(loff_t *)v;
222 struct tty_ldisc_ops *ldops;
223
224 ldops = get_ldops(i);
225 if (IS_ERR(ldops))
226 return 0;
227 seq_printf(m, "%-10s %2d\n", ldops->name ? ldops->name : "???", i);
228 put_ldops(ldops);
229 return 0;
230}
231
232static const struct seq_operations tty_ldiscs_seq_ops = {
233 .start = tty_ldiscs_seq_start,
234 .next = tty_ldiscs_seq_next,
235 .stop = tty_ldiscs_seq_stop,
236 .show = tty_ldiscs_seq_show,
237};
238
239static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
240{
241 return seq_open(file, &tty_ldiscs_seq_ops);
242}
243
244const struct file_operations tty_ldiscs_proc_fops = {
245 .owner = THIS_MODULE,
246 .open = proc_tty_ldiscs_open,
247 .read = seq_read,
248 .llseek = seq_lseek,
249 .release = seq_release,
250};
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
273{
274 ldsem_down_read(&tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT);
275 if (!tty->ldisc)
276 ldsem_up_read(&tty->ldisc_sem);
277 return tty->ldisc;
278}
279EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
280
281
282
283
284
285
286
287
288
289
290struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
291{
292 struct tty_ldisc *ld = NULL;
293
294 if (ldsem_down_read_trylock(&tty->ldisc_sem)) {
295 ld = tty->ldisc;
296 if (!ld)
297 ldsem_up_read(&tty->ldisc_sem);
298 }
299 return ld;
300}
301EXPORT_SYMBOL_GPL(tty_ldisc_ref);
302
303
304
305
306
307
308
309
310
311void tty_ldisc_deref(struct tty_ldisc *ld)
312{
313 ldsem_up_read(&ld->tty->ldisc_sem);
314}
315EXPORT_SYMBOL_GPL(tty_ldisc_deref);
316
317
318static inline int
319__tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)
320{
321 return ldsem_down_write(&tty->ldisc_sem, timeout);
322}
323
324static inline int
325__tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout)
326{
327 return ldsem_down_write_nested(&tty->ldisc_sem,
328 LDISC_SEM_OTHER, timeout);
329}
330
331static inline void __tty_ldisc_unlock(struct tty_struct *tty)
332{
333 ldsem_up_write(&tty->ldisc_sem);
334}
335
336static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)
337{
338 int ret;
339
340 ret = __tty_ldisc_lock(tty, timeout);
341 if (!ret)
342 return -EBUSY;
343 set_bit(TTY_LDISC_HALTED, &tty->flags);
344 return 0;
345}
346
347static void tty_ldisc_unlock(struct tty_struct *tty)
348{
349 clear_bit(TTY_LDISC_HALTED, &tty->flags);
350 __tty_ldisc_unlock(tty);
351}
352
353static int
354tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2,
355 unsigned long timeout)
356{
357 int ret;
358
359 if (tty < tty2) {
360 ret = __tty_ldisc_lock(tty, timeout);
361 if (ret) {
362 ret = __tty_ldisc_lock_nested(tty2, timeout);
363 if (!ret)
364 __tty_ldisc_unlock(tty);
365 }
366 } else {
367
368 WARN_ON_ONCE(tty == tty2);
369 if (tty2 && tty != tty2) {
370 ret = __tty_ldisc_lock(tty2, timeout);
371 if (ret) {
372 ret = __tty_ldisc_lock_nested(tty, timeout);
373 if (!ret)
374 __tty_ldisc_unlock(tty2);
375 }
376 } else
377 ret = __tty_ldisc_lock(tty, timeout);
378 }
379
380 if (!ret)
381 return -EBUSY;
382
383 set_bit(TTY_LDISC_HALTED, &tty->flags);
384 if (tty2)
385 set_bit(TTY_LDISC_HALTED, &tty2->flags);
386 return 0;
387}
388
389static void tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2)
390{
391 tty_ldisc_lock_pair_timeout(tty, tty2, MAX_SCHEDULE_TIMEOUT);
392}
393
394static void tty_ldisc_unlock_pair(struct tty_struct *tty,
395 struct tty_struct *tty2)
396{
397 __tty_ldisc_unlock(tty);
398 if (tty2)
399 __tty_ldisc_unlock(tty2);
400}
401
402
403
404
405
406
407
408
409
410void tty_ldisc_flush(struct tty_struct *tty)
411{
412 struct tty_ldisc *ld = tty_ldisc_ref(tty);
413
414 tty_buffer_flush(tty, ld);
415 if (ld)
416 tty_ldisc_deref(ld);
417}
418EXPORT_SYMBOL_GPL(tty_ldisc_flush);
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436static void tty_set_termios_ldisc(struct tty_struct *tty, int disc)
437{
438 down_write(&tty->termios_rwsem);
439 tty->termios.c_line = disc;
440 up_write(&tty->termios_rwsem);
441
442 tty->disc_data = NULL;
443 tty->receive_room = 0;
444}
445
446
447
448
449
450
451
452
453
454
455
456
457static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
458{
459 WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
460 if (ld->ops->open) {
461 int ret;
462
463 ret = ld->ops->open(tty);
464 if (ret)
465 clear_bit(TTY_LDISC_OPEN, &tty->flags);
466
467 tty_ldisc_debug(tty, "%p: opened\n", ld);
468 return ret;
469 }
470 return 0;
471}
472
473
474
475
476
477
478
479
480
481
482static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
483{
484 WARN_ON(!test_bit(TTY_LDISC_OPEN, &tty->flags));
485 clear_bit(TTY_LDISC_OPEN, &tty->flags);
486 if (ld->ops->close)
487 ld->ops->close(tty);
488 tty_ldisc_debug(tty, "%p: closed\n", ld);
489}
490
491
492
493
494
495
496
497
498
499
500static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
501{
502 struct tty_ldisc *new_ldisc;
503 int r;
504
505
506 old = tty_ldisc_get(tty, old->ops->num);
507 WARN_ON(IS_ERR(old));
508 tty->ldisc = old;
509 tty_set_termios_ldisc(tty, old->ops->num);
510 if (tty_ldisc_open(tty, old) < 0) {
511 tty_ldisc_put(old);
512
513 new_ldisc = tty_ldisc_get(tty, N_TTY);
514 if (IS_ERR(new_ldisc))
515 panic("n_tty: get");
516 tty->ldisc = new_ldisc;
517 tty_set_termios_ldisc(tty, N_TTY);
518 r = tty_ldisc_open(tty, new_ldisc);
519 if (r < 0)
520 panic("Couldn't open N_TTY ldisc for "
521 "%s --- error %d.",
522 tty_name(tty), r);
523 }
524}
525
526
527
528
529
530
531
532
533
534
535
536
537int tty_set_ldisc(struct tty_struct *tty, int disc)
538{
539 int retval;
540 struct tty_ldisc *old_ldisc, *new_ldisc;
541
542 new_ldisc = tty_ldisc_get(tty, disc);
543 if (IS_ERR(new_ldisc))
544 return PTR_ERR(new_ldisc);
545
546 tty_lock(tty);
547 retval = tty_ldisc_lock(tty, 5 * HZ);
548 if (retval)
549 goto err;
550
551 if (!tty->ldisc) {
552 retval = -EIO;
553 goto out;
554 }
555
556
557 if (tty->ldisc->ops->num == disc)
558 goto out;
559
560 if (test_bit(TTY_HUPPED, &tty->flags)) {
561
562 retval = -EIO;
563 goto out;
564 }
565
566 old_ldisc = tty->ldisc;
567
568
569 tty_ldisc_close(tty, old_ldisc);
570
571
572 tty->ldisc = new_ldisc;
573 tty_set_termios_ldisc(tty, disc);
574
575 retval = tty_ldisc_open(tty, new_ldisc);
576 if (retval < 0) {
577
578 tty_ldisc_put(new_ldisc);
579 tty_ldisc_restore(tty, old_ldisc);
580 }
581
582 if (tty->ldisc->ops->num != old_ldisc->ops->num && tty->ops->set_ldisc) {
583 down_read(&tty->termios_rwsem);
584 tty->ops->set_ldisc(tty);
585 up_read(&tty->termios_rwsem);
586 }
587
588
589
590
591
592
593 new_ldisc = old_ldisc;
594out:
595 tty_ldisc_unlock(tty);
596
597
598
599 tty_buffer_restart_work(tty->port);
600err:
601 tty_ldisc_put(new_ldisc);
602 tty_unlock(tty);
603 return retval;
604}
605
606
607
608
609
610
611
612static void tty_ldisc_kill(struct tty_struct *tty)
613{
614 if (!tty->ldisc)
615 return;
616
617
618
619 tty_ldisc_close(tty, tty->ldisc);
620 tty_ldisc_put(tty->ldisc);
621
622 tty->ldisc = NULL;
623}
624
625
626
627
628
629
630
631
632static void tty_reset_termios(struct tty_struct *tty)
633{
634 down_write(&tty->termios_rwsem);
635 tty->termios = tty->driver->init_termios;
636 tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios);
637 tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios);
638 up_write(&tty->termios_rwsem);
639}
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656int tty_ldisc_reinit(struct tty_struct *tty, int disc)
657{
658 struct tty_ldisc *ld;
659 int retval;
660
661 ld = tty_ldisc_get(tty, disc);
662 if (IS_ERR(ld)) {
663 BUG_ON(disc == N_TTY);
664 return PTR_ERR(ld);
665 }
666
667 if (tty->ldisc) {
668 tty_ldisc_close(tty, tty->ldisc);
669 tty_ldisc_put(tty->ldisc);
670 }
671
672
673 tty->ldisc = ld;
674 tty_set_termios_ldisc(tty, disc);
675 retval = tty_ldisc_open(tty, tty->ldisc);
676 if (retval) {
677 if (!WARN_ON(disc == N_TTY)) {
678 tty_ldisc_put(tty->ldisc);
679 tty->ldisc = NULL;
680 }
681 }
682 return retval;
683}
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700void tty_ldisc_hangup(struct tty_struct *tty, bool reinit)
701{
702 struct tty_ldisc *ld;
703
704 tty_ldisc_debug(tty, "%p: hangup\n", tty->ldisc);
705
706 ld = tty_ldisc_ref(tty);
707 if (ld != NULL) {
708 if (ld->ops->flush_buffer)
709 ld->ops->flush_buffer(tty);
710 tty_driver_flush_buffer(tty);
711 if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
712 ld->ops->write_wakeup)
713 ld->ops->write_wakeup(tty);
714 if (ld->ops->hangup)
715 ld->ops->hangup(tty);
716 tty_ldisc_deref(ld);
717 }
718
719 wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
720 wake_up_interruptible_poll(&tty->read_wait, POLLIN);
721
722
723
724
725
726
727
728 tty_ldisc_lock(tty, MAX_SCHEDULE_TIMEOUT);
729
730 if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
731 tty_reset_termios(tty);
732
733 if (tty->ldisc) {
734 if (reinit) {
735 if (tty_ldisc_reinit(tty, tty->termios.c_line) < 0)
736 tty_ldisc_reinit(tty, N_TTY);
737 } else
738 tty_ldisc_kill(tty);
739 }
740 tty_ldisc_unlock(tty);
741}
742
743
744
745
746
747
748
749
750
751
752
753int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
754{
755 int retval = tty_ldisc_open(tty, tty->ldisc);
756 if (retval)
757 return retval;
758
759 if (o_tty) {
760 retval = tty_ldisc_open(o_tty, o_tty->ldisc);
761 if (retval) {
762 tty_ldisc_close(tty, tty->ldisc);
763 return retval;
764 }
765 }
766 return 0;
767}
768
769
770
771
772
773
774
775
776
777void tty_ldisc_release(struct tty_struct *tty)
778{
779 struct tty_struct *o_tty = tty->link;
780
781
782
783
784
785
786 tty_ldisc_lock_pair(tty, o_tty);
787 tty_ldisc_kill(tty);
788 if (o_tty)
789 tty_ldisc_kill(o_tty);
790 tty_ldisc_unlock_pair(tty, o_tty);
791
792
793
794
795 tty_ldisc_debug(tty, "released\n");
796}
797
798
799
800
801
802
803
804
805
806void tty_ldisc_init(struct tty_struct *tty)
807{
808 struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY);
809 if (IS_ERR(ld))
810 panic("n_tty: init_tty");
811 tty->ldisc = ld;
812}
813
814
815
816
817
818
819
820
821void tty_ldisc_deinit(struct tty_struct *tty)
822{
823 if (tty->ldisc)
824 tty_ldisc_put(tty->ldisc);
825 tty->ldisc = NULL;
826}
827