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