xref: /netbsd-src/sys/fs/ptyfs/ptyfs_subr.c (revision cce00501eeb45e19e7b022f347ae0a3819db9ea5)
1*cce00501Schristos /*	$NetBSD: ptyfs_subr.c,v 1.34 2020/11/27 14:43:57 christos Exp $	*/
2156a03ceSjdolecek 
3156a03ceSjdolecek /*
4156a03ceSjdolecek  * Copyright (c) 1993
5156a03ceSjdolecek  *	The Regents of the University of California.  All rights reserved.
6156a03ceSjdolecek  *
7156a03ceSjdolecek  * This code is derived from software contributed to Berkeley by
8156a03ceSjdolecek  * Jan-Simon Pendry.
9156a03ceSjdolecek  *
10156a03ceSjdolecek  * Redistribution and use in source and binary forms, with or without
11156a03ceSjdolecek  * modification, are permitted provided that the following conditions
12156a03ceSjdolecek  * are met:
13156a03ceSjdolecek  * 1. Redistributions of source code must retain the above copyright
14156a03ceSjdolecek  *    notice, this list of conditions and the following disclaimer.
15156a03ceSjdolecek  * 2. Redistributions in binary form must reproduce the above copyright
16156a03ceSjdolecek  *    notice, this list of conditions and the following disclaimer in the
17156a03ceSjdolecek  *    documentation and/or other materials provided with the distribution.
18156a03ceSjdolecek  * 3. Neither the name of the University nor the names of its contributors
19156a03ceSjdolecek  *    may be used to endorse or promote products derived from this software
20156a03ceSjdolecek  *    without specific prior written permission.
21156a03ceSjdolecek  *
22156a03ceSjdolecek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23156a03ceSjdolecek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24156a03ceSjdolecek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25156a03ceSjdolecek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26156a03ceSjdolecek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27156a03ceSjdolecek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28156a03ceSjdolecek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29156a03ceSjdolecek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30156a03ceSjdolecek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31156a03ceSjdolecek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32156a03ceSjdolecek  * SUCH DAMAGE.
33156a03ceSjdolecek  *
34156a03ceSjdolecek  *	@(#)ptyfs_subr.c	8.6 (Berkeley) 5/14/95
35156a03ceSjdolecek  */
36156a03ceSjdolecek 
37156a03ceSjdolecek /*
38156a03ceSjdolecek  * Copyright (c) 1994 Christopher G. Demetriou.  All rights reserved.
39156a03ceSjdolecek  * Copyright (c) 1993 Jan-Simon Pendry
40156a03ceSjdolecek  *
41156a03ceSjdolecek  * This code is derived from software contributed to Berkeley by
42156a03ceSjdolecek  * Jan-Simon Pendry.
43156a03ceSjdolecek  *
44156a03ceSjdolecek  * Redistribution and use in source and binary forms, with or without
45156a03ceSjdolecek  * modification, are permitted provided that the following conditions
46156a03ceSjdolecek  * are met:
47156a03ceSjdolecek  * 1. Redistributions of source code must retain the above copyright
48156a03ceSjdolecek  *    notice, this list of conditions and the following disclaimer.
49156a03ceSjdolecek  * 2. Redistributions in binary form must reproduce the above copyright
50156a03ceSjdolecek  *    notice, this list of conditions and the following disclaimer in the
51156a03ceSjdolecek  *    documentation and/or other materials provided with the distribution.
52156a03ceSjdolecek  * 3. All advertising materials mentioning features or use of this software
53156a03ceSjdolecek  *    must display the following acknowledgement:
54156a03ceSjdolecek  *	This product includes software developed by the University of
55156a03ceSjdolecek  *	California, Berkeley and its contributors.
56156a03ceSjdolecek  * 4. Neither the name of the University nor the names of its contributors
57156a03ceSjdolecek  *    may be used to endorse or promote products derived from this software
58156a03ceSjdolecek  *    without specific prior written permission.
59156a03ceSjdolecek  *
60156a03ceSjdolecek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61156a03ceSjdolecek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62156a03ceSjdolecek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63156a03ceSjdolecek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64156a03ceSjdolecek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65156a03ceSjdolecek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66156a03ceSjdolecek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67156a03ceSjdolecek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68156a03ceSjdolecek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69156a03ceSjdolecek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70156a03ceSjdolecek  * SUCH DAMAGE.
71156a03ceSjdolecek  *
72156a03ceSjdolecek  *	@(#)procfs_subr.c	8.6 (Berkeley) 5/14/95
73156a03ceSjdolecek  */
74156a03ceSjdolecek 
75156a03ceSjdolecek #include <sys/cdefs.h>
76*cce00501Schristos __KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c,v 1.34 2020/11/27 14:43:57 christos Exp $");
77156a03ceSjdolecek 
78156a03ceSjdolecek #include <sys/param.h>
79156a03ceSjdolecek #include <sys/systm.h>
80156a03ceSjdolecek #include <sys/time.h>
81156a03ceSjdolecek #include <sys/kernel.h>
82156a03ceSjdolecek #include <sys/vnode.h>
83156a03ceSjdolecek #include <sys/stat.h>
84e071d39cSad #include <sys/malloc.h>
85156a03ceSjdolecek #include <sys/file.h>
86156a03ceSjdolecek #include <sys/namei.h>
87156a03ceSjdolecek #include <sys/filedesc.h>
88156a03ceSjdolecek #include <sys/select.h>
89156a03ceSjdolecek #include <sys/tty.h>
90156a03ceSjdolecek #include <sys/pty.h>
91fc9422c9Selad #include <sys/kauth.h>
92744a92f0Sad #include <sys/lwp.h>
93156a03ceSjdolecek 
949d12d591Sjdolecek #include <fs/ptyfs/ptyfs.h>
95156a03ceSjdolecek 
96de81194dSad static kmutex_t ptyfs_hashlock;
97156a03ceSjdolecek 
SLIST_HEAD(ptyfs_hashhead,ptyfsnode)98912cfee7Shannken static SLIST_HEAD(ptyfs_hashhead, ptyfsnode) *ptyfs_node_tbl;
99912cfee7Shannken static u_long ptyfs_node_mask; /* size of hash table - 1 */
100156a03ceSjdolecek 
101156a03ceSjdolecek /*
102912cfee7Shannken  * allocate a ptyfsnode/vnode pair.  the vnode is referenced.
103156a03ceSjdolecek  *
10474758fe5Schristos  * the pty, ptyfs_type, and mount point uniquely
105156a03ceSjdolecek  * identify a ptyfsnode.  the mount point is needed
106156a03ceSjdolecek  * because someone might mount this filesystem
107156a03ceSjdolecek  * twice.
108156a03ceSjdolecek  */
109156a03ceSjdolecek int
1102607f151Shannken ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty)
111156a03ceSjdolecek {
112912cfee7Shannken 	struct ptyfskey key;
113156a03ceSjdolecek 
114912cfee7Shannken 	memset(&key, 0, sizeof(key));
115912cfee7Shannken 	key.ptk_pty = pty;
116912cfee7Shannken 	key.ptk_type = type;
117912cfee7Shannken 	return vcache_get(mp, &key, sizeof(key), vpp);
118156a03ceSjdolecek }
119156a03ceSjdolecek 
120156a03ceSjdolecek /*
121156a03ceSjdolecek  * Initialize ptyfsnode hash table.
122156a03ceSjdolecek  */
123156a03ceSjdolecek void
ptyfs_hashinit(void)124156a03ceSjdolecek ptyfs_hashinit(void)
125156a03ceSjdolecek {
126912cfee7Shannken 
127b041904fShannken 	ptyfs_node_tbl = hashinit(16, HASH_SLIST, true, &ptyfs_node_mask);
128de81194dSad 	mutex_init(&ptyfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
129156a03ceSjdolecek }
130156a03ceSjdolecek 
131156a03ceSjdolecek /*
132156a03ceSjdolecek  * Free ptyfsnode hash table.
133156a03ceSjdolecek  */
134156a03ceSjdolecek void
ptyfs_hashdone(void)135156a03ceSjdolecek ptyfs_hashdone(void)
136156a03ceSjdolecek {
137e071d39cSad 
1383914ae19Shaad 	mutex_destroy(&ptyfs_hashlock);
139b041904fShannken 	hashdone(ptyfs_node_tbl, HASH_SLIST, ptyfs_node_mask);
140156a03ceSjdolecek }
141156a03ceSjdolecek 
142156a03ceSjdolecek /*
143912cfee7Shannken  * Get a ptyfsnode from the hash table, or allocate one.
144156a03ceSjdolecek  */
145156a03ceSjdolecek struct ptyfsnode *
ptyfs_get_node(ptyfstype type,int pty)146912cfee7Shannken ptyfs_get_node(ptyfstype type, int pty)
147156a03ceSjdolecek {
148156a03ceSjdolecek 	struct ptyfs_hashhead *ppp;
149156a03ceSjdolecek 	struct ptyfsnode *pp;
150156a03ceSjdolecek 
151912cfee7Shannken 	ppp = &ptyfs_node_tbl[PTYFS_FILENO(type, pty) & ptyfs_node_mask];
152912cfee7Shannken 
153912cfee7Shannken 	mutex_enter(&ptyfs_hashlock);
154912cfee7Shannken 	SLIST_FOREACH(pp, ppp, ptyfs_hash) {
155156a03ceSjdolecek 		if (pty == pp->ptyfs_pty && pp->ptyfs_type == type) {
156912cfee7Shannken 			mutex_exit(&ptyfs_hashlock);
157156a03ceSjdolecek 			return pp;
158156a03ceSjdolecek 		}
159156a03ceSjdolecek 	}
160912cfee7Shannken 	mutex_exit(&ptyfs_hashlock);
161156a03ceSjdolecek 
1629b87d582Scegger 	pp = malloc(sizeof(struct ptyfsnode), M_TEMP, M_WAITOK);
163156a03ceSjdolecek 	pp->ptyfs_pty = pty;
164156a03ceSjdolecek 	pp->ptyfs_type = type;
165*cce00501Schristos 	pp->ptyfs_fileno = PTYFS_FILENO(type, pty);
1662607f151Shannken 	if (pp->ptyfs_type == PTYFSroot)
1672607f151Shannken 		pp->ptyfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|
1682607f151Shannken 		    S_IROTH|S_IXOTH;
1692607f151Shannken 	else
1702607f151Shannken 		pp->ptyfs_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|
1712607f151Shannken 		    S_IROTH|S_IWOTH;
1722607f151Shannken 
1732607f151Shannken 	pp->ptyfs_uid = pp->ptyfs_gid = 0;
1742607f151Shannken 	pp->ptyfs_status = PTYFS_CHANGE;
1752607f151Shannken 	PTYFS_ITIMES(pp, NULL, NULL, NULL);
1762607f151Shannken 	pp->ptyfs_birthtime = pp->ptyfs_mtime =
1772607f151Shannken 	    pp->ptyfs_atime = pp->ptyfs_ctime;
1782607f151Shannken 	pp->ptyfs_flags = 0;
179912cfee7Shannken 	mutex_enter(&ptyfs_hashlock);
18014b4a4b1Schristos 	/*
18114b4a4b1Schristos 	 * XXX We have minimum race condition when opening master side
18214b4a4b1Schristos 	 * first time, if other threads through other mount points, trying
18314b4a4b1Schristos 	 * opening the same device. As follow we have little chance have
18414b4a4b1Schristos 	 * unused list entries.
18514b4a4b1Schristos 	 */
186912cfee7Shannken 	SLIST_INSERT_HEAD(ppp, pp, ptyfs_hash);
187912cfee7Shannken 	mutex_exit(&ptyfs_hashlock);
188156a03ceSjdolecek 	return pp;
189156a03ceSjdolecek }
190156a03ceSjdolecek 
1912607f151Shannken /*
1922607f151Shannken  * Mark this controlling pty as active.
1932607f151Shannken  */
1942607f151Shannken void
ptyfs_set_active(struct mount * mp,int pty)1952607f151Shannken ptyfs_set_active(struct mount *mp, int pty)
1962607f151Shannken {
1972607f151Shannken 	struct ptyfsmount *pmnt = VFSTOPTY(mp);
1982607f151Shannken 
1992607f151Shannken 	KASSERT(pty >= 0);
2002607f151Shannken 	/* Reallocate map if needed. */
2012607f151Shannken 	if (pty >= pmnt->pmnt_bitmap_size * NBBY) {
2022607f151Shannken 		int osize, nsize;
2032607f151Shannken 		uint8_t *obitmap, *nbitmap;
2042607f151Shannken 
2052607f151Shannken 		nsize = roundup(howmany(pty + 1, NBBY), 64);
2062607f151Shannken 		nbitmap = kmem_alloc(nsize, KM_SLEEP);
2072607f151Shannken 		mutex_enter(&pmnt->pmnt_lock);
2082607f151Shannken 		if (pty < pmnt->pmnt_bitmap_size * NBBY) {
2092607f151Shannken 			mutex_exit(&pmnt->pmnt_lock);
2102607f151Shannken 			kmem_free(nbitmap, nsize);
2112607f151Shannken 		} else {
2122607f151Shannken 			osize = pmnt->pmnt_bitmap_size;
2132607f151Shannken 			obitmap = pmnt->pmnt_bitmap;
2142607f151Shannken 			pmnt->pmnt_bitmap_size = nsize;
2152607f151Shannken 			pmnt->pmnt_bitmap = nbitmap;
2162607f151Shannken 			if (osize > 0)
2172607f151Shannken 				memcpy(pmnt->pmnt_bitmap, obitmap, osize);
2182607f151Shannken 			memset(pmnt->pmnt_bitmap + osize, 0, nsize - osize);
2192607f151Shannken 			mutex_exit(&pmnt->pmnt_lock);
2202607f151Shannken 			if (osize > 0)
2212607f151Shannken 				kmem_free(obitmap, osize);
2222607f151Shannken 		}
2232607f151Shannken 	}
2242607f151Shannken 
2252607f151Shannken 	mutex_enter(&pmnt->pmnt_lock);
2262607f151Shannken 	setbit(pmnt->pmnt_bitmap, pty);
2272607f151Shannken 	mutex_exit(&pmnt->pmnt_lock);
2282607f151Shannken }
2292607f151Shannken 
2302607f151Shannken /*
2312607f151Shannken  * Mark this controlling pty as inactive.
2322607f151Shannken  */
2332607f151Shannken void
ptyfs_clr_active(struct mount * mp,int pty)2342607f151Shannken ptyfs_clr_active(struct mount *mp, int pty)
2352607f151Shannken {
2362607f151Shannken 	struct ptyfsmount *pmnt = VFSTOPTY(mp);
2372607f151Shannken 
2382607f151Shannken 	KASSERT(pty >= 0);
2392607f151Shannken 	mutex_enter(&pmnt->pmnt_lock);
2402607f151Shannken 	if (pty >= 0 && pty < pmnt->pmnt_bitmap_size * NBBY)
2412607f151Shannken 		clrbit(pmnt->pmnt_bitmap, pty);
2422607f151Shannken 	mutex_exit(&pmnt->pmnt_lock);
2432607f151Shannken }
2442607f151Shannken 
2452607f151Shannken /*
2462607f151Shannken  * Lookup the next active controlling pty greater or equal "pty".
2472607f151Shannken  * Return -1 if not found.
2482607f151Shannken  */
2492607f151Shannken int
ptyfs_next_active(struct mount * mp,int pty)2502607f151Shannken ptyfs_next_active(struct mount *mp, int pty)
2512607f151Shannken {
2522607f151Shannken 	struct ptyfsmount *pmnt = VFSTOPTY(mp);
2532607f151Shannken 
2542607f151Shannken 	KASSERT(pty >= 0);
2552607f151Shannken 	mutex_enter(&pmnt->pmnt_lock);
2562607f151Shannken 	while (pty < pmnt->pmnt_bitmap_size * NBBY) {
2572607f151Shannken 		if (isset(pmnt->pmnt_bitmap, pty)) {
2582607f151Shannken 			mutex_exit(&pmnt->pmnt_lock);
2592607f151Shannken 			return pty;
2602607f151Shannken 		}
2612607f151Shannken 		pty++;
2622607f151Shannken 	}
2632607f151Shannken 	mutex_exit(&pmnt->pmnt_lock);
2642607f151Shannken 	return -1;
2652607f151Shannken }
266