Home | History | Annotate | Line # | Download | only in ptyfs
      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