xref: /xnu-11215/bsd/kern/tty_dev.c (revision 8d741a5d)
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 	bool free_ptmx_ioctl = true;
263 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, PF_OPEN_S, &driver);
264 	if (pti == NULL) {
265 		return ENXIO;
266 	}
267 	if (!(pti->pt_flags & PF_UNLOCKED)) {
268 		error = EAGAIN;
269 		goto out_free;
270 	}
271 
272 	struct tty *tp = pti->pt_tty;
273 	tty_lock(tp);
274 
275 	if ((tp->t_state & TS_ISOPEN) == 0) {
276 		termioschars(&tp->t_termios);   /* Set up default chars */
277 		tp->t_iflag = TTYDEF_IFLAG;
278 		tp->t_oflag = TTYDEF_OFLAG;
279 		tp->t_lflag = TTYDEF_LFLAG;
280 		tp->t_cflag = TTYDEF_CFLAG;
281 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
282 		ttsetwater(tp);         /* would be done in xxparam() */
283 	} else if ((tp->t_state & TS_XCLUDE) && kauth_cred_issuser(kauth_cred_get())) {
284 		error = EBUSY;
285 		goto out_unlock;
286 	}
287 	if (tp->t_oproc) {                      /* Ctrlr still around. */
288 		(void)(*linesw[tp->t_line].l_modem)(tp, 1);
289 	}
290 	while ((tp->t_state & TS_CARR_ON) == 0) {
291 		if (flag & FNONBLOCK) {
292 			break;
293 		}
294 		error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, __FUNCTION__, 0);
295 		if (error) {
296 			goto out_unlock;
297 		}
298 	}
299 	error = (*linesw[tp->t_line].l_open)(dev, tp);
300 	/* Successful open; mark as open by the replica */
301 
302 	free_ptmx_ioctl = false;
303 	CLR(tp->t_state, TS_IOCTL_NOT_OK);
304 	if (error == 0) {
305 		ptcwakeup(tp, FREAD | FWRITE);
306 	}
307 
308 out_unlock:
309 	tty_unlock(tp);
310 
311 out_free:
312 	if (free_ptmx_ioctl) {
313 		pty_free_ioctl(dev, PF_OPEN_S);
314 	}
315 
316 	return error;
317 }
318 
319 __private_extern__ int
ptsclose(dev_t dev,int flag,__unused int mode,__unused proc_t p)320 ptsclose(dev_t dev, int flag, __unused int mode, __unused proc_t p)
321 {
322 	int err;
323 
324 	/*
325 	 * This is temporary until the VSX conformance tests
326 	 * are fixed.  They are hanging with a deadlock
327 	 * where close() will not complete without t_timeout set
328 	 */
329 #define FIX_VSX_HANG    1
330 #ifdef  FIX_VSX_HANG
331 	int save_timeout;
332 #endif
333 	struct tty_dev_t *driver;
334 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver);
335 	struct tty *tp;
336 
337 	if (pti == NULL) {
338 		return ENXIO;
339 	}
340 
341 	tp = pti->pt_tty;
342 	tty_lock(tp);
343 #ifdef  FIX_VSX_HANG
344 	save_timeout = tp->t_timeout;
345 	tp->t_timeout = 60;
346 #endif
347 	/*
348 	 * Close the line discipline and backing TTY structures.
349 	 */
350 	err = (*linesw[tp->t_line].l_close)(tp, flag);
351 	(void)ttyclose(tp);
352 
353 	/*
354 	 * Flush data and notify any waiters on the primary side of this PTY.
355 	 */
356 	ptsstop(tp, FREAD | FWRITE);
357 #ifdef  FIX_VSX_HANG
358 	tp->t_timeout = save_timeout;
359 #endif
360 	tty_unlock(tp);
361 
362 	if ((flag & IO_REVOKE) == IO_REVOKE && driver->revoke) {
363 		driver->revoke(minor(dev), tp);
364 	}
365 	/* unconditional, just like ttyclose() */
366 	pty_free_ioctl(dev, PF_OPEN_S);
367 
368 	return err;
369 }
370 
371 __private_extern__ int
ptsread(dev_t dev,struct uio * uio,int flag)372 ptsread(dev_t dev, struct uio *uio, int flag)
373 {
374 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL);
375 	struct tty *tp;
376 	int error = 0;
377 	struct uthread *ut;
378 
379 	if (pti == NULL) {
380 		return ENXIO;
381 	}
382 	tp = pti->pt_tty;
383 	tty_lock(tp);
384 
385 	ut = current_uthread();
386 	if (tp->t_oproc) {
387 		error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
388 	}
389 	ptcwakeup(tp, FWRITE);
390 	tty_unlock(tp);
391 	return error;
392 }
393 
394 /*
395  * Write to pseudo-tty.
396  * Wakeups of controlling tty will happen
397  * indirectly, when tty driver calls ptsstart.
398  */
399 __private_extern__ int
ptswrite(dev_t dev,struct uio * uio,int flag)400 ptswrite(dev_t dev, struct uio *uio, int flag)
401 {
402 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL);
403 	struct tty *tp;
404 	int error;
405 
406 	if (pti == NULL) {
407 		return ENXIO;
408 	}
409 	tp = pti->pt_tty;
410 	tty_lock(tp);
411 
412 	if (tp->t_oproc == 0) {
413 		error = EIO;
414 	} else {
415 		error = (*linesw[tp->t_line].l_write)(tp, uio, flag);
416 	}
417 
418 	tty_unlock(tp);
419 
420 	return error;
421 }
422 
423 /*
424  * Start output on pseudo-tty.
425  * Wake up process selecting or sleeping for input from controlling tty.
426  *
427  * t_oproc for this driver; called from within the line discipline
428  *
429  * Locks:	Assumes tp is locked on entry, remains locked on exit
430  */
431 static void
ptsstart(struct tty * tp)432 ptsstart(struct tty *tp)
433 {
434 	struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL);
435 	if (pti == NULL) {
436 		goto out;
437 	}
438 	if (tp->t_state & TS_TTSTOP) {
439 		goto out;
440 	}
441 	if (pti->pt_flags & PF_STOPPED) {
442 		pti->pt_flags &= ~PF_STOPPED;
443 		pti->pt_send = TIOCPKT_START;
444 	}
445 	ptcwakeup(tp, FREAD);
446 out:
447 	return;
448 }
449 
450 static void
ptcwakeup_knote(struct selinfo * sip,long hint)451 ptcwakeup_knote(struct selinfo *sip, long hint)
452 {
453 	if ((sip->si_flags & SI_KNPOSTING) == 0) {
454 		sip->si_flags |= SI_KNPOSTING;
455 		KNOTE(&sip->si_note, hint);
456 		sip->si_flags &= ~SI_KNPOSTING;
457 	}
458 }
459 
460 /*
461  * Locks:	Assumes tty_lock() is held over this call.
462  */
463 static void
ptcwakeup(struct tty * tp,int flag)464 ptcwakeup(struct tty *tp, int flag)
465 {
466 	struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL);
467 	if (pti == NULL) {
468 		return;
469 	}
470 
471 	if (flag & FREAD) {
472 		selwakeup(&pti->pt_selr);
473 		wakeup(TSA_PTC_READ(tp));
474 		ptcwakeup_knote(&pti->pt_selr, 1);
475 	}
476 	if (flag & FWRITE) {
477 		selwakeup(&pti->pt_selw);
478 		wakeup(TSA_PTC_WRITE(tp));
479 		ptcwakeup_knote(&pti->pt_selw, 1);
480 	}
481 }
482 
483 __private_extern__ int
ptcopen(dev_t dev,__unused int flag,__unused int devtype,__unused proc_t p)484 ptcopen(dev_t dev, __unused int flag, __unused int devtype, __unused proc_t p)
485 {
486 	struct tty_dev_t *driver;
487 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, PF_OPEN_M, &driver);
488 	if (pti == NULL) {
489 		return ENXIO;
490 	} else if (pti == (struct ptmx_ioctl*)-1) {
491 		return EREDRIVEOPEN;
492 	}
493 
494 	struct tty *tp = pti->pt_tty;
495 	tty_lock(tp);
496 
497 	/* If primary is open OR replica is still draining, pty is still busy */
498 	if (tp->t_oproc || (tp->t_state & TS_ISOPEN)) {
499 		tty_unlock(tp);
500 		/*
501 		 * If primary is closed, we are the only reference, so we
502 		 * need to clear the primary open bit
503 		 */
504 		if (!tp->t_oproc) {
505 			pty_free_ioctl(dev, PF_OPEN_M);
506 		}
507 		return EBUSY;
508 	}
509 	tp->t_oproc = ptsstart;
510 	CLR(tp->t_state, TS_ZOMBIE);
511 	SET(tp->t_state, TS_IOCTL_NOT_OK);
512 #ifdef sun4c
513 	tp->t_stop = ptsstop;
514 #endif
515 	(void)(*linesw[tp->t_line].l_modem)(tp, 1);
516 	tp->t_lflag &= ~EXTPROC;
517 
518 	if (driver->open_reset) {
519 		pti->pt_flags = PF_UNLOCKED;
520 		pti->pt_send = 0;
521 		pti->pt_ucntl = 0;
522 	}
523 
524 	tty_unlock(tp);
525 	return 0;
526 }
527 
528 __private_extern__ int
ptcclose(dev_t dev,__unused int flags,__unused int fmt,__unused proc_t p)529 ptcclose(dev_t dev, __unused int flags, __unused int fmt, __unused proc_t p)
530 {
531 	struct tty_dev_t *driver;
532 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver);
533 	struct tty *tp;
534 	struct tty *constty = NULL;
535 	struct tty *freetp = NULL;
536 
537 	if (!pti) {
538 		return ENXIO;
539 	}
540 
541 	tp = pti->pt_tty;
542 	tty_lock(tp);
543 
544 	constty = copy_constty();
545 
546 	if (constty == tp) {
547 		freetp = set_constty(NULL);
548 		if (freetp != NULL) {
549 			if (freetp == tp) {
550 				ttyfree_locked(freetp);
551 			} else {
552 				ttyfree(freetp);
553 			}
554 			freetp = NULL;
555 		}
556 
557 
558 
559 		/*
560 		 * Closing current console tty; disable printing of console
561 		 * messages at bottom-level driver.
562 		 */
563 		(*cdevsw[major(tp->t_dev)].d_ioctl)
564 		(tp->t_dev, KMIOCDISABLCONS, NULL, 0, current_proc());
565 	}
566 
567 	if (constty != NULL) {
568 		if (constty == tp) {
569 			ttyfree_locked(constty);
570 		} else {
571 			ttyfree(constty);
572 		}
573 		constty = NULL;
574 	}
575 
576 	/*
577 	 * XXX MDMBUF makes no sense for PTYs, but would inhibit an `l_modem`.
578 	 * CLOCAL makes sense but isn't supported.  Special `l_modem`s that ignore
579 	 * carrier drop make no sense for PTYs but may be in use because other parts
580 	 * of the line discipline make sense for PTYs.  Recover by doing everything
581 	 * that a normal `ttymodem` would have done except for sending SIGHUP.
582 	 */
583 	(void)(*linesw[tp->t_line].l_modem)(tp, 0);
584 	if (tp->t_state & TS_ISOPEN) {
585 		tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
586 		tp->t_state |= TS_ZOMBIE;
587 		ttyflush(tp, FREAD | FWRITE);
588 	}
589 
590 	/*
591 	 * Null out the backing TTY struct's open procedure to prevent starting
592 	 * replicas through `ptsstart`.
593 	 */
594 	tp->t_oproc = NULL;
595 
596 	/*
597 	 * Clear any select or kevent waiters under the lock.
598 	 */
599 	knote(&pti->pt_selr.si_note, NOTE_REVOKE, true);
600 	selthreadclear(&pti->pt_selr);
601 	knote(&pti->pt_selw.si_note, NOTE_REVOKE, true);
602 	selthreadclear(&pti->pt_selw);
603 
604 	tty_unlock(tp);
605 
606 #if CONFIG_MACF
607 	if (driver->mac_notify) {
608 		mac_pty_notify_close(p, tp, dev, NULL);
609 	}
610 #endif
611 	pty_free_ioctl(dev, PF_OPEN_M);
612 
613 	return 0;
614 }
615 
616 __private_extern__ int
ptcread(dev_t dev,struct uio * uio,int flag)617 ptcread(dev_t dev, struct uio *uio, int flag)
618 {
619 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL);
620 	struct tty *tp;
621 	char buf[BUFSIZ];
622 	int error = 0, cc;
623 
624 	if (pti == NULL) {
625 		return ENXIO;
626 	}
627 	tp = pti->pt_tty;
628 	tty_lock(tp);
629 
630 	/*
631 	 * We want to block until the replica
632 	 * is open, and there's something to read;
633 	 * but if we lost the replica or we're NBIO,
634 	 * then return the appropriate error instead.
635 	 */
636 	for (;;) {
637 		if (tp->t_state & TS_ISOPEN) {
638 			if (pti->pt_flags & PF_PKT && pti->pt_send) {
639 				error = ureadc((int)pti->pt_send, uio);
640 				if (error) {
641 					goto out;
642 				}
643 				if (pti->pt_send & TIOCPKT_IOCTL) {
644 #ifdef __LP64__
645 					if (uio->uio_segflg == UIO_USERSPACE32) {
646 						static struct termios32 tio32;
647 						cc = MIN((int)uio_resid(uio), (int)sizeof(tio32));
648 						termios64to32((struct user_termios *)&tp->t_termios,
649 						    (struct termios32 *)&tio32);
650 						uiomove((caddr_t)&tio32, cc, uio);
651 #else
652 					if (uio->uio_segflg == UIO_USERSPACE64) {
653 						static struct user_termios tio64;
654 						cc = MIN((int)uio_resid(uio), (int)sizeof(tio64));
655 						termios32to64((struct termios32 *)&tp->t_termios,
656 						    (struct user_termios *)&tio64);
657 						uiomove((caddr_t)&tio64, cc, uio);
658 #endif
659 					} else {
660 						cc = MIN((int)uio_resid(uio), (int)sizeof(tp->t_termios));
661 						uiomove((caddr_t)&tp->t_termios, cc, uio);
662 					}
663 				}
664 				pti->pt_send = 0;
665 				goto out;
666 			}
667 			if (pti->pt_flags & PF_UCNTL && pti->pt_ucntl) {
668 				error = ureadc((int)pti->pt_ucntl, uio);
669 				if (error) {
670 					goto out;
671 				}
672 				pti->pt_ucntl = 0;
673 				goto out;
674 			}
675 			if (tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) {
676 				break;
677 			}
678 		}
679 		if ((tp->t_state & TS_CONNECTED) == 0) {
680 			goto out;       /* EOF */
681 		}
682 		if (flag & IO_NDELAY) {
683 			error = EWOULDBLOCK;
684 			goto out;
685 		}
686 		error = ttysleep(tp, TSA_PTC_READ(tp), TTIPRI | PCATCH, __FUNCTION__, 0);
687 		if (error) {
688 			goto out;
689 		}
690 	}
691 	if (pti->pt_flags & (PF_PKT | PF_UCNTL)) {
692 		error = ureadc(0, uio);
693 	}
694 	while (uio_resid(uio) > 0 && error == 0) {
695 		cc = q_to_b(&tp->t_outq, (u_char *)buf, MIN((int)uio_resid(uio), BUFSIZ));
696 		if (cc <= 0) {
697 			break;
698 		}
699 		error = uiomove(buf, cc, uio);
700 	}
701 	(*linesw[tp->t_line].l_start)(tp);
702 
703 out:
704 	tty_unlock(tp);
705 
706 	return error;
707 }
708 
709 /*
710  * Line discipline callback
711  *
712  * Locks:	tty_lock() is assumed held on entry and exit.
713  */
714 __private_extern__ int
715 ptsstop(struct tty* tp, int flush)
716 {
717 	struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL);
718 	int flag;
719 
720 	if (pti == NULL) {
721 		return ENXIO;
722 	}
723 
724 	/* note: FLUSHREAD and FLUSHWRITE already ok */
725 	if (flush == 0) {
726 		flush = TIOCPKT_STOP;
727 		pti->pt_flags |= PF_STOPPED;
728 	} else {
729 		pti->pt_flags &= ~PF_STOPPED;
730 	}
731 	pti->pt_send |= flush;
732 	/* change of perspective */
733 	flag = 0;
734 	if (flush & FREAD) {
735 		flag |= FWRITE;
736 	}
737 	if (flush & FWRITE) {
738 		flag |= FREAD;
739 	}
740 	ptcwakeup(tp, flag);
741 	return 0;
742 }
743 
744 __private_extern__ int
745 ptsreset(__unused int uban)
746 {
747 	return 0;
748 }
749 
750 int
751 ptsselect(dev_t dev, int rw, void *wql, proc_t p)
752 {
753 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL);
754 	struct tty *tp;
755 	int retval = 0;
756 
757 	if (pti == NULL) {
758 		return ENXIO;
759 	}
760 	tp = pti->pt_tty;
761 	if (tp == NULL) {
762 		return ENXIO;
763 	}
764 
765 	tty_lock(tp);
766 
767 	switch (rw) {
768 	case FREAD:
769 		if (ISSET(tp->t_state, TS_ZOMBIE)) {
770 			retval = 1;
771 			break;
772 		}
773 
774 		retval = ttnread(tp);
775 		if (retval > 0) {
776 			break;
777 		}
778 
779 		selrecord(p, &tp->t_rsel, wql);
780 		break;
781 	case FWRITE:
782 		if (ISSET(tp->t_state, TS_ZOMBIE)) {
783 			retval = 1;
784 			break;
785 		}
786 
787 		if ((tp->t_outq.c_cc <= tp->t_lowat) &&
788 		    ISSET(tp->t_state, TS_CONNECTED)) {
789 			retval = tp->t_hiwat - tp->t_outq.c_cc;
790 			break;
791 		}
792 
793 		selrecord(p, &tp->t_wsel, wql);
794 		break;
795 	}
796 
797 	tty_unlock(tp);
798 	return retval;
799 }
800 
801 __private_extern__ int
802 ptcselect(dev_t dev, int rw, void *wql, proc_t p)
803 {
804 	struct tty_dev_t *driver;
805 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver);
806 	struct tty *tp;
807 	int retval = 0;
808 
809 	if (pti == NULL) {
810 		return ENXIO;
811 	}
812 	tp = pti->pt_tty;
813 	tty_lock(tp);
814 
815 	if ((tp->t_state & TS_CONNECTED) == 0) {
816 		retval = 1;
817 		goto out;
818 	}
819 	switch (rw) {
820 	case FREAD:
821 		/*
822 		 * Need to block timeouts (ttrstart).
823 		 */
824 		if ((tp->t_state & TS_ISOPEN) &&
825 		    tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) {
826 			retval = (driver->fix_7828447) ? tp->t_outq.c_cc : 1;
827 			break;
828 		}
829 		OS_FALLTHROUGH;
830 
831 	case 0: /* exceptional */
832 		if ((tp->t_state & TS_ISOPEN) &&
833 		    (((pti->pt_flags & PF_PKT) && pti->pt_send) ||
834 		    ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) {
835 			retval = 1;
836 			break;
837 		}
838 		selrecord(p, &pti->pt_selr, wql);
839 		break;
840 
841 
842 	case FWRITE:
843 		if (tp->t_state & TS_ISOPEN) {
844 			retval = (TTYHOG - 2) - (tp->t_rawq.c_cc + tp->t_canq.c_cc);
845 			if (retval > 0) {
846 				retval = (driver->fix_7828447) ? retval : 1;
847 				break;
848 			}
849 			if (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON)) {
850 				retval = 1;
851 				break;
852 			}
853 			retval = 0;
854 		}
855 		selrecord(p, &pti->pt_selw, wql);
856 		break;
857 	}
858 out:
859 	tty_unlock(tp);
860 
861 	return retval;
862 }
863 
864 __private_extern__ int
865 ptcstop(__unused struct tty *tp, __unused int flush)
866 {
867 	return 0;
868 }
869 
870 __private_extern__ int
871 ptcreset(__unused int uban)
872 {
873 	return 0;
874 }
875 
876 __private_extern__ int
877 ptcwrite(dev_t dev, struct uio *uio, int flag)
878 {
879 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, NULL);
880 	struct tty *tp;
881 	u_char *cp = NULL;
882 	int cc = 0;
883 	u_char locbuf[BUFSIZ];
884 	int wcnt = 0;
885 	int error = 0;
886 
887 	if (pti == NULL) {
888 		return ENXIO;
889 	}
890 	tp = pti->pt_tty;
891 	tty_lock(tp);
892 
893 again:
894 	if ((tp->t_state & TS_ISOPEN) == 0) {
895 		goto block;
896 	}
897 	while (uio_resid(uio) > 0 || cc > 0) {
898 		if (cc == 0) {
899 			cc = MIN((int)uio_resid(uio), BUFSIZ);
900 			cp = locbuf;
901 			error = uiomove((caddr_t)cp, cc, uio);
902 			if (error) {
903 				goto out;
904 			}
905 			/* check again for safety */
906 			if ((tp->t_state & TS_ISOPEN) == 0) {
907 				/* adjust for data copied in but not written */
908 				uio_setresid(uio, (uio_resid(uio) + cc));
909 				error = EIO;
910 				goto out;
911 			}
912 		}
913 		while (cc > 0) {
914 			if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
915 			    (tp->t_canq.c_cc > 0 || !(tp->t_lflag & ICANON))) {
916 				wakeup(TSA_HUP_OR_INPUT(tp));
917 				goto block;
918 			}
919 			OS_ANALYZER_SUPPRESS("80961525") (*linesw[tp->t_line].l_rint)(*cp++, tp);
920 			wcnt++;
921 			cc--;
922 		}
923 		cc = 0;
924 	}
925 out:
926 	tty_unlock(tp);
927 
928 	return error;
929 
930 block:
931 	/*
932 	 * Come here to wait for replica to open, for space
933 	 * in outq, or space in rawq, or an empty canq.
934 	 */
935 	if ((tp->t_state & TS_CONNECTED) == 0) {
936 		/* adjust for data copied in but not written */
937 		uio_setresid(uio, (uio_resid(uio) + cc));
938 		error = EIO;
939 		goto out;
940 	}
941 	if (flag & IO_NDELAY) {
942 		/* adjust for data copied in but not written */
943 		uio_setresid(uio, (uio_resid(uio) + cc));
944 		if (wcnt == 0) {
945 			error = EWOULDBLOCK;
946 		}
947 		goto out;
948 	}
949 	error = ttysleep(tp, TSA_PTC_WRITE(tp), TTOPRI | PCATCH, __FUNCTION__, 0);
950 	if (error) {
951 		/* adjust for data copied in but not written */
952 		uio_setresid(uio, (uio_resid(uio) + cc));
953 		goto out;
954 	}
955 	goto again;
956 }
957 
958 /*
959  * ptyioctl: Assumes dev was opened and lock was initilized
960  */
961 __private_extern__ int
962 ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
963 {
964 	struct tty_dev_t *driver;
965 	struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver);
966 	struct tty *tp;
967 	int stop, error = 0;
968 	int allow_ext_ioctl = 1;
969 
970 	if (pti == NULL || pti->pt_tty == NULL) {
971 		return ENXIO;
972 	}
973 
974 	if (cmd == KMIOCDISABLCONS) {
975 		return 0;
976 	}
977 
978 	tp = pti->pt_tty;
979 	tty_lock(tp);
980 
981 	u_char *cc = tp->t_cc;
982 
983 	/*
984 	 * Do not permit extended ioctls on the primary side of the pty unless
985 	 * the replica side has been successfully opened and initialized.
986 	 */
987 	if (major(dev) == driver->primary &&
988 	    driver->fix_7070978 &&
989 	    ISSET(tp->t_state, TS_IOCTL_NOT_OK)) {
990 		allow_ext_ioctl = 0;
991 	}
992 
993 	/*
994 	 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
995 	 * ttywflush(tp) will hang if there are characters in the outq.
996 	 */
997 	if (cmd == TIOCEXT && allow_ext_ioctl) {
998 		/*
999 		 * When the EXTPROC bit is being toggled, we need
1000 		 * to send an TIOCPKT_IOCTL if the packet driver
1001 		 * is turned on.
1002 		 */
1003 		if (*(int *)data) {
1004 			if (pti->pt_flags & PF_PKT) {
1005 				pti->pt_send |= TIOCPKT_IOCTL;
1006 				ptcwakeup(tp, FREAD);
1007 			}
1008 			tp->t_lflag |= EXTPROC;
1009 		} else {
1010 			if ((tp->t_lflag & EXTPROC) &&
1011 			    (pti->pt_flags & PF_PKT)) {
1012 				pti->pt_send |= TIOCPKT_IOCTL;
1013 				ptcwakeup(tp, FREAD);
1014 			}
1015 			tp->t_lflag &= ~EXTPROC;
1016 		}
1017 		goto out;
1018 	} else if (cdevsw[major(dev)].d_open == ptcopen) {
1019 		switch (cmd) {
1020 		case TIOCGPGRP:
1021 			/*
1022 			 * We aviod calling ttioctl on the controller since,
1023 			 * in that case, tp must be the controlling terminal.
1024 			 */
1025 			*(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
1026 			goto out;
1027 
1028 		case TIOCPKT:
1029 			if (*(int *)data) {
1030 				if (pti->pt_flags & PF_UCNTL) {
1031 					error = EINVAL;
1032 					goto out;
1033 				}
1034 				pti->pt_flags |= PF_PKT;
1035 			} else {
1036 				pti->pt_flags &= ~PF_PKT;
1037 			}
1038 			goto out;
1039 
1040 		case TIOCUCNTL:
1041 			if (*(int *)data) {
1042 				if (pti->pt_flags & PF_PKT) {
1043 					error = EINVAL;
1044 					goto out;
1045 				}
1046 				pti->pt_flags |= PF_UCNTL;
1047 			} else {
1048 				pti->pt_flags &= ~PF_UCNTL;
1049 			}
1050 			goto out;
1051 
1052 		case TIOCSETP:
1053 		case TIOCSETN:
1054 		case TIOCSETD:
1055 		case TIOCSETA_32:
1056 		case TIOCSETAW_32:
1057 		case TIOCSETAF_32:
1058 		case TIOCSETA_64:
1059 		case TIOCSETAW_64:
1060 		case TIOCSETAF_64:
1061 			ndflush(&tp->t_outq, tp->t_outq.c_cc);
1062 			break;
1063 
1064 		case TIOCSIG:
1065 			if (*(unsigned int *)data >= NSIG ||
1066 			    *(unsigned int *)data == 0) {
1067 				error = EINVAL;
1068 				goto out;
1069 			}
1070 			if ((tp->t_lflag & NOFLSH) == 0) {
1071 				ttyflush(tp, FREAD | FWRITE);
1072 			}
1073 			if ((*(unsigned int *)data == SIGINFO) &&
1074 			    ((tp->t_lflag & NOKERNINFO) == 0)) {
1075 				ttyinfo_locked(tp);
1076 			}
1077 			/*
1078 			 * SAFE: All callers drop the lock on return and
1079 			 * SAFE: the linesw[] will short circut this call
1080 			 * SAFE: if the ioctl() is eaten before the lower
1081 			 * SAFE: level code gets to see it.
1082 			 */
1083 			tty_pgsignal_locked(tp, *(unsigned int *)data, 1);
1084 			goto out;
1085 
1086 		case TIOCPTYGRANT:      /* grantpt(3) */
1087 			/*
1088 			 * Change the uid of the replica to that of the calling
1089 			 * thread, change the gid of the replica to GID_TTY,
1090 			 * change the mode to 0620 (rw--w----).
1091 			 */
1092 		{
1093 			error = _devfs_setattr(pti->pt_devhandle, 0620, kauth_getuid(), GID_TTY);
1094 			if (major(dev) == driver->primary) {
1095 				if (driver->mac_notify) {
1096 #if CONFIG_MACF
1097 					if (!error) {
1098 						tty_unlock(tp);
1099 						mac_pty_notify_grant(p, tp, dev, NULL);
1100 						tty_lock(tp);
1101 					}
1102 #endif
1103 				} else {
1104 					error = 0;
1105 				}
1106 			}
1107 			goto out;
1108 		}
1109 
1110 		case TIOCPTYGNAME:      /* ptsname(3) */
1111 			/*
1112 			 * Report the name of the replica device in *data
1113 			 * (128 bytes max.).  Use the same template string
1114 			 * used for calling devfs_make_node() to create it.
1115 			 */
1116 			pty_get_name(dev, data, 128);
1117 			error = 0;
1118 			goto out;
1119 
1120 		case TIOCPTYUNLK:       /* unlockpt(3) */
1121 			/*
1122 			 * Unlock the replica device so that it can be opened.
1123 			 */
1124 			if (major(dev) == driver->primary) {
1125 				pti->pt_flags |= PF_UNLOCKED;
1126 			}
1127 			error = 0;
1128 			goto out;
1129 
1130 		case FIONBIO:           /* set/clear non-blocking i/o */
1131 		case FIOASYNC:
1132 			/*
1133 			 * These probably come from sys_fcntl_nocancel().  Nothing specific
1134 			 * to serial devices here, so they should be allowed even if the
1135 			 * replica is closed.  The implementation in ttioctl_locked() is
1136 			 * safe to call in this case.  Bypass the line discipline's l_ioctl
1137 			 * implementation in case it is not.  In practice l_ioctl is
1138 			 * completely unused anyway (existing line disciplines set it to
1139 			 * l_noioctl, and the loadable line discipline mechanism is used
1140 			 * nowhere and not exposed to third parties).
1141 			 */
1142 			error = ttioctl_locked(tp, cmd, data, flag, p);
1143 			goto out;
1144 		}
1145 
1146 		/*
1147 		 * Fail all other calls; pty primaries are not serial devices;
1148 		 * we only pretend they are when the replica side of the pty is
1149 		 * already open.
1150 		 */
1151 		if (!allow_ext_ioctl) {
1152 			error = ENOTTY;
1153 			goto out;
1154 		}
1155 	}
1156 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1157 	if (error == ENOTTY) {
1158 		error = ttioctl_locked(tp, cmd, data, flag, p);
1159 		if (error == ENOTTY) {
1160 			if (pti->pt_flags & PF_UCNTL && (cmd & ~0xff) == UIOCCMD(0)) {
1161 				/* Process the UIOCMD ioctl group */
1162 				if (cmd & 0xff) {
1163 					pti->pt_ucntl = (u_char)cmd;
1164 					ptcwakeup(tp, FREAD);
1165 				}
1166 				error = 0;
1167 				goto out;
1168 			} else if (cmd == TIOCSBRK || cmd == TIOCCBRK) {
1169 				/*
1170 				 * POSIX conformance; rdar://3936338
1171 				 *
1172 				 * Clear ENOTTY in the case of setting or
1173 				 * clearing a break failing because pty's
1174 				 * don't support break like real serial
1175 				 * ports.
1176 				 */
1177 				error = 0;
1178 				goto out;
1179 			}
1180 		}
1181 	}
1182 
1183 	/*
1184 	 * If external processing and packet mode send ioctl packet.
1185 	 */
1186 	if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) {
1187 		switch (cmd) {
1188 		case TIOCSETA_32:
1189 		case TIOCSETAW_32:
1190 		case TIOCSETAF_32:
1191 		case TIOCSETA_64:
1192 		case TIOCSETAW_64:
1193 		case TIOCSETAF_64:
1194 		case TIOCSETP:
1195 		case TIOCSETN:
1196 		case TIOCSETC:
1197 		case TIOCSLTC:
1198 		case TIOCLBIS:
1199 		case TIOCLBIC:
1200 		case TIOCLSET:
1201 			pti->pt_send |= TIOCPKT_IOCTL;
1202 			ptcwakeup(tp, FREAD);
1203 			break;
1204 		default:
1205 			break;
1206 		}
1207 	}
1208 	stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
1209 	    && CCEQ(cc[VSTART], CTRL('q'));
1210 	if (pti->pt_flags & PF_NOSTOP) {
1211 		if (stop) {
1212 			pti->pt_send &= ~TIOCPKT_NOSTOP;
1213 			pti->pt_send |= TIOCPKT_DOSTOP;
1214 			pti->pt_flags &= ~PF_NOSTOP;
1215 			ptcwakeup(tp, FREAD);
1216 		}
1217 	} else {
1218 		if (!stop) {
1219 			pti->pt_send &= ~TIOCPKT_DOSTOP;
1220 			pti->pt_send |= TIOCPKT_NOSTOP;
1221 			pti->pt_flags |= PF_NOSTOP;
1222 			ptcwakeup(tp, FREAD);
1223 		}
1224 	}
1225 out:
1226 	tty_unlock(tp);
1227 
1228 	return error;
1229 }
1230