1 /* $NetBSD: ptyfs_subr.c,v 1.34 2020/11/27 14:43:57 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Jan-Simon Pendry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)ptyfs_subr.c 8.6 (Berkeley) 5/14/95 35 */ 36 37 /* 38 * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved. 39 * Copyright (c) 1993 Jan-Simon Pendry 40 * 41 * This code is derived from software contributed to Berkeley by 42 * Jan-Simon Pendry. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by the University of 55 * California, Berkeley and its contributors. 56 * 4. Neither the name of the University nor the names of its contributors 57 * may be used to endorse or promote products derived from this software 58 * without specific prior written permission. 59 * 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 * SUCH DAMAGE. 71 * 72 * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95 73 */ 74 75 #include <sys/cdefs.h> 76 __KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c,v 1.34 2020/11/27 14:43:57 christos Exp $"); 77 78 #include <sys/param.h> 79 #include <sys/systm.h> 80 #include <sys/time.h> 81 #include <sys/kernel.h> 82 #include <sys/vnode.h> 83 #include <sys/stat.h> 84 #include <sys/malloc.h> 85 #include <sys/file.h> 86 #include <sys/namei.h> 87 #include <sys/filedesc.h> 88 #include <sys/select.h> 89 #include <sys/tty.h> 90 #include <sys/pty.h> 91 #include <sys/kauth.h> 92 #include <sys/lwp.h> 93 94 #include <fs/ptyfs/ptyfs.h> 95 96 static kmutex_t ptyfs_hashlock; 97 98 static SLIST_HEAD(ptyfs_hashhead, ptyfsnode) *ptyfs_node_tbl; 99 static u_long ptyfs_node_mask; /* size of hash table - 1 */ 100 101 /* 102 * allocate a ptyfsnode/vnode pair. the vnode is referenced. 103 * 104 * the pty, ptyfs_type, and mount point uniquely 105 * identify a ptyfsnode. the mount point is needed 106 * because someone might mount this filesystem 107 * twice. 108 */ 109 int 110 ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty) 111 { 112 struct ptyfskey key; 113 114 memset(&key, 0, sizeof(key)); 115 key.ptk_pty = pty; 116 key.ptk_type = type; 117 return vcache_get(mp, &key, sizeof(key), vpp); 118 } 119 120 /* 121 * Initialize ptyfsnode hash table. 122 */ 123 void 124 ptyfs_hashinit(void) 125 { 126 127 ptyfs_node_tbl = hashinit(16, HASH_SLIST, true, &ptyfs_node_mask); 128 mutex_init(&ptyfs_hashlock, MUTEX_DEFAULT, IPL_NONE); 129 } 130 131 /* 132 * Free ptyfsnode hash table. 133 */ 134 void 135 ptyfs_hashdone(void) 136 { 137 138 mutex_destroy(&ptyfs_hashlock); 139 hashdone(ptyfs_node_tbl, HASH_SLIST, ptyfs_node_mask); 140 } 141 142 /* 143 * Get a ptyfsnode from the hash table, or allocate one. 144 */ 145 struct ptyfsnode * 146 ptyfs_get_node(ptyfstype type, int pty) 147 { 148 struct ptyfs_hashhead *ppp; 149 struct ptyfsnode *pp; 150 151 ppp = &ptyfs_node_tbl[PTYFS_FILENO(type, pty) & ptyfs_node_mask]; 152 153 mutex_enter(&ptyfs_hashlock); 154 SLIST_FOREACH(pp, ppp, ptyfs_hash) { 155 if (pty == pp->ptyfs_pty && pp->ptyfs_type == type) { 156 mutex_exit(&ptyfs_hashlock); 157 return pp; 158 } 159 } 160 mutex_exit(&ptyfs_hashlock); 161 162 pp = malloc(sizeof(struct ptyfsnode), M_TEMP, M_WAITOK); 163 pp->ptyfs_pty = pty; 164 pp->ptyfs_type = type; 165 pp->ptyfs_fileno = PTYFS_FILENO(type, pty); 166 if (pp->ptyfs_type == PTYFSroot) 167 pp->ptyfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP| 168 S_IROTH|S_IXOTH; 169 else 170 pp->ptyfs_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| 171 S_IROTH|S_IWOTH; 172 173 pp->ptyfs_uid = pp->ptyfs_gid = 0; 174 pp->ptyfs_status = PTYFS_CHANGE; 175 PTYFS_ITIMES(pp, NULL, NULL, NULL); 176 pp->ptyfs_birthtime = pp->ptyfs_mtime = 177 pp->ptyfs_atime = pp->ptyfs_ctime; 178 pp->ptyfs_flags = 0; 179 mutex_enter(&ptyfs_hashlock); 180 /* 181 * XXX We have minimum race condition when opening master side 182 * first time, if other threads through other mount points, trying 183 * opening the same device. As follow we have little chance have 184 * unused list entries. 185 */ 186 SLIST_INSERT_HEAD(ppp, pp, ptyfs_hash); 187 mutex_exit(&ptyfs_hashlock); 188 return pp; 189 } 190 191 /* 192 * Mark this controlling pty as active. 193 */ 194 void 195 ptyfs_set_active(struct mount *mp, int pty) 196 { 197 struct ptyfsmount *pmnt = VFSTOPTY(mp); 198 199 KASSERT(pty >= 0); 200 /* Reallocate map if needed. */ 201 if (pty >= pmnt->pmnt_bitmap_size * NBBY) { 202 int osize, nsize; 203 uint8_t *obitmap, *nbitmap; 204 205 nsize = roundup(howmany(pty + 1, NBBY), 64); 206 nbitmap = kmem_alloc(nsize, KM_SLEEP); 207 mutex_enter(&pmnt->pmnt_lock); 208 if (pty < pmnt->pmnt_bitmap_size * NBBY) { 209 mutex_exit(&pmnt->pmnt_lock); 210 kmem_free(nbitmap, nsize); 211 } else { 212 osize = pmnt->pmnt_bitmap_size; 213 obitmap = pmnt->pmnt_bitmap; 214 pmnt->pmnt_bitmap_size = nsize; 215 pmnt->pmnt_bitmap = nbitmap; 216 if (osize > 0) 217 memcpy(pmnt->pmnt_bitmap, obitmap, osize); 218 memset(pmnt->pmnt_bitmap + osize, 0, nsize - osize); 219 mutex_exit(&pmnt->pmnt_lock); 220 if (osize > 0) 221 kmem_free(obitmap, osize); 222 } 223 } 224 225 mutex_enter(&pmnt->pmnt_lock); 226 setbit(pmnt->pmnt_bitmap, pty); 227 mutex_exit(&pmnt->pmnt_lock); 228 } 229 230 /* 231 * Mark this controlling pty as inactive. 232 */ 233 void 234 ptyfs_clr_active(struct mount *mp, int pty) 235 { 236 struct ptyfsmount *pmnt = VFSTOPTY(mp); 237 238 KASSERT(pty >= 0); 239 mutex_enter(&pmnt->pmnt_lock); 240 if (pty >= 0 && pty < pmnt->pmnt_bitmap_size * NBBY) 241 clrbit(pmnt->pmnt_bitmap, pty); 242 mutex_exit(&pmnt->pmnt_lock); 243 } 244 245 /* 246 * Lookup the next active controlling pty greater or equal "pty". 247 * Return -1 if not found. 248 */ 249 int 250 ptyfs_next_active(struct mount *mp, int pty) 251 { 252 struct ptyfsmount *pmnt = VFSTOPTY(mp); 253 254 KASSERT(pty >= 0); 255 mutex_enter(&pmnt->pmnt_lock); 256 while (pty < pmnt->pmnt_bitmap_size * NBBY) { 257 if (isset(pmnt->pmnt_bitmap, pty)) { 258 mutex_exit(&pmnt->pmnt_lock); 259 return pty; 260 } 261 pty++; 262 } 263 mutex_exit(&pmnt->pmnt_lock); 264 return -1; 265 } 266