1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)filedesc.h 8.1 (Berkeley) 6/2/93 32 * $FreeBSD$ 33 */ 34 35 #ifndef _SYS_FILEDESC_H_ 36 #define _SYS_FILEDESC_H_ 37 38 #include <sys/caprights.h> 39 #include <sys/queue.h> 40 #include <sys/event.h> 41 #include <sys/lock.h> 42 #include <sys/priority.h> 43 #include <sys/seq.h> 44 #include <sys/sx.h> 45 46 #include <machine/_limits.h> 47 48 struct filecaps { 49 cap_rights_t fc_rights; /* per-descriptor capability rights */ 50 u_long *fc_ioctls; /* per-descriptor allowed ioctls */ 51 int16_t fc_nioctls; /* fc_ioctls array size */ 52 uint32_t fc_fcntls; /* per-descriptor allowed fcntls */ 53 }; 54 55 struct filedescent { 56 struct file *fde_file; /* file structure for open file */ 57 struct filecaps fde_caps; /* per-descriptor rights */ 58 uint8_t fde_flags; /* per-process open file flags */ 59 seq_t fde_seq; /* keep file and caps in sync */ 60 }; 61 #define fde_rights fde_caps.fc_rights 62 #define fde_fcntls fde_caps.fc_fcntls 63 #define fde_ioctls fde_caps.fc_ioctls 64 #define fde_nioctls fde_caps.fc_nioctls 65 #define fde_change_size (offsetof(struct filedescent, fde_seq)) 66 67 struct fdescenttbl { 68 int fdt_nfiles; /* number of open files allocated */ 69 struct filedescent fdt_ofiles[0]; /* open files */ 70 }; 71 #define fd_seq(fdt, fd) (&(fdt)->fdt_ofiles[(fd)].fde_seq) 72 73 /* 74 * This structure is used for the management of descriptors. It may be 75 * shared by multiple processes. 76 */ 77 #define NDSLOTTYPE u_long 78 79 struct filedesc { 80 struct fdescenttbl *fd_files; /* open files table */ 81 struct vnode *fd_cdir; /* current directory */ 82 struct vnode *fd_rdir; /* root directory */ 83 struct vnode *fd_jdir; /* jail root directory */ 84 NDSLOTTYPE *fd_map; /* bitmap of free fds */ 85 int fd_lastfile; /* high-water mark of fd_ofiles */ 86 int fd_freefile; /* approx. next free file */ 87 u_short fd_cmask; /* mask for file creation */ 88 int fd_refcnt; /* thread reference count */ 89 int fd_holdcnt; /* hold count on structure + mutex */ 90 struct sx fd_sx; /* protects members of this struct */ 91 struct kqlist fd_kqlist; /* list of kqueues on this filedesc */ 92 int fd_holdleaderscount; /* block fdfree() for shared close() */ 93 int fd_holdleaderswakeup; /* fdfree() needs wakeup */ 94 }; 95 96 /* 97 * Structure to keep track of (process leader, struct fildedesc) tuples. 98 * Each process has a pointer to such a structure when detailed tracking 99 * is needed, e.g., when rfork(RFPROC | RFMEM) causes a file descriptor 100 * table to be shared by processes having different "p_leader" pointers 101 * and thus distinct POSIX style locks. 102 * 103 * fdl_refcount and fdl_holdcount are protected by struct filedesc mtx. 104 */ 105 struct filedesc_to_leader { 106 int fdl_refcount; /* references from struct proc */ 107 int fdl_holdcount; /* temporary hold during closef */ 108 int fdl_wakeup; /* fdfree() waits on closef() */ 109 struct proc *fdl_leader; /* owner of POSIX locks */ 110 /* Circular list: */ 111 struct filedesc_to_leader *fdl_prev; 112 struct filedesc_to_leader *fdl_next; 113 }; 114 #define fd_nfiles fd_files->fdt_nfiles 115 #define fd_ofiles fd_files->fdt_ofiles 116 117 /* 118 * Per-process open flags. 119 */ 120 #define UF_EXCLOSE 0x01 /* auto-close on exec */ 121 122 #ifdef _KERNEL 123 124 /* Lock a file descriptor table. */ 125 #define FILEDESC_LOCK_INIT(fdp) sx_init(&(fdp)->fd_sx, "filedesc structure") 126 #define FILEDESC_LOCK_DESTROY(fdp) sx_destroy(&(fdp)->fd_sx) 127 #define FILEDESC_LOCK(fdp) (&(fdp)->fd_sx) 128 #define FILEDESC_XLOCK(fdp) sx_xlock(&(fdp)->fd_sx) 129 #define FILEDESC_XUNLOCK(fdp) sx_xunlock(&(fdp)->fd_sx) 130 #define FILEDESC_SLOCK(fdp) sx_slock(&(fdp)->fd_sx) 131 #define FILEDESC_SUNLOCK(fdp) sx_sunlock(&(fdp)->fd_sx) 132 133 #define FILEDESC_LOCK_ASSERT(fdp) sx_assert(&(fdp)->fd_sx, SX_LOCKED | \ 134 SX_NOTRECURSED) 135 #define FILEDESC_XLOCK_ASSERT(fdp) sx_assert(&(fdp)->fd_sx, SX_XLOCKED | \ 136 SX_NOTRECURSED) 137 #define FILEDESC_UNLOCK_ASSERT(fdp) sx_assert(&(fdp)->fd_sx, SX_UNLOCKED) 138 139 /* Operation types for kern_dup(). */ 140 enum { 141 FDDUP_NORMAL, /* dup() behavior. */ 142 FDDUP_FCNTL, /* fcntl()-style errors. */ 143 FDDUP_FIXED, /* Force fixed allocation. */ 144 FDDUP_MUSTREPLACE, /* Target must exist. */ 145 FDDUP_LASTMODE, 146 }; 147 148 /* Flags for kern_dup(). */ 149 #define FDDUP_FLAG_CLOEXEC 0x1 /* Atomically set UF_EXCLOSE. */ 150 151 /* For backward compatibility. */ 152 #define falloc(td, resultfp, resultfd, flags) \ 153 falloc_caps(td, resultfp, resultfd, flags, NULL) 154 155 struct thread; 156 157 void filecaps_init(struct filecaps *fcaps); 158 bool filecaps_copy(const struct filecaps *src, struct filecaps *dst, 159 bool locked); 160 void filecaps_move(struct filecaps *src, struct filecaps *dst); 161 void filecaps_free(struct filecaps *fcaps); 162 163 int closef(struct file *fp, struct thread *td); 164 int dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode, 165 int openerror, int *indxp); 166 int falloc_caps(struct thread *td, struct file **resultfp, int *resultfd, 167 int flags, struct filecaps *fcaps); 168 int falloc_noinstall(struct thread *td, struct file **resultfp); 169 void _finstall(struct filedesc *fdp, struct file *fp, int fd, int flags, 170 struct filecaps *fcaps); 171 int finstall(struct thread *td, struct file *fp, int *resultfd, int flags, 172 struct filecaps *fcaps); 173 int fdalloc(struct thread *td, int minfd, int *result); 174 int fdallocn(struct thread *td, int minfd, int *fds, int n); 175 int fdcheckstd(struct thread *td); 176 void fdclose(struct thread *td, struct file *fp, int idx); 177 void fdcloseexec(struct thread *td); 178 void fdsetugidsafety(struct thread *td); 179 struct filedesc *fdcopy(struct filedesc *fdp); 180 int fdcopy_remapped(struct filedesc *fdp, const int *fds, size_t nfds, 181 struct filedesc **newfdp); 182 void fdinstall_remapped(struct thread *td, struct filedesc *fdp); 183 void fdunshare(struct thread *td); 184 void fdescfree(struct thread *td); 185 void fdescfree_remapped(struct filedesc *fdp); 186 struct filedesc *fdinit(struct filedesc *fdp, bool prepfiles); 187 struct filedesc *fdshare(struct filedesc *fdp); 188 struct filedesc_to_leader * 189 filedesc_to_leader_alloc(struct filedesc_to_leader *old, 190 struct filedesc *fdp, struct proc *leader); 191 int getvnode(struct thread *td, int fd, cap_rights_t *rightsp, 192 struct file **fpp); 193 void mountcheckdirs(struct vnode *olddp, struct vnode *newdp); 194 195 int fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, 196 struct file **fpp, struct filecaps *havecapsp); 197 int fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, 198 struct file **fpp, struct filecaps *havecapsp); 199 200 /* Return a referenced file from an unlocked descriptor. */ 201 int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, 202 struct file **fpp, seq_t *seqp); 203 204 /* Requires a FILEDESC_{S,X}LOCK held and returns without a ref. */ 205 static __inline struct file * 206 fget_locked(struct filedesc *fdp, int fd) 207 { 208 209 FILEDESC_LOCK_ASSERT(fdp); 210 211 if (__predict_false((u_int)fd >= fdp->fd_nfiles)) 212 return (NULL); 213 214 return (fdp->fd_ofiles[fd].fde_file); 215 } 216 217 static __inline struct filedescent * 218 fdeget_locked(struct filedesc *fdp, int fd) 219 { 220 struct filedescent *fde; 221 222 FILEDESC_LOCK_ASSERT(fdp); 223 224 if (__predict_false((u_int)fd >= fdp->fd_nfiles)) 225 return (NULL); 226 227 fde = &fdp->fd_ofiles[fd]; 228 if (__predict_false(fde->fde_file == NULL)) 229 return (NULL); 230 231 return (fde); 232 } 233 234 #ifdef CAPABILITIES 235 static __inline bool 236 fd_modified(struct filedesc *fdp, int fd, seq_t seq) 237 { 238 239 return (!seq_consistent(fd_seq(fdp->fd_files, fd), seq)); 240 } 241 #endif 242 243 /* cdir/rdir/jdir manipulation functions. */ 244 void pwd_chdir(struct thread *td, struct vnode *vp); 245 int pwd_chroot(struct thread *td, struct vnode *vp); 246 void pwd_ensure_dirs(void); 247 248 #endif /* _KERNEL */ 249 250 #endif /* !_SYS_FILEDESC_H_ */ 251