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