1 /*
2 * Copyright (c) 1997-2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1982, 1986, 1989, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)tty_pty.c 8.4 (Berkeley) 2/20/95
61 */
62
63 /* Common callbacks for the pseudo-teletype driver (pty/tty)
64 * and cloning pseudo-teletype driver (ptmx/pts).
65 */
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/ioctl.h>
70 #include <sys/proc_internal.h>
71 #include <sys/kauth.h>
72 #include <sys/tty.h>
73 #include <sys/conf.h>
74 #include <sys/file_internal.h>
75 #include <sys/uio_internal.h>
76 #include <sys/kernel.h>
77 #include <sys/vnode.h>
78 #include <sys/vnode_internal.h> /* _devfs_setattr() */
79 #include <sys/stat.h> /* _devfs_setattr() */
80 #include <sys/user.h>
81 #include <sys/signalvar.h>
82 #include <sys/sysctl.h>
83 #include <miscfs/devfs/devfs.h>
84 #include <miscfs/devfs/devfsdefs.h> /* DEVFS_LOCK()/DEVFS_UNLOCK() */
85 #include <dev/kmreg_com.h>
86 #include <machine/cons.h>
87
88 #if CONFIG_MACF
89 #include <security/mac_framework.h>
90 #endif
91
92 #include "tty_dev.h"
93
94 /* XXX belongs in devfs somewhere - LATER */
95 static int _devfs_setattr(void *, unsigned short, uid_t, gid_t);
96
97 /*
98 * Forward declarations
99 */
100 static void ptcwakeup(struct tty *tp, int flag);
101 __XNU_PRIVATE_EXTERN d_open_t ptsopen;
102 __XNU_PRIVATE_EXTERN d_close_t ptsclose;
103 __XNU_PRIVATE_EXTERN d_read_t ptsread;
104 __XNU_PRIVATE_EXTERN d_write_t ptswrite;
105 __XNU_PRIVATE_EXTERN d_ioctl_t ptyioctl; /* common ioctl */
106 __XNU_PRIVATE_EXTERN d_stop_t ptsstop;
107 __XNU_PRIVATE_EXTERN d_reset_t ptsreset;
108 __XNU_PRIVATE_EXTERN d_select_t ptsselect;
109 __XNU_PRIVATE_EXTERN d_open_t ptcopen;
110 __XNU_PRIVATE_EXTERN d_close_t ptcclose;
111 __XNU_PRIVATE_EXTERN d_read_t ptcread;
112 __XNU_PRIVATE_EXTERN d_write_t ptcwrite;
113 __XNU_PRIVATE_EXTERN d_stop_t ptcstop; /* NO-OP */
114 __XNU_PRIVATE_EXTERN d_reset_t ptcreset;
115 __XNU_PRIVATE_EXTERN d_select_t ptcselect;
116
117 /*
118 * XXX Should be devfs function... and use VATTR mechanisms, per
119 * XXX vnode_setattr2(); only we maybe can't really get back to the
120 * XXX vnode here for cloning devices (but it works for *cloned* devices
121 * XXX that are not themselves cloning).
122 *
123 * Returns: 0 Success
124 * namei:???
125 * vnode_setattr:???
126 */
127 static int
_devfs_setattr(void * handle,unsigned short mode,uid_t uid,gid_t gid)128 _devfs_setattr(void * handle, unsigned short mode, uid_t uid, gid_t gid)
129 {
130 devdirent_t *direntp = (devdirent_t *)handle;
131 devnode_t *devnodep;
132 int error = EACCES;
133 vfs_context_t ctx = vfs_context_current();
134 struct vnode_attr va;
135
136 VATTR_INIT(&va);
137 VATTR_SET(&va, va_uid, uid);
138 VATTR_SET(&va, va_gid, gid);
139 VATTR_SET(&va, va_mode, mode & ALLPERMS);
140
141 /*
142 * If the TIOCPTYGRANT loses the race with the clone operation because
143 * this function is not part of devfs, and therefore can't take the
144 * devfs lock to protect the direntp update, then force user space to
145 * redrive the grant request.
146 */
147 if (direntp == NULL || (devnodep = direntp->de_dnp) == NULL) {
148 error = ERESTART;
149 goto out;
150 }
151
152 /*
153 * Only do this if we are operating on device that doesn't clone
154 * each time it's referenced. We perform a lookup on the device
155 * to insure we get the right instance. We can't just use the call
156 * to devfs_dntovn() to get the vp for the operation, because
157 * dn_dvm may not have been initialized.
158 */
159 if (devnodep->dn_clone == NULL) {
160 struct nameidata nd;
161 char name[128];
162
163 snprintf(name, sizeof(name), "/dev/%s", direntp->de_name);
164 NDINIT(&nd, LOOKUP, OP_SETATTR, FOLLOW, UIO_SYSSPACE, CAST_USER_ADDR_T(name), ctx);
165 error = namei(&nd);
166 if (error) {
167 goto out;
168 }
169 error = vnode_setattr(nd.ni_vp, &va, ctx);
170 vnode_put(nd.ni_vp);
171 nameidone(&nd);
172 goto out;
173 }
174
175 out:
176 return error;
177 }
178
179 #define BUFSIZ 100 /* Chunk size iomoved to/from user */
180
181 static struct tty_dev_t *tty_dev_head;
182
183 __private_extern__ void
tty_dev_register(struct tty_dev_t * driver)184 tty_dev_register(struct tty_dev_t *driver)
185 {
186 if (driver) {
187 driver->next = tty_dev_head;
188 tty_dev_head = driver;
189 }
190 }
191
192 /*
193 * Given a minor number, return the corresponding structure for that minor
194 * number. If there isn't one, and the create flag is specified, we create
195 * one if possible.
196 *
197 * Parameters: minor Minor number of ptmx device
198 * open_flag PF_OPEN_M First open of primary
199 * PF_OPEN_S First open of replica
200 * 0 Just want ioctl struct
201 *
202 * Returns: NULL Did not exist/could not create
203 * !NULL structure corresponding minor number
204 *
205 * Locks: tty_lock() on ptmx_ioctl->pt_tty NOT held on entry or exit.
206 */
207
208 static struct tty_dev_t *
pty_get_driver(dev_t dev)209 pty_get_driver(dev_t dev)
210 {
211 int major = major(dev);
212 struct tty_dev_t *driver;
213 for (driver = tty_dev_head; driver != NULL; driver = driver->next) {
214 if ((driver->primary == major || driver->replica == major)) {
215 break;
216 }
217 }
218 return driver;
219 }
220
221 static struct ptmx_ioctl *
pty_get_ioctl(dev_t dev,int open_flag,struct tty_dev_t ** out_driver)222 pty_get_ioctl(dev_t dev, int open_flag, struct tty_dev_t **out_driver)
223 {
224 struct tty_dev_t *driver = pty_get_driver(dev);
225 if (out_driver) {
226 *out_driver = driver;
227 }
228 if (driver && driver->open) {
229 return driver->open(minor(dev), open_flag);
230 }
231 return NULL;
232 }
233
234 /*
235 * Locks: tty_lock() of old_ptmx_ioctl->pt_tty NOT held for this call.
236 */
237 static int
pty_free_ioctl(dev_t dev,int open_flag)238 pty_free_ioctl(dev_t dev, int open_flag)
239 {
240 struct tty_dev_t *driver = pty_get_driver(dev);
241 if (driver && driver->free) {
242 return driver->free(minor(dev), open_flag);
243 }
244 return 0;
245 }
246
247 static int
pty_get_name(dev_t dev,char * buffer,size_t size)248 pty_get_name(dev_t dev, char *buffer, size_t size)
249 {
250 struct tty_dev_t *driver = pty_get_driver(dev);
251 if (driver && driver->name) {
252 return driver->name(minor(dev), buffer, size);
253 }
254 return 0;
255 }
256
257 __private_extern__ int
ptsopen(dev_t dev,int flag,__unused int devtype,__unused struct proc * p)258 ptsopen(dev_t dev, int flag, __unused int devtype, __unused struct proc *p)
259 {
260 int error;
261 struct tty_dev_t *driver;
262 struct ptmx_ioctl *pti = pty_get_ioctl(dev, PF_OPEN_S, &driver);
263 if (pti == NULL) {
264 return ENXIO;
265 }
266 if (!(pti->pt_flags & PF_UNLOCKED)) {
267 return EAGAIN;
268 }
269
270 struct tty *tp = pti->pt_tty;
271 tty_lock(tp);
272
273 if ((tp->t_state & TS_ISOPEN) == 0) {
274 termioschars(&tp->t_termios); /* Set up default chars */
275 tp->t_iflag = TTYDEF_IFLAG;
276 tp->t_oflag = TTYDEF_OFLAG;
277 tp->t_lflag = TTYDEF_LFLAG;
278 tp->t_cflag = TTYDEF_CFLAG;
279 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
280 ttsetwater(tp); /* would be done in xxparam() */
281 } else if ((tp->t_state & TS_XCLUDE) && kauth_cred_issuser(kauth_cred_get())) {
282 error = EBUSY;
283 goto out;
284 }
285 if (tp->t_oproc) { /* Ctrlr still around. */
286 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
287 }
288 while ((tp->t_state & TS_CARR_ON) == 0) {
289 if (flag & FNONBLOCK) {
290 break;
291 }
292 error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, __FUNCTION__, 0);
293 if (error) {
294 goto out;
295 }
296 }
297 error = (*linesw[tp->t_line].l_open)(dev, tp);
298 /* Successful open; mark as open by the replica */
299
300 pti->pt_flags |= PF_OPEN_S;
301 CLR(tp->t_state, TS_IOCTL_NOT_OK);
302 if (error == 0) {
303 ptcwakeup(tp, FREAD | FWRITE);
304 }
305
306 out:
307 tty_unlock(tp);
308 return error;
309 }
310
311 __private_extern__ int
ptsclose(dev_t dev,int flag,__unused int mode,__unused proc_t p)312 ptsclose(dev_t dev, int flag, __unused int mode, __unused proc_t p)
313 {
314 int err;
315
316 /*
317 * This is temporary until the VSX conformance tests
318 * are fixed. They are hanging with a deadlock
319 * where close() will not complete without t_timeout set
320 */
321 #define FIX_VSX_HANG 1
322 #ifdef FIX_VSX_HANG
323 int save_timeout;
324 #endif
325 struct tty_dev_t *driver;
326 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver);
327 struct tty *tp;
328
329 if (pti == NULL) {
330 return ENXIO;
331 }
332
333 tp = pti->pt_tty;
334 tty_lock(tp);
335 #ifdef FIX_VSX_HANG
336 save_timeout = tp->t_timeout;
337 tp->t_timeout = 60;
338 #endif
339 /*
340 * Close the line discipline and backing TTY structures.
341 */
342 err = (*linesw[tp->t_line].l_close)(tp, flag);
343 (void)ttyclose(tp);
344
345 /*
346 * Flush data and notify any waiters on the primary side of this PTY.
347 */
348 ptsstop(tp, FREAD | FWRITE);
349 #ifdef FIX_VSX_HANG
350 tp->t_timeout = save_timeout;
351 #endif
352 tty_unlock(tp);
353
354 if ((flag & IO_REVOKE) == IO_REVOKE && driver->revoke) {
355 driver->revoke(minor(dev), tp);
356 }
357 /* unconditional, just like ttyclose() */
358 pty_free_ioctl(dev, PF_OPEN_S);
359
360 return err;
361 }
362
363 __private_extern__ int
ptsread(dev_t dev,struct uio * uio,int flag)364 ptsread(dev_t dev, struct uio *uio, int flag)
365 {
366 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL);
367 struct tty *tp;
368 int error = 0;
369 struct uthread *ut;
370
371 if (pti == NULL) {
372 return ENXIO;
373 }
374 tp = pti->pt_tty;
375 tty_lock(tp);
376
377 ut = current_uthread();
378 if (tp->t_oproc) {
379 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
380 }
381 ptcwakeup(tp, FWRITE);
382 tty_unlock(tp);
383 return error;
384 }
385
386 /*
387 * Write to pseudo-tty.
388 * Wakeups of controlling tty will happen
389 * indirectly, when tty driver calls ptsstart.
390 */
391 __private_extern__ int
ptswrite(dev_t dev,struct uio * uio,int flag)392 ptswrite(dev_t dev, struct uio *uio, int flag)
393 {
394 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL);
395 struct tty *tp;
396 int error;
397
398 if (pti == NULL) {
399 return ENXIO;
400 }
401 tp = pti->pt_tty;
402 tty_lock(tp);
403
404 if (tp->t_oproc == 0) {
405 error = EIO;
406 } else {
407 error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
408 }
409
410 tty_unlock(tp);
411
412 return error;
413 }
414
415 /*
416 * Start output on pseudo-tty.
417 * Wake up process selecting or sleeping for input from controlling tty.
418 *
419 * t_oproc for this driver; called from within the line discipline
420 *
421 * Locks: Assumes tp is locked on entry, remains locked on exit
422 */
423 static void
ptsstart(struct tty * tp)424 ptsstart(struct tty *tp)
425 {
426 struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL);
427 if (pti == NULL) {
428 goto out;
429 }
430 if (tp->t_state & TS_TTSTOP) {
431 goto out;
432 }
433 if (pti->pt_flags & PF_STOPPED) {
434 pti->pt_flags &= ~PF_STOPPED;
435 pti->pt_send = TIOCPKT_START;
436 }
437 ptcwakeup(tp, FREAD);
438 out:
439 return;
440 }
441
442 static void
ptcwakeup_knote(struct selinfo * sip,long hint)443 ptcwakeup_knote(struct selinfo *sip, long hint)
444 {
445 if ((sip->si_flags & SI_KNPOSTING) == 0) {
446 sip->si_flags |= SI_KNPOSTING;
447 KNOTE(&sip->si_note, hint);
448 sip->si_flags &= ~SI_KNPOSTING;
449 }
450 }
451
452 /*
453 * Locks: Assumes tty_lock() is held over this call.
454 */
455 static void
ptcwakeup(struct tty * tp,int flag)456 ptcwakeup(struct tty *tp, int flag)
457 {
458 struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL);
459 if (pti == NULL) {
460 return;
461 }
462
463 if (flag & FREAD) {
464 selwakeup(&pti->pt_selr);
465 wakeup(TSA_PTC_READ(tp));
466 ptcwakeup_knote(&pti->pt_selr, 1);
467 }
468 if (flag & FWRITE) {
469 selwakeup(&pti->pt_selw);
470 wakeup(TSA_PTC_WRITE(tp));
471 ptcwakeup_knote(&pti->pt_selw, 1);
472 }
473 }
474
475 __private_extern__ int
ptcopen(dev_t dev,__unused int flag,__unused int devtype,__unused proc_t p)476 ptcopen(dev_t dev, __unused int flag, __unused int devtype, __unused proc_t p)
477 {
478 struct tty_dev_t *driver;
479 struct ptmx_ioctl *pti = pty_get_ioctl(dev, PF_OPEN_M, &driver);
480 if (pti == NULL) {
481 return ENXIO;
482 } else if (pti == (struct ptmx_ioctl*)-1) {
483 return EREDRIVEOPEN;
484 }
485
486 struct tty *tp = pti->pt_tty;
487 tty_lock(tp);
488
489 /* If primary is open OR replica is still draining, pty is still busy */
490 if (tp->t_oproc || (tp->t_state & TS_ISOPEN)) {
491 tty_unlock(tp);
492 /*
493 * If primary is closed, we are the only reference, so we
494 * need to clear the primary open bit
495 */
496 if (!tp->t_oproc) {
497 pty_free_ioctl(dev, PF_OPEN_M);
498 }
499 return EBUSY;
500 }
501 tp->t_oproc = ptsstart;
502 CLR(tp->t_state, TS_ZOMBIE);
503 SET(tp->t_state, TS_IOCTL_NOT_OK);
504 #ifdef sun4c
505 tp->t_stop = ptsstop;
506 #endif
507 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
508 tp->t_lflag &= ~EXTPROC;
509
510 if (driver->open_reset) {
511 pti->pt_flags = PF_UNLOCKED;
512 pti->pt_send = 0;
513 pti->pt_ucntl = 0;
514 }
515
516 tty_unlock(tp);
517 return 0;
518 }
519
520 __private_extern__ int
ptcclose(dev_t dev,__unused int flags,__unused int fmt,__unused proc_t p)521 ptcclose(dev_t dev, __unused int flags, __unused int fmt, __unused proc_t p)
522 {
523 struct tty_dev_t *driver;
524 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver);
525 struct tty *tp;
526
527 if (!pti) {
528 return ENXIO;
529 }
530
531 tp = pti->pt_tty;
532 tty_lock(tp);
533
534 if (constty == tp) {
535 constty = NULL;
536
537
538 /*
539 * Closing current console tty; disable printing of console
540 * messages at bottom-level driver.
541 */
542 (*cdevsw[major(tp->t_dev)].d_ioctl)
543 (tp->t_dev, KMIOCDISABLCONS, NULL, 0, current_proc());
544 }
545
546 /*
547 * XXX MDMBUF makes no sense for PTYs, but would inhibit an `l_modem`.
548 * CLOCAL makes sense but isn't supported. Special `l_modem`s that ignore
549 * carrier drop make no sense for PTYs but may be in use because other parts
550 * of the line discipline make sense for PTYs. Recover by doing everything
551 * that a normal `ttymodem` would have done except for sending SIGHUP.
552 */
553 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
554 if (tp->t_state & TS_ISOPEN) {
555 tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
556 tp->t_state |= TS_ZOMBIE;
557 ttyflush(tp, FREAD | FWRITE);
558 }
559
560 /*
561 * Null out the backing TTY struct's open procedure to prevent starting
562 * replicas through `ptsstart`.
563 */
564 tp->t_oproc = NULL;
565
566 /*
567 * Clear any select or kevent waiters under the lock.
568 */
569 knote(&pti->pt_selr.si_note, NOTE_REVOKE, true);
570 selthreadclear(&pti->pt_selr);
571 knote(&pti->pt_selw.si_note, NOTE_REVOKE, true);
572 selthreadclear(&pti->pt_selw);
573
574 tty_unlock(tp);
575
576 pty_free_ioctl(dev, PF_OPEN_M);
577 #if CONFIG_MACF
578 if (driver->mac_notify) {
579 mac_pty_notify_close(p, tp, dev, NULL);
580 }
581 #endif
582
583 return 0;
584 }
585
586 __private_extern__ int
ptcread(dev_t dev,struct uio * uio,int flag)587 ptcread(dev_t dev, struct uio *uio, int flag)
588 {
589 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL);
590 struct tty *tp;
591 char buf[BUFSIZ];
592 int error = 0, cc;
593
594 if (pti == NULL) {
595 return ENXIO;
596 }
597 tp = pti->pt_tty;
598 tty_lock(tp);
599
600 /*
601 * We want to block until the replica
602 * is open, and there's something to read;
603 * but if we lost the replica or we're NBIO,
604 * then return the appropriate error instead.
605 */
606 for (;;) {
607 if (tp->t_state & TS_ISOPEN) {
608 if (pti->pt_flags & PF_PKT && pti->pt_send) {
609 error = ureadc((int)pti->pt_send, uio);
610 if (error) {
611 goto out;
612 }
613 if (pti->pt_send & TIOCPKT_IOCTL) {
614 #ifdef __LP64__
615 if (uio->uio_segflg == UIO_USERSPACE32) {
616 static struct termios32 tio32;
617 cc = MIN((int)uio_resid(uio), (int)sizeof(tio32));
618 termios64to32((struct user_termios *)&tp->t_termios,
619 (struct termios32 *)&tio32);
620 uiomove((caddr_t)&tio32, cc, uio);
621 #else
622 if (uio->uio_segflg == UIO_USERSPACE64) {
623 static struct user_termios tio64;
624 cc = MIN((int)uio_resid(uio), (int)sizeof(tio64));
625 termios32to64((struct termios32 *)&tp->t_termios,
626 (struct user_termios *)&tio64);
627 uiomove((caddr_t)&tio64, cc, uio);
628 #endif
629 } else {
630 cc = MIN((int)uio_resid(uio), (int)sizeof(tp->t_termios));
631 uiomove((caddr_t)&tp->t_termios, cc, uio);
632 }
633 }
634 pti->pt_send = 0;
635 goto out;
636 }
637 if (pti->pt_flags & PF_UCNTL && pti->pt_ucntl) {
638 error = ureadc((int)pti->pt_ucntl, uio);
639 if (error) {
640 goto out;
641 }
642 pti->pt_ucntl = 0;
643 goto out;
644 }
645 if (tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) {
646 break;
647 }
648 }
649 if ((tp->t_state & TS_CONNECTED) == 0) {
650 goto out; /* EOF */
651 }
652 if (flag & IO_NDELAY) {
653 error = EWOULDBLOCK;
654 goto out;
655 }
656 error = ttysleep(tp, TSA_PTC_READ(tp), TTIPRI | PCATCH, __FUNCTION__, 0);
657 if (error) {
658 goto out;
659 }
660 }
661 if (pti->pt_flags & (PF_PKT | PF_UCNTL)) {
662 error = ureadc(0, uio);
663 }
664 while (uio_resid(uio) > 0 && error == 0) {
665 cc = q_to_b(&tp->t_outq, (u_char *)buf, MIN((int)uio_resid(uio), BUFSIZ));
666 if (cc <= 0) {
667 break;
668 }
669 error = uiomove(buf, cc, uio);
670 }
671 (*linesw[tp->t_line].l_start)(tp);
672
673 out:
674 tty_unlock(tp);
675
676 return error;
677 }
678
679 /*
680 * Line discipline callback
681 *
682 * Locks: tty_lock() is assumed held on entry and exit.
683 */
684 __private_extern__ int
685 ptsstop(struct tty* tp, int flush)
686 {
687 struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL);
688 int flag;
689
690 if (pti == NULL) {
691 return ENXIO;
692 }
693
694 /* note: FLUSHREAD and FLUSHWRITE already ok */
695 if (flush == 0) {
696 flush = TIOCPKT_STOP;
697 pti->pt_flags |= PF_STOPPED;
698 } else {
699 pti->pt_flags &= ~PF_STOPPED;
700 }
701 pti->pt_send |= flush;
702 /* change of perspective */
703 flag = 0;
704 if (flush & FREAD) {
705 flag |= FWRITE;
706 }
707 if (flush & FWRITE) {
708 flag |= FREAD;
709 }
710 ptcwakeup(tp, flag);
711 return 0;
712 }
713
714 __private_extern__ int
715 ptsreset(__unused int uban)
716 {
717 return 0;
718 }
719
720 int
721 ptsselect(dev_t dev, int rw, void *wql, proc_t p)
722 {
723 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL);
724 struct tty *tp;
725 int retval = 0;
726
727 if (pti == NULL) {
728 return ENXIO;
729 }
730 tp = pti->pt_tty;
731 if (tp == NULL) {
732 return ENXIO;
733 }
734
735 tty_lock(tp);
736
737 switch (rw) {
738 case FREAD:
739 if (ISSET(tp->t_state, TS_ZOMBIE)) {
740 retval = 1;
741 break;
742 }
743
744 retval = ttnread(tp);
745 if (retval > 0) {
746 break;
747 }
748
749 selrecord(p, &tp->t_rsel, wql);
750 break;
751 case FWRITE:
752 if (ISSET(tp->t_state, TS_ZOMBIE)) {
753 retval = 1;
754 break;
755 }
756
757 if ((tp->t_outq.c_cc <= tp->t_lowat) &&
758 ISSET(tp->t_state, TS_CONNECTED)) {
759 retval = tp->t_hiwat - tp->t_outq.c_cc;
760 break;
761 }
762
763 selrecord(p, &tp->t_wsel, wql);
764 break;
765 }
766
767 tty_unlock(tp);
768 return retval;
769 }
770
771 __private_extern__ int
772 ptcselect(dev_t dev, int rw, void *wql, proc_t p)
773 {
774 struct tty_dev_t *driver;
775 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver);
776 struct tty *tp;
777 int retval = 0;
778
779 if (pti == NULL) {
780 return ENXIO;
781 }
782 tp = pti->pt_tty;
783 tty_lock(tp);
784
785 if ((tp->t_state & TS_CONNECTED) == 0) {
786 retval = 1;
787 goto out;
788 }
789 switch (rw) {
790 case FREAD:
791 /*
792 * Need to block timeouts (ttrstart).
793 */
794 if ((tp->t_state & TS_ISOPEN) &&
795 tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) {
796 retval = (driver->fix_7828447) ? tp->t_outq.c_cc : 1;
797 break;
798 }
799 OS_FALLTHROUGH;
800
801 case 0: /* exceptional */
802 if ((tp->t_state & TS_ISOPEN) &&
803 (((pti->pt_flags & PF_PKT) && pti->pt_send) ||
804 ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) {
805 retval = 1;
806 break;
807 }
808 selrecord(p, &pti->pt_selr, wql);
809 break;
810
811
812 case FWRITE:
813 if (tp->t_state & TS_ISOPEN) {
814 retval = (TTYHOG - 2) - (tp->t_rawq.c_cc + tp->t_canq.c_cc);
815 if (retval > 0) {
816 retval = (driver->fix_7828447) ? retval : 1;
817 break;
818 }
819 if (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON)) {
820 retval = 1;
821 break;
822 }
823 retval = 0;
824 }
825 selrecord(p, &pti->pt_selw, wql);
826 break;
827 }
828 out:
829 tty_unlock(tp);
830
831 return retval;
832 }
833
834 __private_extern__ int
835 ptcstop(__unused struct tty *tp, __unused int flush)
836 {
837 return 0;
838 }
839
840 __private_extern__ int
841 ptcreset(__unused int uban)
842 {
843 return 0;
844 }
845
846 __private_extern__ int
847 ptcwrite(dev_t dev, struct uio *uio, int flag)
848 {
849 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL);
850 struct tty *tp;
851 u_char *cp = NULL;
852 int cc = 0;
853 u_char locbuf[BUFSIZ];
854 int wcnt = 0;
855 int error = 0;
856
857 if (pti == NULL) {
858 return ENXIO;
859 }
860 tp = pti->pt_tty;
861 tty_lock(tp);
862
863 again:
864 if ((tp->t_state & TS_ISOPEN) == 0) {
865 goto block;
866 }
867 while (uio_resid(uio) > 0 || cc > 0) {
868 if (cc == 0) {
869 cc = MIN((int)uio_resid(uio), BUFSIZ);
870 cp = locbuf;
871 error = uiomove((caddr_t)cp, cc, uio);
872 if (error) {
873 goto out;
874 }
875 /* check again for safety */
876 if ((tp->t_state & TS_ISOPEN) == 0) {
877 /* adjust for data copied in but not written */
878 uio_setresid(uio, (uio_resid(uio) + cc));
879 error = EIO;
880 goto out;
881 }
882 }
883 while (cc > 0) {
884 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
885 (tp->t_canq.c_cc > 0 || !(tp->t_lflag & ICANON))) {
886 wakeup(TSA_HUP_OR_INPUT(tp));
887 goto block;
888 }
889 OS_ANALYZER_SUPPRESS("80961525") (*linesw[tp->t_line].l_rint)(*cp++, tp);
890 wcnt++;
891 cc--;
892 }
893 cc = 0;
894 }
895 out:
896 tty_unlock(tp);
897
898 return error;
899
900 block:
901 /*
902 * Come here to wait for replica to open, for space
903 * in outq, or space in rawq, or an empty canq.
904 */
905 if ((tp->t_state & TS_CONNECTED) == 0) {
906 /* adjust for data copied in but not written */
907 uio_setresid(uio, (uio_resid(uio) + cc));
908 error = EIO;
909 goto out;
910 }
911 if (flag & IO_NDELAY) {
912 /* adjust for data copied in but not written */
913 uio_setresid(uio, (uio_resid(uio) + cc));
914 if (wcnt == 0) {
915 error = EWOULDBLOCK;
916 }
917 goto out;
918 }
919 error = ttysleep(tp, TSA_PTC_WRITE(tp), TTOPRI | PCATCH, __FUNCTION__, 0);
920 if (error) {
921 /* adjust for data copied in but not written */
922 uio_setresid(uio, (uio_resid(uio) + cc));
923 goto out;
924 }
925 goto again;
926 }
927
928 /*
929 * ptyioctl: Assumes dev was opened and lock was initilized
930 */
931 __private_extern__ int
932 ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
933 {
934 struct tty_dev_t *driver;
935 struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver);
936 struct tty *tp;
937 int stop, error = 0;
938 int allow_ext_ioctl = 1;
939
940 if (pti == NULL || pti->pt_tty == NULL) {
941 return ENXIO;
942 }
943
944 if (cmd == KMIOCDISABLCONS) {
945 return 0;
946 }
947
948 tp = pti->pt_tty;
949 tty_lock(tp);
950
951 u_char *cc = tp->t_cc;
952
953 /*
954 * Do not permit extended ioctls on the primary side of the pty unless
955 * the replica side has been successfully opened and initialized.
956 */
957 if (major(dev) == driver->primary &&
958 driver->fix_7070978 &&
959 ISSET(tp->t_state, TS_IOCTL_NOT_OK)) {
960 allow_ext_ioctl = 0;
961 }
962
963 /*
964 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
965 * ttywflush(tp) will hang if there are characters in the outq.
966 */
967 if (cmd == TIOCEXT && allow_ext_ioctl) {
968 /*
969 * When the EXTPROC bit is being toggled, we need
970 * to send an TIOCPKT_IOCTL if the packet driver
971 * is turned on.
972 */
973 if (*(int *)data) {
974 if (pti->pt_flags & PF_PKT) {
975 pti->pt_send |= TIOCPKT_IOCTL;
976 ptcwakeup(tp, FREAD);
977 }
978 tp->t_lflag |= EXTPROC;
979 } else {
980 if ((tp->t_lflag & EXTPROC) &&
981 (pti->pt_flags & PF_PKT)) {
982 pti->pt_send |= TIOCPKT_IOCTL;
983 ptcwakeup(tp, FREAD);
984 }
985 tp->t_lflag &= ~EXTPROC;
986 }
987 goto out;
988 } else if (cdevsw[major(dev)].d_open == ptcopen) {
989 switch (cmd) {
990 case TIOCGPGRP:
991 /*
992 * We aviod calling ttioctl on the controller since,
993 * in that case, tp must be the controlling terminal.
994 */
995 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
996 goto out;
997
998 case TIOCPKT:
999 if (*(int *)data) {
1000 if (pti->pt_flags & PF_UCNTL) {
1001 error = EINVAL;
1002 goto out;
1003 }
1004 pti->pt_flags |= PF_PKT;
1005 } else {
1006 pti->pt_flags &= ~PF_PKT;
1007 }
1008 goto out;
1009
1010 case TIOCUCNTL:
1011 if (*(int *)data) {
1012 if (pti->pt_flags & PF_PKT) {
1013 error = EINVAL;
1014 goto out;
1015 }
1016 pti->pt_flags |= PF_UCNTL;
1017 } else {
1018 pti->pt_flags &= ~PF_UCNTL;
1019 }
1020 goto out;
1021
1022 case TIOCSETP:
1023 case TIOCSETN:
1024 case TIOCSETD:
1025 case TIOCSETA_32:
1026 case TIOCSETAW_32:
1027 case TIOCSETAF_32:
1028 case TIOCSETA_64:
1029 case TIOCSETAW_64:
1030 case TIOCSETAF_64:
1031 ndflush(&tp->t_outq, tp->t_outq.c_cc);
1032 break;
1033
1034 case TIOCSIG:
1035 if (*(unsigned int *)data >= NSIG ||
1036 *(unsigned int *)data == 0) {
1037 error = EINVAL;
1038 goto out;
1039 }
1040 if ((tp->t_lflag & NOFLSH) == 0) {
1041 ttyflush(tp, FREAD | FWRITE);
1042 }
1043 if ((*(unsigned int *)data == SIGINFO) &&
1044 ((tp->t_lflag & NOKERNINFO) == 0)) {
1045 ttyinfo_locked(tp);
1046 }
1047 /*
1048 * SAFE: All callers drop the lock on return and
1049 * SAFE: the linesw[] will short circut this call
1050 * SAFE: if the ioctl() is eaten before the lower
1051 * SAFE: level code gets to see it.
1052 */
1053 tty_pgsignal_locked(tp, *(unsigned int *)data, 1);
1054 goto out;
1055
1056 case TIOCPTYGRANT: /* grantpt(3) */
1057 /*
1058 * Change the uid of the replica to that of the calling
1059 * thread, change the gid of the replica to GID_TTY,
1060 * change the mode to 0620 (rw--w----).
1061 */
1062 {
1063 error = _devfs_setattr(pti->pt_devhandle, 0620, kauth_getuid(), GID_TTY);
1064 if (major(dev) == driver->primary) {
1065 if (driver->mac_notify) {
1066 #if CONFIG_MACF
1067 if (!error) {
1068 tty_unlock(tp);
1069 mac_pty_notify_grant(p, tp, dev, NULL);
1070 tty_lock(tp);
1071 }
1072 #endif
1073 } else {
1074 error = 0;
1075 }
1076 }
1077 goto out;
1078 }
1079
1080 case TIOCPTYGNAME: /* ptsname(3) */
1081 /*
1082 * Report the name of the replica device in *data
1083 * (128 bytes max.). Use the same template string
1084 * used for calling devfs_make_node() to create it.
1085 */
1086 pty_get_name(dev, data, 128);
1087 error = 0;
1088 goto out;
1089
1090 case TIOCPTYUNLK: /* unlockpt(3) */
1091 /*
1092 * Unlock the replica device so that it can be opened.
1093 */
1094 if (major(dev) == driver->primary) {
1095 pti->pt_flags |= PF_UNLOCKED;
1096 }
1097 error = 0;
1098 goto out;
1099 }
1100
1101 /*
1102 * Fail all other calls; pty primaries are not serial devices;
1103 * we only pretend they are when the replica side of the pty is
1104 * already open.
1105 */
1106 if (!allow_ext_ioctl) {
1107 error = ENOTTY;
1108 goto out;
1109 }
1110 }
1111 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1112 if (error == ENOTTY) {
1113 error = ttioctl_locked(tp, cmd, data, flag, p);
1114 if (error == ENOTTY) {
1115 if (pti->pt_flags & PF_UCNTL && (cmd & ~0xff) == UIOCCMD(0)) {
1116 /* Process the UIOCMD ioctl group */
1117 if (cmd & 0xff) {
1118 pti->pt_ucntl = (u_char)cmd;
1119 ptcwakeup(tp, FREAD);
1120 }
1121 error = 0;
1122 goto out;
1123 } else if (cmd == TIOCSBRK || cmd == TIOCCBRK) {
1124 /*
1125 * POSIX conformance; rdar://3936338
1126 *
1127 * Clear ENOTTY in the case of setting or
1128 * clearing a break failing because pty's
1129 * don't support break like real serial
1130 * ports.
1131 */
1132 error = 0;
1133 goto out;
1134 }
1135 }
1136 }
1137
1138 /*
1139 * If external processing and packet mode send ioctl packet.
1140 */
1141 if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) {
1142 switch (cmd) {
1143 case TIOCSETA_32:
1144 case TIOCSETAW_32:
1145 case TIOCSETAF_32:
1146 case TIOCSETA_64:
1147 case TIOCSETAW_64:
1148 case TIOCSETAF_64:
1149 case TIOCSETP:
1150 case TIOCSETN:
1151 case TIOCSETC:
1152 case TIOCSLTC:
1153 case TIOCLBIS:
1154 case TIOCLBIC:
1155 case TIOCLSET:
1156 pti->pt_send |= TIOCPKT_IOCTL;
1157 ptcwakeup(tp, FREAD);
1158 break;
1159 default:
1160 break;
1161 }
1162 }
1163 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
1164 && CCEQ(cc[VSTART], CTRL('q'));
1165 if (pti->pt_flags & PF_NOSTOP) {
1166 if (stop) {
1167 pti->pt_send &= ~TIOCPKT_NOSTOP;
1168 pti->pt_send |= TIOCPKT_DOSTOP;
1169 pti->pt_flags &= ~PF_NOSTOP;
1170 ptcwakeup(tp, FREAD);
1171 }
1172 } else {
1173 if (!stop) {
1174 pti->pt_send &= ~TIOCPKT_DOSTOP;
1175 pti->pt_send |= TIOCPKT_NOSTOP;
1176 pti->pt_flags |= PF_NOSTOP;
1177 ptcwakeup(tp, FREAD);
1178 }
1179 }
1180 out:
1181 tty_unlock(tp);
1182
1183 return error;
1184 }
1185