xref: /xnu-8020.140.41/bsd/kern/tty_ptmx.c (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
1 /*
2  * Copyright (c) 1997-2019 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 /*
64  * Pseudo-teletype Driver
65  * (Actually two drivers, requiring two entries in 'cdevsw')
66  */
67 #include "pty.h"                /* XXX */
68 
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/ioctl.h>
72 #include <sys/proc_internal.h>
73 #include <sys/kauth.h>
74 #include <sys/tty.h>
75 #include <sys/conf.h>
76 #include <sys/file_internal.h>
77 #include <sys/uio_internal.h>
78 #include <sys/kernel.h>
79 #include <sys/vnode.h>
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 <libkern/section_keywords.h>
86 
87 #if CONFIG_MACF
88 #include <security/mac_framework.h>
89 #endif
90 
91 #include "tty_dev.h"
92 
93 /*
94  * Forward declarations
95  */
96 int ptmx_init(int n_ptys);
97 static struct ptmx_ioctl *ptmx_get_ioctl(int minor, int open_flag);
98 static int ptmx_free_ioctl(int minor, int open_flag);
99 static int ptmx_get_name(int minor, char *buffer, size_t size);
100 static void ptsd_revoke_knotes(int minor, struct tty *tp);
101 
102 extern  d_open_t        ptsopen;
103 extern  d_close_t       ptsclose;
104 extern  d_read_t        ptsread;
105 extern  d_write_t       ptswrite;
106 extern  d_ioctl_t       ptyioctl;
107 extern  d_stop_t        ptsstop;
108 extern  d_reset_t       ptsreset;
109 extern  d_select_t      ptsselect;
110 
111 extern  d_open_t        ptcopen;
112 extern  d_close_t       ptcclose;
113 extern  d_read_t        ptcread;
114 extern  d_write_t       ptcwrite;
115 extern  d_stop_t        ptcstop;
116 extern  d_reset_t       ptcreset;
117 extern  d_select_t      ptcselect;
118 
119 static int ptmx_major;          /* dynamically assigned major number */
120 static const struct cdevsw ptmx_cdev = {
121 	.d_open       = ptcopen,
122 	.d_close      = ptcclose,
123 	.d_read       = ptcread,
124 	.d_write      = ptcwrite,
125 	.d_ioctl      = ptyioctl,
126 	.d_stop       = ptcstop,
127 	.d_reset      = ptcreset,
128 	.d_ttys       = NULL,
129 	.d_select     = ptcselect,
130 	.d_mmap       = eno_mmap,
131 	.d_strategy   = eno_strat,
132 	.d_reserved_1 = eno_getc,
133 	.d_reserved_2 = eno_putc,
134 	.d_type       = D_TTY
135 };
136 
137 static int ptsd_major;          /* dynamically assigned major number */
138 static const struct cdevsw ptsd_cdev = {
139 	.d_open       = ptsopen,
140 	.d_close      = ptsclose,
141 	.d_read       = ptsread,
142 	.d_write      = ptswrite,
143 	.d_ioctl      = ptyioctl,
144 	.d_stop       = ptsstop,
145 	.d_reset      = ptsreset,
146 	.d_ttys       = NULL,
147 	.d_select     = ptsselect,
148 	.d_mmap       = eno_mmap,
149 	.d_strategy   = eno_strat,
150 	.d_reserved_1 = eno_getc,
151 	.d_reserved_2 = eno_putc,
152 	.d_type       = D_TTY
153 };
154 
155 /*
156  * ptmx == /dev/ptmx
157  * ptsd == /dev/pts[0123456789]{3}
158  */
159 #define PTMX_TEMPLATE   "ptmx"
160 #define PTSD_TEMPLATE   "ttys%03d"
161 
162 /*
163  * System-wide limit on the max number of cloned ptys
164  */
165 #define PTMX_MAX_DEFAULT        511     /* 512 entries */
166 #define PTMX_MAX_HARD           999     /* 1000 entries, due to PTSD_TEMPLATE */
167 
168 static int ptmx_max = PTMX_MAX_DEFAULT; /* default # of clones we allow */
169 
170 /* Range enforcement for the sysctl */
171 static int
sysctl_ptmx_max(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)172 sysctl_ptmx_max(__unused struct sysctl_oid *oidp, __unused void *arg1,
173     __unused int arg2, struct sysctl_req *req)
174 {
175 	int new_value, changed;
176 	int error = sysctl_io_number(req, ptmx_max, sizeof(int), &new_value, &changed);
177 	if (changed) {
178 		if (new_value > 0 && new_value <= PTMX_MAX_HARD) {
179 			ptmx_max = new_value;
180 		} else {
181 			error = EINVAL;
182 		}
183 	}
184 	return error;
185 }
186 
187 SYSCTL_NODE(_kern, KERN_TTY, tty, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "TTY");
188 SYSCTL_PROC(_kern_tty, OID_AUTO, ptmx_max,
189     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
190     &ptmx_max, 0, &sysctl_ptmx_max, "I", "ptmx_max");
191 
192 static int      ptmx_clone(dev_t dev, int minor);
193 
194 static struct tty_dev_t _ptmx_driver;
195 
196 int
ptmx_init(__unused int config_count)197 ptmx_init( __unused int config_count)
198 {
199 	/*
200 	 * We start looking at slot 10, since there are inits that will
201 	 * stomp explicit slots (e.g. vndevice stomps 1) below that.
202 	 */
203 
204 	/* Get a major number for /dev/ptmx */
205 	if ((ptmx_major = cdevsw_add(-15, &ptmx_cdev)) == -1) {
206 		printf("ptmx_init: failed to obtain /dev/ptmx major number\n");
207 		return ENOENT;
208 	}
209 
210 	if (cdevsw_setkqueueok(ptmx_major, &ptmx_cdev, CDEVSW_IS_PTC) == -1) {
211 		panic("Failed to set flags on ptmx cdevsw entry.");
212 	}
213 
214 	/* Get a major number for /dev/pts/nnn */
215 	if ((ptsd_major = cdevsw_add(-15, &ptsd_cdev)) == -1) {
216 		(void)cdevsw_remove(ptmx_major, &ptmx_cdev);
217 		printf("ptmx_init: failed to obtain /dev/ptmx major number\n");
218 		return ENOENT;
219 	}
220 
221 	if (cdevsw_setkqueueok(ptsd_major, &ptsd_cdev, CDEVSW_IS_PTS) == -1) {
222 		panic("Failed to set flags on ptmx cdevsw entry.");
223 	}
224 
225 	/* Create the /dev/ptmx device {<major>,0} */
226 	(void)devfs_make_node_clone(makedev(ptmx_major, 0),
227 	    DEVFS_CHAR, UID_ROOT, GID_TTY, 0666,
228 	    ptmx_clone, PTMX_TEMPLATE);
229 
230 	_ptmx_driver.primary = ptmx_major;
231 	_ptmx_driver.replica = ptsd_major;
232 	_ptmx_driver.fix_7828447 = 1;
233 	_ptmx_driver.fix_7070978 = 1;
234 #if CONFIG_MACF
235 	_ptmx_driver.mac_notify = 1;
236 #endif
237 	_ptmx_driver.open = &ptmx_get_ioctl;
238 	_ptmx_driver.free = &ptmx_free_ioctl;
239 	_ptmx_driver.name = &ptmx_get_name;
240 	_ptmx_driver.revoke = &ptsd_revoke_knotes;
241 	tty_dev_register(&_ptmx_driver);
242 
243 	return 0;
244 }
245 
246 
247 static struct _ptmx_ioctl_state {
248 	struct ptmx_ioctl       **pis_ioctl_list;       /* pointer vector */
249 	int                     pis_total;              /* total slots */
250 	int                     pis_free;               /* free slots */
251 } _state;
252 #define PTMX_GROW_VECTOR        16      /* Grow by this many slots at a time */
253 
254 /*
255  * Given a minor number, return the corresponding structure for that minor
256  * number.  If there isn't one, and the create flag is specified, we create
257  * one if possible.
258  *
259  * Parameters:	minor			Minor number of ptmx device
260  *		open_flag		PF_OPEN_M	First open of primary
261  *					PF_OPEN_S	First open of replica
262  *					0		Just want ioctl struct
263  *
264  * Returns:	NULL			Did not exist/could not create
265  *		!NULL			structure corresponding minor number
266  *
267  * Locks:	tty_lock() on ptmx_ioctl->pt_tty NOT held on entry or exit.
268  */
269 static struct ptmx_ioctl *
ptmx_get_ioctl(int minor,int open_flag)270 ptmx_get_ioctl(int minor, int open_flag)
271 {
272 	struct ptmx_ioctl *ptmx_ioctl = NULL;
273 
274 	if (open_flag & PF_OPEN_M) {
275 		struct ptmx_ioctl *new_ptmx_ioctl;
276 
277 		DEVFS_LOCK();
278 		/*
279 		 * If we are about to allocate more memory, but we have
280 		 * already hit the administrative limit, then fail the
281 		 * operation.
282 		 *
283 		 * Note:	Subtract free from total when making this
284 		 *		check to allow unit increments, rather than
285 		 *		snapping to the nearest PTMX_GROW_VECTOR...
286 		 */
287 		if ((_state.pis_total - _state.pis_free) >= ptmx_max) {
288 			DEVFS_UNLOCK();
289 			return NULL;
290 		}
291 		DEVFS_UNLOCK();
292 
293 		new_ptmx_ioctl = kalloc_type(struct ptmx_ioctl,
294 		    Z_WAITOK | Z_ZERO | Z_NOFAIL);
295 
296 		if ((new_ptmx_ioctl->pt_tty = ttymalloc()) == NULL) {
297 			kfree_type(struct ptmx_ioctl, new_ptmx_ioctl);
298 			return NULL;
299 		}
300 
301 		/*
302 		 * Hold the DEVFS_LOCK() over this whole operation; devfs
303 		 * itself does this over malloc/free as well, so this should
304 		 * be safe to do.  We hold it longer than we want to, but
305 		 * doing so avoids a reallocation race on the minor number.
306 		 */
307 		DEVFS_LOCK();
308 
309 		/*
310 		 * Check again to ensure the limit is not reached after initial check
311 		 * when the lock was dropped momentarily for malloc.
312 		 */
313 		if ((_state.pis_total - _state.pis_free) >= ptmx_max) {
314 			ttyfree(new_ptmx_ioctl->pt_tty);
315 			DEVFS_UNLOCK();
316 			kfree_type(struct ptmx_ioctl, new_ptmx_ioctl);
317 			return NULL;
318 		}
319 
320 		/* Need to allocate a larger vector? */
321 		if (_state.pis_free == 0) {
322 			struct ptmx_ioctl **new_pis_ioctl_list;
323 			struct ptmx_ioctl **old_pis_ioctl_list = NULL;
324 			size_t old_pis_total = 0;
325 
326 			/* Yes. */
327 			new_pis_ioctl_list = kalloc_type(struct ptmx_ioctl *,
328 			    _state.pis_total + PTMX_GROW_VECTOR, Z_WAITOK | Z_ZERO);
329 			if (new_pis_ioctl_list == NULL) {
330 				ttyfree(new_ptmx_ioctl->pt_tty);
331 				DEVFS_UNLOCK();
332 				kfree_type(struct ptmx_ioctl, new_ptmx_ioctl);
333 				return NULL;
334 			}
335 
336 			/* If this is not the first time, copy the old over */
337 			bcopy(_state.pis_ioctl_list, new_pis_ioctl_list, sizeof(struct ptmx_ioctl *) * _state.pis_total);
338 			old_pis_ioctl_list = _state.pis_ioctl_list;
339 			old_pis_total = _state.pis_total;
340 			_state.pis_ioctl_list = new_pis_ioctl_list;
341 			_state.pis_free += PTMX_GROW_VECTOR;
342 			_state.pis_total += PTMX_GROW_VECTOR;
343 			kfree_type(struct ptmx_ioctl *, old_pis_total, old_pis_ioctl_list);
344 		}
345 
346 		/* is minor in range now? */
347 		if (minor < 0 || minor >= _state.pis_total) {
348 			ttyfree(new_ptmx_ioctl->pt_tty);
349 			DEVFS_UNLOCK();
350 			kfree_type(struct ptmx_ioctl, new_ptmx_ioctl);
351 			return NULL;
352 		}
353 
354 		if (_state.pis_ioctl_list[minor] != NULL) {
355 			ttyfree(new_ptmx_ioctl->pt_tty);
356 			DEVFS_UNLOCK();
357 			kfree_type(struct ptmx_ioctl, new_ptmx_ioctl);
358 
359 			/* Special error value so we know to redrive the open, we've been raced */
360 			return (struct ptmx_ioctl*)-1;
361 		}
362 
363 		/* Vector is large enough; grab a new ptmx_ioctl */
364 
365 		/* Now grab a free slot... */
366 		_state.pis_ioctl_list[minor] = new_ptmx_ioctl;
367 
368 		/* reduce free count */
369 		_state.pis_free--;
370 
371 		_state.pis_ioctl_list[minor]->pt_flags |= PF_OPEN_M;
372 		DEVFS_UNLOCK();
373 
374 		/* Create the /dev/ttysXXX device {<major>,XXX} */
375 		_state.pis_ioctl_list[minor]->pt_devhandle = devfs_make_node(
376 			makedev(ptsd_major, minor),
377 			DEVFS_CHAR, UID_ROOT, GID_TTY, 0620,
378 			PTSD_TEMPLATE, minor);
379 		if (_state.pis_ioctl_list[minor]->pt_devhandle == NULL) {
380 			printf("devfs_make_node() call failed for ptmx_get_ioctl()!!!!\n");
381 		}
382 	}
383 
384 	/*
385 	 * Lock is held here to protect race when the 'pis_ioctl_list' array is
386 	 * being reallocated to increase its slots.
387 	 */
388 	DEVFS_LOCK();
389 	if (minor >= 0 && minor < _state.pis_total) {
390 		ptmx_ioctl = _state.pis_ioctl_list[minor];
391 	}
392 	DEVFS_UNLOCK();
393 
394 	return ptmx_ioctl;
395 }
396 
397 /*
398  * Locks:	tty_lock() of old_ptmx_ioctl->pt_tty NOT held for this call.
399  */
400 static int
ptmx_free_ioctl(int minor,int open_flag)401 ptmx_free_ioctl(int minor, int open_flag)
402 {
403 	struct ptmx_ioctl *old_ptmx_ioctl = NULL;
404 
405 	DEVFS_LOCK();
406 
407 	if (minor < 0 || minor >= _state.pis_total) {
408 		DEVFS_UNLOCK();
409 		return -1;
410 	}
411 
412 	_state.pis_ioctl_list[minor]->pt_flags &= ~(open_flag);
413 
414 	/*
415 	 * Was this the last close?  We will recognize it because we only get
416 	 * a notification on the last close of a device, and we will have
417 	 * cleared both the primary and the replica open bits in the flags.
418 	 */
419 	if (!(_state.pis_ioctl_list[minor]->pt_flags & (PF_OPEN_M | PF_OPEN_S))) {
420 		/* Mark as free so it can be reallocated later */
421 		old_ptmx_ioctl = _state.pis_ioctl_list[minor];
422 		_state.pis_ioctl_list[minor] = NULL;
423 		_state.pis_free++;
424 	}
425 	DEVFS_UNLOCK();
426 
427 	/* Free old after dropping lock */
428 	if (old_ptmx_ioctl != NULL) {
429 		/*
430 		 * XXX See <rdar://5348651> and <rdar://4854638>
431 		 *
432 		 * XXX Conditional to be removed when/if tty/pty reference
433 		 * XXX counting and mutex implemented.
434 		 */
435 		if (old_ptmx_ioctl->pt_devhandle != NULL) {
436 			devfs_remove(old_ptmx_ioctl->pt_devhandle);
437 		}
438 		ttyfree(old_ptmx_ioctl->pt_tty);
439 		kfree_type(struct ptmx_ioctl, old_ptmx_ioctl);
440 	}
441 
442 	return 0;     /* Success */
443 }
444 
445 static int
ptmx_get_name(int minor,char * buffer,size_t size)446 ptmx_get_name(int minor, char *buffer, size_t size)
447 {
448 	return snprintf(buffer, size, "/dev/" PTSD_TEMPLATE, minor);
449 }
450 
451 
452 
453 /*
454  * Given the dev entry that's being opened, we clone the device.  This driver
455  * doesn't actually use the dev entry, since we alreaqdy know who we are by
456  * being called from this code.  This routine is a callback registered from
457  * devfs_make_node_clone() in ptmx_init(); it's purpose is to provide a new
458  * minor number, or to return -1, if one can't be provided.
459  *
460  * Parameters:	dev			The device we are cloning from
461  *
462  * Returns:	>= 0			A new minor device number
463  *		-1			Error: ENOMEM ("Can't alloc device")
464  *
465  * NOTE:	Called with DEVFS_LOCK() held
466  */
467 static int
ptmx_clone(__unused dev_t dev,int action)468 ptmx_clone(__unused dev_t dev, int action)
469 {
470 	int i;
471 
472 	if (action == DEVFS_CLONE_ALLOC) {
473 		/* First one */
474 		if (_state.pis_total == 0) {
475 			return 0;
476 		}
477 
478 		/*
479 		 * Note: We can add hinting on free slots, if this linear search
480 		 * ends up being a performance bottleneck...
481 		 */
482 		for (i = 0; i < _state.pis_total; i++) {
483 			if (_state.pis_ioctl_list[i] == NULL) {
484 				break;
485 			}
486 		}
487 
488 		/*
489 		 * XXX We fall off the end here; if we did this twice at the
490 		 * XXX same time, we could return the same minor to two
491 		 * XXX callers; we should probably exand the pointer vector
492 		 * XXX here, but I need more information on the MALLOC/FREE
493 		 * XXX locking to ensure against a deadlock.  Maybe we can
494 		 * XXX just high watermark it at 1/2 of PTMX_GROW_VECTOR?
495 		 * XXX That would require returning &minor as implict return
496 		 * XXX and an error code ("EAGAIN/ERESTART") or 0 as our
497 		 * XXX explicit return.
498 		 */
499 
500 		return i;     /* empty slot or next slot */
501 	}
502 	return -1;
503 }
504 
505 
506 /*
507  * kqueue support.
508  */
509 int ptsd_kqfilter(dev_t dev, struct knote *kn);
510 static void ptsd_kqops_detach(struct knote *);
511 static int ptsd_kqops_event(struct knote *, long);
512 static int ptsd_kqops_touch(struct knote *kn, struct kevent_qos_s *kev);
513 static int ptsd_kqops_process(struct knote *kn, struct kevent_qos_s *kev);
514 
515 SECURITY_READ_ONLY_EARLY(struct filterops) ptsd_kqops = {
516 	.f_isfd = 1,
517 	/* attach is handled by ptsd_kqfilter -- the dev node must be passed in */
518 	.f_detach = ptsd_kqops_detach,
519 	.f_event = ptsd_kqops_event,
520 	.f_touch = ptsd_kqops_touch,
521 	.f_process = ptsd_kqops_process,
522 };
523 
524 /*
525  * In the normal case, by the time the driver_close() routine is called
526  * on the replica, all knotes have been detached.  However in the revoke(2)
527  * case, the driver's close routine is called while there are knotes active
528  * that reference the handlers below.  And we have no obvious means to
529  * reach from the driver out to the kqueue's that reference them to get
530  * them to stop.
531  */
532 
533 static void
ptsd_kqops_detach(struct knote * kn)534 ptsd_kqops_detach(struct knote *kn)
535 {
536 	struct tty *tp = kn->kn_hook;
537 
538 	tty_lock(tp);
539 
540 	/*
541 	 * Only detach knotes from open ttys -- ttyclose detaches all knotes
542 	 * under the lock and unsets TS_ISOPEN.
543 	 */
544 	if (tp->t_state & TS_ISOPEN) {
545 		switch (kn->kn_filter) {
546 		case EVFILT_READ:
547 			KNOTE_DETACH(&tp->t_rsel.si_note, kn);
548 			break;
549 		case EVFILT_WRITE:
550 			KNOTE_DETACH(&tp->t_wsel.si_note, kn);
551 			break;
552 		default:
553 			panic("invalid knote %p detach, filter: %d", kn, kn->kn_filter);
554 			break;
555 		}
556 	}
557 
558 	tty_unlock(tp);
559 	ttyfree(tp);
560 }
561 
562 static int
ptsd_kqops_common(struct knote * kn,struct kevent_qos_s * kev,struct tty * tp)563 ptsd_kqops_common(struct knote *kn, struct kevent_qos_s *kev, struct tty *tp)
564 {
565 	int retval = 0;
566 	int64_t data = 0;
567 
568 	TTY_LOCK_OWNED(tp);
569 
570 	switch (kn->kn_filter) {
571 	case EVFILT_READ:
572 		/*
573 		 * ttnread can change the tty state,
574 		 * hence must be done upfront, before any other check.
575 		 */
576 		data = ttnread(tp);
577 		retval = (data > 0);
578 		break;
579 
580 	case EVFILT_WRITE:
581 		if ((tp->t_outq.c_cc <= tp->t_lowat) &&
582 		    (tp->t_state & TS_CONNECTED)) {
583 			data = tp->t_outq.c_cn - tp->t_outq.c_cc;
584 			retval = 1;
585 		}
586 		break;
587 
588 	default:
589 		panic("ptsd kevent: unexpected filter: %d, kn = %p, tty = %p",
590 		    kn->kn_filter, kn, tp);
591 		break;
592 	}
593 
594 	if (tp->t_state & TS_ZOMBIE) {
595 		kn->kn_flags |= EV_EOF;
596 	}
597 	if (kn->kn_flags & EV_EOF) {
598 		retval = 1;
599 	}
600 	if (retval && kev) {
601 		knote_fill_kevent(kn, kev, data);
602 	}
603 	return retval;
604 }
605 
606 static int
ptsd_kqops_event(struct knote * kn,long hint)607 ptsd_kqops_event(struct knote *kn, long hint)
608 {
609 	struct tty *tp = kn->kn_hook;
610 	int ret;
611 
612 	TTY_LOCK_OWNED(tp);
613 
614 	if (hint & NOTE_REVOKE) {
615 		kn->kn_flags |= EV_EOF | EV_ONESHOT;
616 		ret = 1;
617 	} else {
618 		ret = ptsd_kqops_common(kn, NULL, tp);
619 	}
620 
621 	return ret;
622 }
623 
624 static int
ptsd_kqops_touch(struct knote * kn,struct kevent_qos_s * kev)625 ptsd_kqops_touch(struct knote *kn, struct kevent_qos_s *kev)
626 {
627 	struct tty *tp = kn->kn_hook;
628 	int ret;
629 
630 	tty_lock(tp);
631 
632 	/* accept new kevent state */
633 	kn->kn_sfflags = kev->fflags;
634 	kn->kn_sdata = kev->data;
635 
636 	/* recapture fired state of knote */
637 	ret = ptsd_kqops_common(kn, NULL, tp);
638 
639 	tty_unlock(tp);
640 
641 	return ret;
642 }
643 
644 static int
ptsd_kqops_process(struct knote * kn,struct kevent_qos_s * kev)645 ptsd_kqops_process(struct knote *kn, struct kevent_qos_s *kev)
646 {
647 	struct tty *tp = kn->kn_hook;
648 	int ret;
649 
650 	tty_lock(tp);
651 	ret = ptsd_kqops_common(kn, kev, tp);
652 	tty_unlock(tp);
653 
654 	return ret;
655 }
656 
657 int
ptsd_kqfilter(dev_t dev,struct knote * kn)658 ptsd_kqfilter(dev_t dev, struct knote *kn)
659 {
660 	struct tty *tp = NULL;
661 	struct ptmx_ioctl *pti = NULL;
662 	int ret;
663 
664 	/* make sure we're talking about the right device type */
665 	if (cdevsw[major(dev)].d_open != ptsopen) {
666 		knote_set_error(kn, ENODEV);
667 		return 0;
668 	}
669 
670 	if ((pti = ptmx_get_ioctl(minor(dev), 0)) == NULL) {
671 		knote_set_error(kn, ENXIO);
672 		return 0;
673 	}
674 
675 	tp = pti->pt_tty;
676 	tty_lock(tp);
677 
678 	assert(tp->t_state & TS_ISOPEN);
679 
680 	kn->kn_filtid = EVFILTID_PTSD;
681 	/* the tty will be freed when detaching the knote */
682 	ttyhold(tp);
683 	kn->kn_hook = tp;
684 
685 	switch (kn->kn_filter) {
686 	case EVFILT_READ:
687 		KNOTE_ATTACH(&tp->t_rsel.si_note, kn);
688 		break;
689 	case EVFILT_WRITE:
690 		KNOTE_ATTACH(&tp->t_wsel.si_note, kn);
691 		break;
692 	default:
693 		panic("ptsd kevent: unexpected filter: %d, kn = %p, tty = %p",
694 		    kn->kn_filter, kn, tp);
695 		break;
696 	}
697 
698 	/* capture current event state */
699 	ret = ptsd_kqops_common(kn, NULL, tp);
700 
701 	tty_unlock(tp);
702 
703 	return ret;
704 }
705 
706 /*
707  * Support for revoke(2).
708  */
709 static void
ptsd_revoke_knotes(__unused int minor,struct tty * tp)710 ptsd_revoke_knotes(__unused int minor, struct tty *tp)
711 {
712 	tty_lock(tp);
713 
714 	ttwakeup(tp);
715 	assert((tp->t_rsel.si_flags & SI_KNPOSTING) == 0);
716 	KNOTE(&tp->t_rsel.si_note, NOTE_REVOKE);
717 
718 	ttwwakeup(tp);
719 	assert((tp->t_wsel.si_flags & SI_KNPOSTING) == 0);
720 	KNOTE(&tp->t_wsel.si_note, NOTE_REVOKE);
721 
722 	tty_unlock(tp);
723 }
724 
725 /*
726  * kevent filter routines for the master side of a pty, a ptmx.
727  *
728  * Stuff the ptmx_ioctl structure into the hook for ptmx knotes.  Use the
729  * embedded tty's lock for synchronization.
730  */
731 
732 int ptmx_kqfilter(dev_t dev, struct knote *kn);
733 static void ptmx_kqops_detach(struct knote *);
734 static int ptmx_kqops_event(struct knote *, long);
735 static int ptmx_kqops_touch(struct knote *kn, struct kevent_qos_s *kev);
736 static int ptmx_kqops_process(struct knote *kn, struct kevent_qos_s *kev);
737 static int ptmx_kqops_common(struct knote *kn, struct kevent_qos_s *kev,
738     struct ptmx_ioctl *pti, struct tty *tp);
739 
740 SECURITY_READ_ONLY_EARLY(struct filterops) ptmx_kqops = {
741 	.f_isfd = 1,
742 	/* attach is handled by ptmx_kqfilter -- the dev node must be passed in */
743 	.f_detach = ptmx_kqops_detach,
744 	.f_event = ptmx_kqops_event,
745 	.f_touch = ptmx_kqops_touch,
746 	.f_process = ptmx_kqops_process,
747 };
748 
749 static struct ptmx_ioctl *
ptmx_knote_ioctl(struct knote * kn)750 ptmx_knote_ioctl(struct knote *kn)
751 {
752 	return (struct ptmx_ioctl *)kn->kn_hook;
753 }
754 
755 static struct tty *
ptmx_knote_tty(struct knote * kn)756 ptmx_knote_tty(struct knote *kn)
757 {
758 	return ptmx_knote_ioctl(kn)->pt_tty;
759 }
760 
761 int
ptmx_kqfilter(dev_t dev,struct knote * kn)762 ptmx_kqfilter(dev_t dev, struct knote *kn)
763 {
764 	struct tty *tp = NULL;
765 	struct ptmx_ioctl *pti = NULL;
766 	int ret;
767 
768 	/* make sure we're talking about the right device type */
769 	if (cdevsw[major(dev)].d_open != ptcopen) {
770 		knote_set_error(kn, ENODEV);
771 		return 0;
772 	}
773 
774 	if ((pti = ptmx_get_ioctl(minor(dev), 0)) == NULL) {
775 		knote_set_error(kn, ENXIO);
776 		return 0;
777 	}
778 
779 	tp = pti->pt_tty;
780 	tty_lock(tp);
781 
782 	kn->kn_filtid = EVFILTID_PTMX;
783 	/* the tty will be freed when detaching the knote */
784 	ttyhold(tp);
785 	kn->kn_hook = pti;
786 
787 	/*
788 	 * Attach to the ptmx's selinfo structures.  This is the major difference
789 	 * to the ptsd filtops, which use the selinfo structures in the tty
790 	 * structure.
791 	 */
792 	switch (kn->kn_filter) {
793 	case EVFILT_READ:
794 		KNOTE_ATTACH(&pti->pt_selr.si_note, kn);
795 		break;
796 	case EVFILT_WRITE:
797 		KNOTE_ATTACH(&pti->pt_selw.si_note, kn);
798 		break;
799 	default:
800 		panic("ptmx kevent: unexpected filter: %d, kn = %p, tty = %p",
801 		    kn->kn_filter, kn, tp);
802 		break;
803 	}
804 
805 	/* capture current event state */
806 	ret = ptmx_kqops_common(kn, NULL, pti, tp);
807 
808 	tty_unlock(tp);
809 
810 	return ret;
811 }
812 
813 static void
ptmx_kqops_detach(struct knote * kn)814 ptmx_kqops_detach(struct knote *kn)
815 {
816 	struct ptmx_ioctl *pti = kn->kn_hook;
817 	struct tty *tp = pti->pt_tty;
818 
819 	tty_lock(tp);
820 
821 	switch (kn->kn_filter) {
822 	case EVFILT_READ:
823 		KNOTE_DETACH(&pti->pt_selr.si_note, kn);
824 		break;
825 	case EVFILT_WRITE:
826 		KNOTE_DETACH(&pti->pt_selw.si_note, kn);
827 		break;
828 	default:
829 		panic("invalid knote %p detach, filter: %d", kn, kn->kn_filter);
830 		break;
831 	}
832 
833 	tty_unlock(tp);
834 	ttyfree(tp);
835 }
836 
837 static int
ptmx_kqops_common(struct knote * kn,struct kevent_qos_s * kev,struct ptmx_ioctl * pti,struct tty * tp)838 ptmx_kqops_common(struct knote *kn, struct kevent_qos_s *kev,
839     struct ptmx_ioctl *pti, struct tty *tp)
840 {
841 	int retval = 0;
842 	int64_t data = 0;
843 
844 	TTY_LOCK_OWNED(tp);
845 
846 	switch (kn->kn_filter) {
847 	case EVFILT_READ:
848 		/* there's data on the TTY and it's not stopped */
849 		if (tp->t_outq.c_cc && !(tp->t_state & TS_TTSTOP)) {
850 			data = tp->t_outq.c_cc;
851 			retval = data > 0;
852 		} else if (((pti->pt_flags & PF_PKT) && pti->pt_send) ||
853 		    ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) {
854 			retval = 1;
855 		}
856 		break;
857 
858 	case EVFILT_WRITE:
859 		retval = (TTYHOG - 2) - (tp->t_rawq.c_cc + tp->t_canq.c_cc);
860 		if (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON)) {
861 			retval = 1;
862 		}
863 		if (retval < 0) {
864 			retval = 0;
865 		}
866 		break;
867 
868 	default:
869 		panic("ptmx kevent: unexpected filter: %d, kn = %p, tty = %p",
870 		    kn->kn_filter, kn, tp);
871 		break;
872 	}
873 
874 	/* disconnects should force a wakeup (EOF) */
875 	if (!(tp->t_state & TS_CONNECTED) || (tp->t_state & TS_ZOMBIE)) {
876 		kn->kn_flags |= EV_EOF;
877 	}
878 	if (kn->kn_flags & EV_EOF) {
879 		retval = 1;
880 	}
881 	if (retval && kev) {
882 		knote_fill_kevent(kn, kev, data);
883 	}
884 	return retval;
885 }
886 
887 static int
ptmx_kqops_event(struct knote * kn,long hint)888 ptmx_kqops_event(struct knote *kn, long hint)
889 {
890 	struct ptmx_ioctl *pti = ptmx_knote_ioctl(kn);
891 	struct tty *tp = ptmx_knote_tty(kn);
892 	int ret;
893 
894 	TTY_LOCK_OWNED(tp);
895 
896 	if (hint & NOTE_REVOKE) {
897 		kn->kn_flags |= EV_EOF | EV_ONESHOT;
898 		ret = 1;
899 	} else {
900 		ret = ptmx_kqops_common(kn, NULL, pti, tp);
901 	}
902 
903 	return ret;
904 }
905 
906 static int
ptmx_kqops_touch(struct knote * kn,struct kevent_qos_s * kev)907 ptmx_kqops_touch(struct knote *kn, struct kevent_qos_s *kev)
908 {
909 	struct ptmx_ioctl *pti = ptmx_knote_ioctl(kn);
910 	struct tty *tp = ptmx_knote_tty(kn);
911 	int ret;
912 
913 	tty_lock(tp);
914 
915 	/* accept new kevent state */
916 	kn->kn_sfflags = kev->fflags;
917 	kn->kn_sdata = kev->data;
918 
919 	/* recapture fired state of knote */
920 	ret = ptmx_kqops_common(kn, NULL, pti, tp);
921 
922 	tty_unlock(tp);
923 
924 	return ret;
925 }
926 
927 static int
ptmx_kqops_process(struct knote * kn,struct kevent_qos_s * kev)928 ptmx_kqops_process(struct knote *kn, struct kevent_qos_s *kev)
929 {
930 	struct ptmx_ioctl *pti = ptmx_knote_ioctl(kn);
931 	struct tty *tp = ptmx_knote_tty(kn);
932 	int ret;
933 
934 	tty_lock(tp);
935 	ret = ptmx_kqops_common(kn, kev, pti, tp);
936 	tty_unlock(tp);
937 
938 	return ret;
939 }
940