Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 | /* * Copyright (c) 2000-2012 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */ /* * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)filedesc.h 8.1 (Berkeley) 6/2/93 */ #ifndef _SYS_FILEDESC_H_ #define _SYS_FILEDESC_H_ #include <sys/appleapiopts.h> /* * This structure is used for the management of descriptors. It may be * shared by multiple processes. * * A process is initially started out with NDFILE descriptors [XXXstored within * this structureXXX], selected to be enough for typical applications based on * the historical limit of 20 open files (and the usage of descriptors by * shells). If these descriptors are exhausted, a larger descriptor table * may be allocated, up to a process' resource limit; [XXXthe internal arrays * are then unusedXXX]. The initial expansion is set to NDEXTENT; each time * it runs out, it is doubled until the resource limit is reached. NDEXTENT * should be selected to be the biggest multiple of OFILESIZE (see below) * that will fit in a power-of-two sized piece of memory. */ #define NDFILE 25 /* 125 bytes */ #define NDEXTENT 50 /* 250 bytes in 256-byte alloc. */ #ifdef XNU_KERNEL_PRIVATE #include <sys/kernel_types.h> #include <kern/locks.h> struct klist; struct kqwllist; __options_decl(filedesc_flags_t, uint8_t, { /* * process was chrooted... keep track even * if we're force unmounted and unable to * take a vnode_ref on fd_rdir during a fork */ FD_CHROOT = 0x01, /* * process has created a kqworkloop that * requires manual cleanup on exit */ FD_WORKLOOP = 0x02, #if CONFIG_PROC_RESOURCE_LIMITS /* process has exceeded fd_nfiles soft limit */ FD_ABOVE_SOFT_LIMIT = 0x04, /* process has exceeded fd_nfiles hard limit */ FD_ABOVE_HARD_LIMIT = 0x08, /* fd_nfiles soft limit notification has already been sent */ FD_SOFT_LIMIT_NOTIFIED = 0x10, /* fd_nfiles hard limit notification has already been sent */ FD_HARD_LIMIT_NOTIFIED = 0x20, #endif /* CONFIG_PROC_RESOURCE_LIMITS */ }); #define FILEDESC_FORK_INHERITED_MASK (FD_CHROOT) struct filedesc { lck_mtx_t fd_lock; /* (L) lock to protect fdesc */ uint8_t fd_fpdrainwait; /* (L) has drain waiters */ filedesc_flags_t fd_flags; /* (L) filedesc flags */ u_short fd_cmask; /* (L) mask for file creation */ int fd_nfiles; /* (L) number of open fdesc slots allocated */ int fd_afterlast; /* (L) high-water mark of fd_ofiles */ int fd_freefile; /* (L) approx. next free file */ #if CONFIG_PROC_RESOURCE_LIMITS int fd_nfiles_open; int fd_nfiles_soft_limit; /* (L) fd_nfiles soft limit to trigger guard */ int fd_nfiles_hard_limit; /* (L) fd_nfiles hard limit to terminate */ #endif /* CONFIG_PROC_RESOURCE_LIMITS */ int fd_knlistsize; /* (L) size of knlist */ struct fileproc **XNU_PTRAUTH_SIGNED_PTR("filedesc.fd_ofiles") fd_ofiles; /* (L) file structures for open files */ char *fd_ofileflags; /* (L) per-process open file flags */ struct klist *fd_knlist; /* (L) list of attached knotes */ struct kqworkq *fd_wqkqueue; /* (L) the workq kqueue */ struct vnode *fd_cdir; /* (L) current directory */ struct vnode *fd_rdir; /* (L) root directory */ lck_rw_t fd_dirs_lock; /* keeps fd_cdir and fd_rdir stable across a lookup */ lck_mtx_t fd_kqhashlock; /* (Q) lock for dynamic kqueue hash */ u_long fd_kqhashmask; /* (Q) size of dynamic kqueue hash */ struct kqwllist *fd_kqhash; /* (Q) hash table for dynamic kqueues */ lck_mtx_t fd_knhashlock; /* (N) lock for hash table for attached knotes */ u_long fd_knhashmask; /* (N) size of knhash */ struct klist *fd_knhash; /* (N) hash table for attached knotes */ }; #define fdt_flag_test(fdt, flag) (((fdt)->fd_flags & (flag)) != 0) #define fdt_flag_set(fdt, flag) ((void)((fdt)->fd_flags |= (flag))) #define fdt_flag_clear(fdt, flag) ((void)((fdt)->fd_flags &= ~(flag))) #if CONFIG_PROC_RESOURCE_LIMITS #define fd_above_soft_limit_notify(fdp) fdt_flag_test(fdp, FD_ABOVE_SOFT_LIMIT) #define fd_above_hard_limit_notify(fdp) fdt_flag_test(fdp, FD_ABOVE_HARD_LIMIT) #define fd_above_soft_limit_send_notification(fdp) fdt_flag_set(fdp, FD_ABOVE_SOFT_LIMIT) #define fd_above_hard_limit_send_notification(fdp) fdt_flag_set(fdp, FD_ABOVE_HARD_LIMIT) #define fd_soft_limit_already_notified(fdp) fdt_flag_test(fdp, FD_SOFT_LIMIT_NOTIFIED) #define fd_soft_limit_notified(fdp) fdt_flag_set(fdp, FD_SOFT_LIMIT_NOTIFIED) #define fd_hard_limit_already_notified(fdp) fdt_flag_test(fdp, FD_HARD_LIMIT_NOTIFIED) #define fd_hard_limit_notified(fdp) fdt_flag_set(fdp, FD_HARD_LIMIT_NOTIFIED) #endif /* CONFIG_PROC_RESOURCE_LIMITS */ /* * Per-process open flags. */ #define UF_RESERVED 0x04 /* open pending / in progress */ #define UF_CLOSING 0x08 /* close in progress */ #define UF_RESVWAIT 0x10 /* close in progress */ #define UF_INHERIT 0x20 /* "inherit-on-exec" */ /* * Storage required per open file descriptor. */ #define OFILESIZE (sizeof(struct file *) + sizeof(char)) /*! * @function fdt_available * * @brief * Returns whether the file descritor table can accomodate * for @c n new entries. * * @discussion * The answer is only valid so long as the @c proc_fdlock() is held by the * caller. */ extern bool fdt_available_locked(proc_t p, int n); /*! * @struct fdt_iterator * * @brief * Type used to iterate a file descriptor table. */ struct fdt_iterator { int fdti_fd; struct fileproc *fdti_fp; }; /*! * @function fdt_next * * @brief * Seek the iterator forward. * * @discussion * The @c proc_fdlock() should be held by the caller. * * @param p * The process for which the file descriptor table is being iterated. * * @param fd * The current file file descriptor to scan from (exclusive). * * @param only_settled * When true, only fileprocs with @c UF_RESERVED set are returned. * If false, fileprocs that are in flux (@c UF_RESERVED is set) are returned. * * @returns * The next iterator position. * If @c fdti_fp is NULL, the iteration is done. */ extern struct fdt_iterator fdt_next(proc_t p, int fd, bool only_settled); /*! * @function fdt_next * * @brief * Seek the iterator backwards. * * @discussion * The @c proc_fdlock() should be held by the caller. * * @param p * The process for which the file descriptor table is being iterated. * * @param fd * The current file file descriptor to scan from (exclusive). * * @param only_settled * When true, only fileprocs with @c UF_RESERVED set are returned. * If false, fileprocs that are in flux (@c UF_RESERVED is set) are returned. * * @returns * The next iterator position. * If @c fdti_fp is NULL, the iteration is done. */ extern struct fdt_iterator fdt_prev(proc_t p, int fd, bool only_settled); /*! * @def fdt_foreach * * @brief * Convenience macro around @c fdt_next() to enumerates fileprocs in a process * file descriptor table. * * @discussion * The @c proc_fdlock() should be held by the caller. * * @param fp * The iteration variable. * * @param p * The process for which the file descriptor table is being iterated. */ #define fdt_foreach(fp, p) \ for (struct fdt_iterator __fdt_it = fdt_next(p, -1, true); \ ((fp) = __fdt_it.fdti_fp); \ __fdt_it = fdt_next(p, __fdt_it.fdti_fd, true)) /*! * @def fdt_foreach_fd * * @brief * When in an @c fdt_foreach() loop, return the current file descriptor * being inspected. */ #define fdt_foreach_fd() __fdt_it.fdti_fd /*! * @function fdt_init * * @brief * Initializers a proc file descriptor table. * * @warning * The proc that is passed is supposed to have been zeroed out, * as this function is used to setup @c kernelproc's file descriptor table * and some fields are already initialized when fdt_init() is called. */ extern void fdt_init(proc_t p); /*! * @function fdt_destroy * * @brief * Destroys locks from the file descriptor table. * * @description * This function destroys the file descriptor table locks. * * This cannot be done while the process this table belongs * to can be looked up. */ extern void fdt_destroy(proc_t p); /*! * @function fdt_fork * * @brief * Clones a file descriptor table for the @c fork() system call. * * @discussion * This function internally takes and drops @c proc_fdlock(). * * Files are copied directly, ignoring the new resource limits for the process * that's being copied into. Since the descriptor references are just * additional references, this does not count against the number of open files * on the system. * * The struct filedesc includes the current working directory, and the current * root directory, if the process is chroot'ed. * * If the exec was called by a thread using a per thread current working * directory, we inherit the working directory from the thread making the call, * rather than from the process. * * In the case of a failure to obtain a reference, for most cases, the file * entry will be silently dropped. There's an exception for the case of * a chroot dir, since a failure to to obtain a reference there would constitute * an "escape" from the chroot environment, which must not be allowed. * * @param child_fdt * The child process file descriptor table. * * @param parent_p * The parent process to clone the file descriptor table from. * * @param uth_cdir * The vnode for the current thread's current working directory if it is * different from the parent process one. * * @param in_exec * The duplication of fdt is happening for exec * * @returns * 0 Success * EPERM Unable to acquire a reference to the current chroot directory * ENOMEM Not enough memory to perform the clone operation */ extern int fdt_fork(struct filedesc *child_fdt, proc_t parent_p, struct vnode *uth_cdir, bool in_exec); /*! * @function fdt_exec * * @brief * Perform close-on-exec processing for all files in a process * that are either marked as close-on-exec. * * @description * Also handles the case (via posix_spawn()) where -all- files except those * marked with "inherit" as treated as close-on-exec. * * This function internally takes and drops proc_fdlock() * But assumes tables don't grow/change while unlocked. * * @param p * The process whose file descriptor table is being filrered. * * @param posix_spawn_flags * A set of @c POSIX_SPAWN_* flags. * * @param thread * new thread * * @param in_exec * If the process is in exec */ extern void fdt_exec(proc_t p, short posix_spawn_flags, thread_t thread, bool in_exec); /*! * @function fdt_invalidate * * @brief * Invalidates a proc file descriptor table. * * @discussion * Closes all open files in the file descriptor table, * empties hash tables, etc... * * However, the fileproc arrays stay allocated to still allow external lookups. * These get cleaned up by @c fdt_destroy(). * * This function internally takes and drops proc_fdlock(). */ extern void fdt_invalidate(proc_t p); /* * Kernel global variables and routines. */ extern int dupfdopen(proc_t p, int indx, int dfd, int mode, int error); extern int fdalloc(proc_t p, int want, int *result); extern void fdrelse(struct proc * p, int fd); #define fdfile(p, fd) \ (&(p)->p_fd.fd_ofiles[(fd)]) #define fdflags(p, fd) \ (&(p)->p_fd.fd_ofileflags[(fd)]) extern int falloc(proc_t p, struct fileproc **resultfp, int *resultfd, struct vfs_context *ctx); typedef void (*fp_initfn_t)(struct fileproc *, void *ctx); extern int falloc_withinit(proc_t p, struct fileproc **resultfp, int *resultfd, struct vfs_context *ctx, fp_initfn_t fp_init, void *initarg); #if CONFIG_PROC_RESOURCE_LIMITS void fd_check_limit_exceeded(struct filedesc *fdp); #endif /* CONFIG_PROC_RESOURCE_LIMITS */ #endif /* XNU_KERNEL_PRIVATE */ #endif /* !_SYS_FILEDESC_H_ */ |