1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <linux/types.h> |
3 | #include <linux/errno.h> |
4 | #include <linux/kmod.h> |
5 | #include <linux/sched.h> |
6 | #include <linux/interrupt.h> |
7 | #include <linux/tty.h> |
8 | #include <linux/tty_driver.h> |
9 | #include <linux/file.h> |
10 | #include <linux/mm.h> |
11 | #include <linux/string.h> |
12 | #include <linux/slab.h> |
13 | #include <linux/poll.h> |
14 | #include <linux/proc_fs.h> |
15 | #include <linux/module.h> |
16 | #include <linux/device.h> |
17 | #include <linux/wait.h> |
18 | #include <linux/bitops.h> |
19 | #include <linux/seq_file.h> |
20 | #include <linux/uaccess.h> |
21 | #include <linux/ratelimit.h> |
22 | #include "tty.h" |
23 | |
24 | #undef LDISC_DEBUG_HANGUP |
25 | |
26 | #ifdef LDISC_DEBUG_HANGUP |
27 | #define tty_ldisc_debug(tty, f, args...) tty_debug(tty, f, ##args) |
28 | #else |
29 | #define tty_ldisc_debug(tty, f, args...) |
30 | #endif |
31 | |
32 | /* lockdep nested classes for tty->ldisc_sem */ |
33 | enum { |
34 | LDISC_SEM_NORMAL, |
35 | LDISC_SEM_OTHER, |
36 | }; |
37 | |
38 | |
39 | /* |
40 | * This guards the refcounted line discipline lists. The lock |
41 | * must be taken with irqs off because there are hangup path |
42 | * callers who will do ldisc lookups and cannot sleep. |
43 | */ |
44 | |
45 | static DEFINE_RAW_SPINLOCK(tty_ldiscs_lock); |
46 | /* Line disc dispatch table */ |
47 | static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; |
48 | |
49 | /** |
50 | * tty_register_ldisc - install a line discipline |
51 | * @new_ldisc: pointer to the ldisc object |
52 | * |
53 | * Installs a new line discipline into the kernel. The discipline is set up as |
54 | * unreferenced and then made available to the kernel from this point onwards. |
55 | * |
56 | * Locking: takes %tty_ldiscs_lock to guard against ldisc races |
57 | */ |
58 | int tty_register_ldisc(struct tty_ldisc_ops *new_ldisc) |
59 | { |
60 | unsigned long flags; |
61 | |
62 | if (new_ldisc->num < N_TTY || new_ldisc->num >= NR_LDISCS) |
63 | return -EINVAL; |
64 | |
65 | raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); |
66 | tty_ldiscs[new_ldisc->num] = new_ldisc; |
67 | raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); |
68 | |
69 | return 0; |
70 | } |
71 | EXPORT_SYMBOL(tty_register_ldisc); |
72 | |
73 | /** |
74 | * tty_unregister_ldisc - unload a line discipline |
75 | * @ldisc: ldisc number |
76 | * |
77 | * Remove a line discipline from the kernel providing it is not currently in |
78 | * use. |
79 | * |
80 | * Locking: takes %tty_ldiscs_lock to guard against ldisc races |
81 | */ |
82 | |
83 | void tty_unregister_ldisc(struct tty_ldisc_ops *ldisc) |
84 | { |
85 | unsigned long flags; |
86 | |
87 | raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); |
88 | tty_ldiscs[ldisc->num] = NULL; |
89 | raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); |
90 | } |
91 | EXPORT_SYMBOL(tty_unregister_ldisc); |
92 | |
93 | static struct tty_ldisc_ops *get_ldops(int disc) |
94 | { |
95 | unsigned long flags; |
96 | struct tty_ldisc_ops *ldops, *ret; |
97 | |
98 | raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); |
99 | ret = ERR_PTR(error: -EINVAL); |
100 | ldops = tty_ldiscs[disc]; |
101 | if (ldops) { |
102 | ret = ERR_PTR(error: -EAGAIN); |
103 | if (try_module_get(module: ldops->owner)) |
104 | ret = ldops; |
105 | } |
106 | raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); |
107 | return ret; |
108 | } |
109 | |
110 | static void put_ldops(struct tty_ldisc_ops *ldops) |
111 | { |
112 | unsigned long flags; |
113 | |
114 | raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); |
115 | module_put(module: ldops->owner); |
116 | raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); |
117 | } |
118 | |
119 | int tty_ldisc_autoload = IS_BUILTIN(CONFIG_LDISC_AUTOLOAD); |
120 | |
121 | /** |
122 | * tty_ldisc_get - take a reference to an ldisc |
123 | * @tty: tty device |
124 | * @disc: ldisc number |
125 | * |
126 | * Takes a reference to a line discipline. Deals with refcounts and module |
127 | * locking counts. If the discipline is not available, its module loaded, if |
128 | * possible. |
129 | * |
130 | * Returns: |
131 | * * -%EINVAL if the discipline index is not [%N_TTY .. %NR_LDISCS] or if the |
132 | * discipline is not registered |
133 | * * -%EAGAIN if request_module() failed to load or register the discipline |
134 | * * -%ENOMEM if allocation failure |
135 | * * Otherwise, returns a pointer to the discipline and bumps the ref count |
136 | * |
137 | * Locking: takes %tty_ldiscs_lock to guard against ldisc races |
138 | */ |
139 | static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) |
140 | { |
141 | struct tty_ldisc *ld; |
142 | struct tty_ldisc_ops *ldops; |
143 | |
144 | if (disc < N_TTY || disc >= NR_LDISCS) |
145 | return ERR_PTR(error: -EINVAL); |
146 | |
147 | /* |
148 | * Get the ldisc ops - we may need to request them to be loaded |
149 | * dynamically and try again. |
150 | */ |
151 | ldops = get_ldops(disc); |
152 | if (IS_ERR(ptr: ldops)) { |
153 | if (!capable(CAP_SYS_MODULE) && !tty_ldisc_autoload) |
154 | return ERR_PTR(error: -EPERM); |
155 | request_module("tty-ldisc-%d" , disc); |
156 | ldops = get_ldops(disc); |
157 | if (IS_ERR(ptr: ldops)) |
158 | return ERR_CAST(ptr: ldops); |
159 | } |
160 | |
161 | /* |
162 | * There is no way to handle allocation failure of only 16 bytes. |
163 | * Let's simplify error handling and save more memory. |
164 | */ |
165 | ld = kmalloc(size: sizeof(struct tty_ldisc), GFP_KERNEL | __GFP_NOFAIL); |
166 | ld->ops = ldops; |
167 | ld->tty = tty; |
168 | |
169 | return ld; |
170 | } |
171 | |
172 | /** |
173 | * tty_ldisc_put - release the ldisc |
174 | * @ld: lisdsc to release |
175 | * |
176 | * Complement of tty_ldisc_get(). |
177 | */ |
178 | static void tty_ldisc_put(struct tty_ldisc *ld) |
179 | { |
180 | if (WARN_ON_ONCE(!ld)) |
181 | return; |
182 | |
183 | put_ldops(ldops: ld->ops); |
184 | kfree(objp: ld); |
185 | } |
186 | |
187 | static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) |
188 | { |
189 | return (*pos < NR_LDISCS) ? pos : NULL; |
190 | } |
191 | |
192 | static void *tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) |
193 | { |
194 | (*pos)++; |
195 | return (*pos < NR_LDISCS) ? pos : NULL; |
196 | } |
197 | |
198 | static void tty_ldiscs_seq_stop(struct seq_file *m, void *v) |
199 | { |
200 | } |
201 | |
202 | static int tty_ldiscs_seq_show(struct seq_file *m, void *v) |
203 | { |
204 | int i = *(loff_t *)v; |
205 | struct tty_ldisc_ops *ldops; |
206 | |
207 | ldops = get_ldops(disc: i); |
208 | if (IS_ERR(ptr: ldops)) |
209 | return 0; |
210 | seq_printf(m, fmt: "%-10s %2d\n" , ldops->name ? ldops->name : "???" , i); |
211 | put_ldops(ldops); |
212 | return 0; |
213 | } |
214 | |
215 | const struct seq_operations tty_ldiscs_seq_ops = { |
216 | .start = tty_ldiscs_seq_start, |
217 | .next = tty_ldiscs_seq_next, |
218 | .stop = tty_ldiscs_seq_stop, |
219 | .show = tty_ldiscs_seq_show, |
220 | }; |
221 | |
222 | /** |
223 | * tty_ldisc_ref_wait - wait for the tty ldisc |
224 | * @tty: tty device |
225 | * |
226 | * Dereference the line discipline for the terminal and take a reference to it. |
227 | * If the line discipline is in flux then wait patiently until it changes. |
228 | * |
229 | * Returns: %NULL if the tty has been hungup and not re-opened with a new file |
230 | * descriptor, otherwise valid ldisc reference |
231 | * |
232 | * Note 1: Must not be called from an IRQ/timer context. The caller must also |
233 | * be careful not to hold other locks that will deadlock against a discipline |
234 | * change, such as an existing ldisc reference (which we check for). |
235 | * |
236 | * Note 2: a file_operations routine (read/poll/write) should use this function |
237 | * to wait for any ldisc lifetime events to finish. |
238 | */ |
239 | struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) |
240 | { |
241 | struct tty_ldisc *ld; |
242 | |
243 | ldsem_down_read(sem: &tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT); |
244 | ld = tty->ldisc; |
245 | if (!ld) |
246 | ldsem_up_read(sem: &tty->ldisc_sem); |
247 | return ld; |
248 | } |
249 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); |
250 | |
251 | /** |
252 | * tty_ldisc_ref - get the tty ldisc |
253 | * @tty: tty device |
254 | * |
255 | * Dereference the line discipline for the terminal and take a reference to it. |
256 | * If the line discipline is in flux then return %NULL. Can be called from IRQ |
257 | * and timer functions. |
258 | */ |
259 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) |
260 | { |
261 | struct tty_ldisc *ld = NULL; |
262 | |
263 | if (ldsem_down_read_trylock(sem: &tty->ldisc_sem)) { |
264 | ld = tty->ldisc; |
265 | if (!ld) |
266 | ldsem_up_read(sem: &tty->ldisc_sem); |
267 | } |
268 | return ld; |
269 | } |
270 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); |
271 | |
272 | /** |
273 | * tty_ldisc_deref - free a tty ldisc reference |
274 | * @ld: reference to free up |
275 | * |
276 | * Undoes the effect of tty_ldisc_ref() or tty_ldisc_ref_wait(). May be called |
277 | * in IRQ context. |
278 | */ |
279 | void tty_ldisc_deref(struct tty_ldisc *ld) |
280 | { |
281 | ldsem_up_read(sem: &ld->tty->ldisc_sem); |
282 | } |
283 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); |
284 | |
285 | |
286 | static inline int |
287 | __tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) |
288 | { |
289 | return ldsem_down_write(sem: &tty->ldisc_sem, timeout); |
290 | } |
291 | |
292 | static inline int |
293 | __tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout) |
294 | { |
295 | return ldsem_down_write_nested(sem: &tty->ldisc_sem, |
296 | subclass: LDISC_SEM_OTHER, timeout); |
297 | } |
298 | |
299 | static inline void __tty_ldisc_unlock(struct tty_struct *tty) |
300 | { |
301 | ldsem_up_write(sem: &tty->ldisc_sem); |
302 | } |
303 | |
304 | int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) |
305 | { |
306 | int ret; |
307 | |
308 | /* Kindly asking blocked readers to release the read side */ |
309 | set_bit(TTY_LDISC_CHANGING, addr: &tty->flags); |
310 | wake_up_interruptible_all(&tty->read_wait); |
311 | wake_up_interruptible_all(&tty->write_wait); |
312 | |
313 | ret = __tty_ldisc_lock(tty, timeout); |
314 | if (!ret) |
315 | return -EBUSY; |
316 | set_bit(TTY_LDISC_HALTED, addr: &tty->flags); |
317 | return 0; |
318 | } |
319 | |
320 | void tty_ldisc_unlock(struct tty_struct *tty) |
321 | { |
322 | clear_bit(TTY_LDISC_HALTED, addr: &tty->flags); |
323 | /* Can be cleared here - ldisc_unlock will wake up writers firstly */ |
324 | clear_bit(TTY_LDISC_CHANGING, addr: &tty->flags); |
325 | __tty_ldisc_unlock(tty); |
326 | } |
327 | |
328 | static int |
329 | tty_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(tty: tty2, timeout); |
338 | if (!ret) |
339 | __tty_ldisc_unlock(tty); |
340 | } |
341 | } else { |
342 | /* if this is possible, it has lots of implications */ |
343 | WARN_ON_ONCE(tty == tty2); |
344 | if (tty2 && tty != tty2) { |
345 | ret = __tty_ldisc_lock(tty: tty2, timeout); |
346 | if (ret) { |
347 | ret = __tty_ldisc_lock_nested(tty, timeout); |
348 | if (!ret) |
349 | __tty_ldisc_unlock(tty: 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, addr: &tty->flags); |
359 | if (tty2) |
360 | set_bit(TTY_LDISC_HALTED, addr: &tty2->flags); |
361 | return 0; |
362 | } |
363 | |
364 | static void tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2) |
365 | { |
366 | tty_ldisc_lock_pair_timeout(tty, tty2, MAX_SCHEDULE_TIMEOUT); |
367 | } |
368 | |
369 | static void tty_ldisc_unlock_pair(struct tty_struct *tty, |
370 | struct tty_struct *tty2) |
371 | { |
372 | __tty_ldisc_unlock(tty); |
373 | if (tty2) |
374 | __tty_ldisc_unlock(tty: tty2); |
375 | } |
376 | |
377 | /** |
378 | * tty_ldisc_flush - flush line discipline queue |
379 | * @tty: tty to flush ldisc for |
380 | * |
381 | * Flush the line discipline queue (if any) and the tty flip buffers for this |
382 | * @tty. |
383 | */ |
384 | void tty_ldisc_flush(struct tty_struct *tty) |
385 | { |
386 | struct tty_ldisc *ld = tty_ldisc_ref(tty); |
387 | |
388 | tty_buffer_flush(tty, ld); |
389 | if (ld) |
390 | tty_ldisc_deref(ld); |
391 | } |
392 | EXPORT_SYMBOL_GPL(tty_ldisc_flush); |
393 | |
394 | /** |
395 | * tty_set_termios_ldisc - set ldisc field |
396 | * @tty: tty structure |
397 | * @disc: line discipline number |
398 | * |
399 | * This is probably overkill for real world processors but they are not on hot |
400 | * paths so a little discipline won't do any harm. |
401 | * |
402 | * The line discipline-related tty_struct fields are reset to prevent the ldisc |
403 | * driver from re-using stale information for the new ldisc instance. |
404 | * |
405 | * Locking: takes termios_rwsem |
406 | */ |
407 | static void tty_set_termios_ldisc(struct tty_struct *tty, int disc) |
408 | { |
409 | down_write(sem: &tty->termios_rwsem); |
410 | tty->termios.c_line = disc; |
411 | up_write(sem: &tty->termios_rwsem); |
412 | |
413 | tty->disc_data = NULL; |
414 | tty->receive_room = 0; |
415 | } |
416 | |
417 | /** |
418 | * tty_ldisc_open - open a line discipline |
419 | * @tty: tty we are opening the ldisc on |
420 | * @ld: discipline to open |
421 | * |
422 | * A helper opening method. Also a convenient debugging and check point. |
423 | * |
424 | * Locking: always called with BTM already held. |
425 | */ |
426 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) |
427 | { |
428 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); |
429 | if (ld->ops->open) { |
430 | int ret; |
431 | /* BTM here locks versus a hangup event */ |
432 | ret = ld->ops->open(tty); |
433 | if (ret) |
434 | clear_bit(TTY_LDISC_OPEN, addr: &tty->flags); |
435 | |
436 | tty_ldisc_debug(tty, "%p: opened\n" , ld); |
437 | return ret; |
438 | } |
439 | return 0; |
440 | } |
441 | |
442 | /** |
443 | * tty_ldisc_close - close a line discipline |
444 | * @tty: tty we are opening the ldisc on |
445 | * @ld: discipline to close |
446 | * |
447 | * A helper close method. Also a convenient debugging and check point. |
448 | */ |
449 | static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) |
450 | { |
451 | lockdep_assert_held_write(&tty->ldisc_sem); |
452 | WARN_ON(!test_bit(TTY_LDISC_OPEN, &tty->flags)); |
453 | clear_bit(TTY_LDISC_OPEN, addr: &tty->flags); |
454 | if (ld->ops->close) |
455 | ld->ops->close(tty); |
456 | tty_ldisc_debug(tty, "%p: closed\n" , ld); |
457 | } |
458 | |
459 | /** |
460 | * tty_ldisc_failto - helper for ldisc failback |
461 | * @tty: tty to open the ldisc on |
462 | * @ld: ldisc we are trying to fail back to |
463 | * |
464 | * Helper to try and recover a tty when switching back to the old ldisc fails |
465 | * and we need something attached. |
466 | */ |
467 | static int tty_ldisc_failto(struct tty_struct *tty, int ld) |
468 | { |
469 | struct tty_ldisc *disc = tty_ldisc_get(tty, disc: ld); |
470 | int r; |
471 | |
472 | lockdep_assert_held_write(&tty->ldisc_sem); |
473 | if (IS_ERR(ptr: disc)) |
474 | return PTR_ERR(ptr: disc); |
475 | tty->ldisc = disc; |
476 | tty_set_termios_ldisc(tty, disc: ld); |
477 | r = tty_ldisc_open(tty, ld: disc); |
478 | if (r < 0) |
479 | tty_ldisc_put(ld: disc); |
480 | return r; |
481 | } |
482 | |
483 | /** |
484 | * tty_ldisc_restore - helper for tty ldisc change |
485 | * @tty: tty to recover |
486 | * @old: previous ldisc |
487 | * |
488 | * Restore the previous line discipline or %N_TTY when a line discipline change |
489 | * fails due to an open error |
490 | */ |
491 | static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) |
492 | { |
493 | /* There is an outstanding reference here so this is safe */ |
494 | if (tty_ldisc_failto(tty, ld: old->ops->num) < 0) { |
495 | const char *name = tty_name(tty); |
496 | |
497 | pr_warn("Falling back ldisc for %s.\n" , name); |
498 | /* |
499 | * The traditional behaviour is to fall back to N_TTY, we |
500 | * want to avoid falling back to N_NULL unless we have no |
501 | * choice to avoid the risk of breaking anything |
502 | */ |
503 | if (tty_ldisc_failto(tty, N_TTY) < 0 && |
504 | tty_ldisc_failto(tty, N_NULL) < 0) |
505 | panic(fmt: "Couldn't open N_NULL ldisc for %s." , name); |
506 | } |
507 | } |
508 | |
509 | /** |
510 | * tty_set_ldisc - set line discipline |
511 | * @tty: the terminal to set |
512 | * @disc: the line discipline number |
513 | * |
514 | * Set the discipline of a tty line. Must be called from a process context. The |
515 | * ldisc change logic has to protect itself against any overlapping ldisc |
516 | * change (including on the other end of pty pairs), the close of one side of a |
517 | * tty/pty pair, and eventually hangup. |
518 | */ |
519 | int tty_set_ldisc(struct tty_struct *tty, int disc) |
520 | { |
521 | int retval; |
522 | struct tty_ldisc *old_ldisc, *new_ldisc; |
523 | |
524 | new_ldisc = tty_ldisc_get(tty, disc); |
525 | if (IS_ERR(ptr: new_ldisc)) |
526 | return PTR_ERR(ptr: new_ldisc); |
527 | |
528 | tty_lock(tty); |
529 | retval = tty_ldisc_lock(tty, timeout: 5 * HZ); |
530 | if (retval) |
531 | goto err; |
532 | |
533 | if (!tty->ldisc) { |
534 | retval = -EIO; |
535 | goto out; |
536 | } |
537 | |
538 | /* Check the no-op case */ |
539 | if (tty->ldisc->ops->num == disc) |
540 | goto out; |
541 | |
542 | if (test_bit(TTY_HUPPED, &tty->flags)) { |
543 | /* We were raced by hangup */ |
544 | retval = -EIO; |
545 | goto out; |
546 | } |
547 | |
548 | old_ldisc = tty->ldisc; |
549 | |
550 | /* Shutdown the old discipline. */ |
551 | tty_ldisc_close(tty, ld: old_ldisc); |
552 | |
553 | /* Now set up the new line discipline. */ |
554 | tty->ldisc = new_ldisc; |
555 | tty_set_termios_ldisc(tty, disc); |
556 | |
557 | retval = tty_ldisc_open(tty, ld: new_ldisc); |
558 | if (retval < 0) { |
559 | /* Back to the old one or N_TTY if we can't */ |
560 | tty_ldisc_put(ld: new_ldisc); |
561 | tty_ldisc_restore(tty, old: old_ldisc); |
562 | } |
563 | |
564 | if (tty->ldisc->ops->num != old_ldisc->ops->num && tty->ops->set_ldisc) { |
565 | down_read(sem: &tty->termios_rwsem); |
566 | tty->ops->set_ldisc(tty); |
567 | up_read(sem: &tty->termios_rwsem); |
568 | } |
569 | |
570 | /* |
571 | * At this point we hold a reference to the new ldisc and a |
572 | * reference to the old ldisc, or we hold two references to |
573 | * the old ldisc (if it was restored as part of error cleanup |
574 | * above). In either case, releasing a single reference from |
575 | * the old ldisc is correct. |
576 | */ |
577 | new_ldisc = old_ldisc; |
578 | out: |
579 | tty_ldisc_unlock(tty); |
580 | |
581 | /* |
582 | * Restart the work queue in case no characters kick it off. Safe if |
583 | * already running |
584 | */ |
585 | tty_buffer_restart_work(port: tty->port); |
586 | err: |
587 | tty_ldisc_put(ld: new_ldisc); /* drop the extra reference */ |
588 | tty_unlock(tty); |
589 | return retval; |
590 | } |
591 | EXPORT_SYMBOL_GPL(tty_set_ldisc); |
592 | |
593 | /** |
594 | * tty_ldisc_kill - teardown ldisc |
595 | * @tty: tty being released |
596 | * |
597 | * Perform final close of the ldisc and reset @tty->ldisc |
598 | */ |
599 | static void tty_ldisc_kill(struct tty_struct *tty) |
600 | { |
601 | lockdep_assert_held_write(&tty->ldisc_sem); |
602 | if (!tty->ldisc) |
603 | return; |
604 | /* |
605 | * Now kill off the ldisc |
606 | */ |
607 | tty_ldisc_close(tty, ld: tty->ldisc); |
608 | tty_ldisc_put(ld: tty->ldisc); |
609 | /* Force an oops if we mess this up */ |
610 | tty->ldisc = NULL; |
611 | } |
612 | |
613 | /** |
614 | * tty_reset_termios - reset terminal state |
615 | * @tty: tty to reset |
616 | * |
617 | * Restore a terminal to the driver default state. |
618 | */ |
619 | static void tty_reset_termios(struct tty_struct *tty) |
620 | { |
621 | down_write(sem: &tty->termios_rwsem); |
622 | tty->termios = tty->driver->init_termios; |
623 | tty->termios.c_ispeed = tty_termios_input_baud_rate(termios: &tty->termios); |
624 | tty->termios.c_ospeed = tty_termios_baud_rate(termios: &tty->termios); |
625 | up_write(sem: &tty->termios_rwsem); |
626 | } |
627 | |
628 | |
629 | /** |
630 | * tty_ldisc_reinit - reinitialise the tty ldisc |
631 | * @tty: tty to reinit |
632 | * @disc: line discipline to reinitialize |
633 | * |
634 | * Completely reinitialize the line discipline state, by closing the current |
635 | * instance, if there is one, and opening a new instance. If an error occurs |
636 | * opening the new non-%N_TTY instance, the instance is dropped and @tty->ldisc |
637 | * reset to %NULL. The caller can then retry with %N_TTY instead. |
638 | * |
639 | * Returns: 0 if successful, otherwise error code < 0 |
640 | */ |
641 | int tty_ldisc_reinit(struct tty_struct *tty, int disc) |
642 | { |
643 | struct tty_ldisc *ld; |
644 | int retval; |
645 | |
646 | lockdep_assert_held_write(&tty->ldisc_sem); |
647 | ld = tty_ldisc_get(tty, disc); |
648 | if (IS_ERR(ptr: ld)) { |
649 | BUG_ON(disc == N_TTY); |
650 | return PTR_ERR(ptr: ld); |
651 | } |
652 | |
653 | if (tty->ldisc) { |
654 | tty_ldisc_close(tty, ld: tty->ldisc); |
655 | tty_ldisc_put(ld: tty->ldisc); |
656 | } |
657 | |
658 | /* switch the line discipline */ |
659 | tty->ldisc = ld; |
660 | tty_set_termios_ldisc(tty, disc); |
661 | retval = tty_ldisc_open(tty, ld: tty->ldisc); |
662 | if (retval) { |
663 | tty_ldisc_put(ld: tty->ldisc); |
664 | tty->ldisc = NULL; |
665 | } |
666 | return retval; |
667 | } |
668 | |
669 | /** |
670 | * tty_ldisc_hangup - hangup ldisc reset |
671 | * @tty: tty being hung up |
672 | * @reinit: whether to re-initialise the tty |
673 | * |
674 | * Some tty devices reset their termios when they receive a hangup event. In |
675 | * that situation we must also switch back to %N_TTY properly before we reset |
676 | * the termios data. |
677 | * |
678 | * Locking: We can take the ldisc mutex as the rest of the code is careful to |
679 | * allow for this. |
680 | * |
681 | * In the pty pair case this occurs in the close() path of the tty itself so we |
682 | * must be careful about locking rules. |
683 | */ |
684 | void tty_ldisc_hangup(struct tty_struct *tty, bool reinit) |
685 | { |
686 | struct tty_ldisc *ld; |
687 | |
688 | tty_ldisc_debug(tty, "%p: hangup\n" , tty->ldisc); |
689 | |
690 | ld = tty_ldisc_ref(tty); |
691 | if (ld != NULL) { |
692 | if (ld->ops->flush_buffer) |
693 | ld->ops->flush_buffer(tty); |
694 | tty_driver_flush_buffer(tty); |
695 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && |
696 | ld->ops->write_wakeup) |
697 | ld->ops->write_wakeup(tty); |
698 | if (ld->ops->hangup) |
699 | ld->ops->hangup(tty); |
700 | tty_ldisc_deref(ld); |
701 | } |
702 | |
703 | wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT); |
704 | wake_up_interruptible_poll(&tty->read_wait, EPOLLIN); |
705 | |
706 | /* |
707 | * Shutdown the current line discipline, and reset it to |
708 | * N_TTY if need be. |
709 | * |
710 | * Avoid racing set_ldisc or tty_ldisc_release |
711 | */ |
712 | tty_ldisc_lock(tty, MAX_SCHEDULE_TIMEOUT); |
713 | |
714 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) |
715 | tty_reset_termios(tty); |
716 | |
717 | if (tty->ldisc) { |
718 | if (reinit) { |
719 | if (tty_ldisc_reinit(tty, disc: tty->termios.c_line) < 0 && |
720 | tty_ldisc_reinit(tty, N_TTY) < 0) |
721 | WARN_ON(tty_ldisc_reinit(tty, N_NULL) < 0); |
722 | } else |
723 | tty_ldisc_kill(tty); |
724 | } |
725 | tty_ldisc_unlock(tty); |
726 | } |
727 | |
728 | /** |
729 | * tty_ldisc_setup - open line discipline |
730 | * @tty: tty being shut down |
731 | * @o_tty: pair tty for pty/tty pairs |
732 | * |
733 | * Called during the initial open of a tty/pty pair in order to set up the line |
734 | * disciplines and bind them to the @tty. This has no locking issues as the |
735 | * device isn't yet active. |
736 | */ |
737 | int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) |
738 | { |
739 | int retval = tty_ldisc_open(tty, ld: tty->ldisc); |
740 | |
741 | if (retval) |
742 | return retval; |
743 | |
744 | if (o_tty) { |
745 | /* |
746 | * Called without o_tty->ldisc_sem held, as o_tty has been |
747 | * just allocated and no one has a reference to it. |
748 | */ |
749 | retval = tty_ldisc_open(tty: o_tty, ld: o_tty->ldisc); |
750 | if (retval) { |
751 | tty_ldisc_close(tty, ld: tty->ldisc); |
752 | return retval; |
753 | } |
754 | } |
755 | return 0; |
756 | } |
757 | |
758 | /** |
759 | * tty_ldisc_release - release line discipline |
760 | * @tty: tty being shut down (or one end of pty pair) |
761 | * |
762 | * Called during the final close of a tty or a pty pair in order to shut down |
763 | * the line discpline layer. On exit, each tty's ldisc is %NULL. |
764 | */ |
765 | void tty_ldisc_release(struct tty_struct *tty) |
766 | { |
767 | struct tty_struct *o_tty = tty->link; |
768 | |
769 | /* |
770 | * Shutdown this line discipline. As this is the final close, |
771 | * it does not race with the set_ldisc code path. |
772 | */ |
773 | |
774 | tty_ldisc_lock_pair(tty, tty2: o_tty); |
775 | tty_ldisc_kill(tty); |
776 | if (o_tty) |
777 | tty_ldisc_kill(tty: o_tty); |
778 | tty_ldisc_unlock_pair(tty, tty2: o_tty); |
779 | |
780 | /* |
781 | * And the memory resources remaining (buffers, termios) will be |
782 | * disposed of when the kref hits zero |
783 | */ |
784 | |
785 | tty_ldisc_debug(tty, "released\n" ); |
786 | } |
787 | |
788 | /** |
789 | * tty_ldisc_init - ldisc setup for new tty |
790 | * @tty: tty being allocated |
791 | * |
792 | * Set up the line discipline objects for a newly allocated tty. Note that the |
793 | * tty structure is not completely set up when this call is made. |
794 | */ |
795 | int tty_ldisc_init(struct tty_struct *tty) |
796 | { |
797 | struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY); |
798 | |
799 | if (IS_ERR(ptr: ld)) |
800 | return PTR_ERR(ptr: ld); |
801 | tty->ldisc = ld; |
802 | return 0; |
803 | } |
804 | |
805 | /** |
806 | * tty_ldisc_deinit - ldisc cleanup for new tty |
807 | * @tty: tty that was allocated recently |
808 | * |
809 | * The tty structure must not be completely set up (tty_ldisc_setup()) when |
810 | * this call is made. |
811 | */ |
812 | void tty_ldisc_deinit(struct tty_struct *tty) |
813 | { |
814 | /* no ldisc_sem, tty is being destroyed */ |
815 | if (tty->ldisc) |
816 | tty_ldisc_put(ld: tty->ldisc); |
817 | tty->ldisc = NULL; |
818 | } |
819 | |