]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_descrip.c
af4f5f27836a5f86c6b504113deb775c37c24a1d
[apple/xnu.git] / bsd / kern / kern_descrip.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
23 /*
24 * Copyright (c) 1982, 1986, 1989, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 * (c) UNIX System Laboratories, Inc.
27 * All or some portions of this file are derived from material licensed
28 * to the University of California by American Telephone and Telegraph
29 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30 * the permission of UNIX System Laboratories, Inc.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
61 */
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/filedesc.h>
66 #include <sys/kernel.h>
67 #include <sys/vnode_internal.h>
68 #include <sys/proc_internal.h>
69 #include <sys/kauth.h>
70 #include <sys/file_internal.h>
71 #include <sys/socket.h>
72 #include <sys/socketvar.h>
73 #include <sys/stat.h>
74 #include <sys/ioctl.h>
75 #include <sys/fcntl.h>
76 #include <sys/malloc.h>
77 #include <sys/mman.h>
78 #include <sys/syslog.h>
79 #include <sys/unistd.h>
80 #include <sys/resourcevar.h>
81 #include <sys/aio_kern.h>
82 #include <sys/ev.h>
83 #include <kern/lock.h>
84
85 #include <bsm/audit_kernel.h>
86
87 #include <sys/mount_internal.h>
88 #include <sys/kdebug.h>
89 #include <sys/sysproto.h>
90 #include <sys/pipe.h>
91 #include <kern/kern_types.h>
92 #include <kern/kalloc.h>
93 #include <libkern/OSAtomic.h>
94
95 struct psemnode;
96 struct pshmnode;
97
98 int fdopen(dev_t dev, int mode, int type, struct proc *p);
99 int ogetdtablesize(struct proc *p, void *uap, register_t *retval);
100 int finishdup(struct proc * p, struct filedesc *fdp, int old, int new, register_t *retval);
101
102 int closef(struct fileglob *fg, struct proc *p);
103 int falloc_locked(struct proc *p, struct fileproc **resultfp, int *resultfd, int locked);
104 void fddrop(struct proc *p, int fd);
105 int fdgetf_noref(struct proc *p, int fd, struct fileproc **resultfp);
106 void fg_drop(struct fileproc * fp);
107 void fg_free(struct fileglob *fg);
108 void fg_ref(struct fileproc * fp);
109 int fp_getfpshm(struct proc *p, int fd, struct fileproc **resultfp, struct pshmnode **resultpshm);
110
111 static int closef_finish(struct fileproc *fp, struct fileglob *fg, struct proc *p);
112
113 extern void file_lock_init(void);
114 extern int is_suser(void);
115 extern int kqueue_stat(struct fileproc *fp, struct stat *st, struct proc *p);
116 extern int soo_stat(struct socket *so, struct stat *ub);
117 extern int vn_path_package_check(vnode_t vp, char *path, int pathlen, int *component);
118
119 extern kauth_scope_t kauth_scope_fileop;
120
121 #define f_flag f_fglob->fg_flag
122 #define f_type f_fglob->fg_type
123 #define f_msgcount f_fglob->fg_msgcount
124 #define f_cred f_fglob->fg_cred
125 #define f_ops f_fglob->fg_ops
126 #define f_offset f_fglob->fg_offset
127 #define f_data f_fglob->fg_data
128 /*
129 * Descriptor management.
130 */
131 struct filelist filehead; /* head of list of open files */
132 struct fmsglist fmsghead; /* head of list of open files */
133 struct fmsglist fmsg_ithead; /* head of list of open files */
134 int nfiles; /* actual number of open files */
135
136
137 lck_grp_attr_t * file_lck_grp_attr;
138 lck_grp_t * file_lck_grp;
139 lck_attr_t * file_lck_attr;
140
141 lck_mtx_t * uipc_lock;
142 lck_mtx_t * file_iterate_lcok;
143 lck_mtx_t * file_flist_lock;
144
145
146 void
147 file_lock_init(void)
148 {
149
150 /* allocate file lock group attribute and group */
151 file_lck_grp_attr= lck_grp_attr_alloc_init();
152 lck_grp_attr_setstat(file_lck_grp_attr);
153
154 file_lck_grp = lck_grp_alloc_init("file", file_lck_grp_attr);
155
156 /* Allocate file lock attribute */
157 file_lck_attr = lck_attr_alloc_init();
158 //lck_attr_setdebug(file_lck_attr);
159
160 uipc_lock = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
161 file_iterate_lcok = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
162 file_flist_lock = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
163
164
165
166 }
167
168
169 void
170 proc_fdlock(struct proc *p)
171 {
172 lck_mtx_lock(&p->p_fdmlock);
173 }
174
175 void
176 proc_fdunlock(struct proc *p)
177 {
178 lck_mtx_unlock(&p->p_fdmlock);
179 }
180
181 /*
182 * System calls on descriptors.
183 */
184
185 int
186 getdtablesize(struct proc *p, __unused struct getdtablesize_args *uap, register_t *retval)
187 {
188 proc_fdlock(p);
189 *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
190 proc_fdunlock(p);
191
192 return (0);
193 }
194
195 int
196 ogetdtablesize(struct proc *p, __unused void *uap, register_t *retval)
197 {
198 proc_fdlock(p);
199 *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, NOFILE);
200 proc_fdunlock(p);
201
202 return (0);
203 }
204
205 void
206 procfdtbl_reservefd(struct proc * p, int fd)
207 {
208 p->p_fd->fd_ofiles[fd] = NULL;
209 p->p_fd->fd_ofileflags[fd] |= UF_RESERVED;
210 }
211
212 void
213 procfdtbl_markclosefd(struct proc * p, int fd)
214 {
215 p->p_fd->fd_ofileflags[fd] |= (UF_RESERVED | UF_CLOSING);
216 }
217
218 void
219 procfdtbl_releasefd(struct proc * p, int fd, struct fileproc * fp)
220 {
221 if (fp != NULL)
222 p->p_fd->fd_ofiles[fd] = fp;
223 p->p_fd->fd_ofileflags[fd] &= ~UF_RESERVED;
224 if ((p->p_fd->fd_ofileflags[fd] & UF_RESVWAIT) == UF_RESVWAIT) {
225 p->p_fd->fd_ofileflags[fd] &= ~UF_RESVWAIT;
226 wakeup(&p->p_fd);
227 }
228 }
229
230 void
231 procfdtbl_waitfd(struct proc * p, int fd)
232 {
233 p->p_fd->fd_ofileflags[fd] |= UF_RESVWAIT;
234 msleep(&p->p_fd, &p->p_fdmlock, PRIBIO, "ftbl_waitfd", NULL);
235 }
236
237
238 void
239 procfdtbl_clearfd(struct proc * p, int fd)
240 {
241 int waiting;
242
243 waiting = (p->p_fd->fd_ofileflags[fd] & UF_RESVWAIT);
244 p->p_fd->fd_ofiles[fd] = NULL;
245 p->p_fd->fd_ofileflags[fd] = 0;
246 if ( waiting == UF_RESVWAIT) {
247 wakeup(&p->p_fd);
248 }
249 }
250
251
252 static __inline__ void
253 _fdrelse(struct proc *p, int fd)
254 {
255 struct filedesc *fdp = p->p_fd;
256 int nfd = 0;
257
258 if (fd < fdp->fd_freefile)
259 fdp->fd_freefile = fd;
260 #if DIAGNOSTIC
261 if (fd > fdp->fd_lastfile)
262 panic("fdrelse: fd_lastfile inconsistent");
263 #endif
264 procfdtbl_clearfd(p, fd);
265
266 while ((nfd = fdp->fd_lastfile) > 0 &&
267 fdp->fd_ofiles[nfd] == NULL &&
268 !(fdp->fd_ofileflags[nfd] & UF_RESERVED))
269 fdp->fd_lastfile--;
270 }
271
272 /*
273 * Duplicate a file descriptor.
274 */
275 /* ARGSUSED */
276 int
277 dup(p, uap, retval)
278 struct proc *p;
279 struct dup_args *uap;
280 register_t *retval;
281 {
282 register struct filedesc *fdp = p->p_fd;
283 register int old = uap->fd;
284 int new, error;
285 struct fileproc *fp;
286
287 proc_fdlock(p);
288 if ( (error = fp_lookup(p, old, &fp, 1)) ) {
289 proc_fdunlock(p);
290 return(error);
291 }
292 if ( (error = fdalloc(p, 0, &new)) ) {
293 fp_drop(p, old, fp, 1);
294 proc_fdunlock(p);
295 return (error);
296 }
297 error = finishdup(p, fdp, old, new, retval);
298 fp_drop(p, old, fp, 1);
299 proc_fdunlock(p);
300
301 return (error);
302 }
303
304 /*
305 * Duplicate a file descriptor to a particular value.
306 */
307 /* ARGSUSED */
308 int
309 dup2(p, uap, retval)
310 struct proc *p;
311 struct dup2_args *uap;
312 register_t *retval;
313 {
314 register struct filedesc *fdp = p->p_fd;
315 register int old = uap->from, new = uap->to;
316 int i, error;
317 struct fileproc *fp, *nfp;
318
319 proc_fdlock(p);
320
321 startover:
322 if ( (error = fp_lookup(p, old, &fp, 1)) ) {
323 proc_fdunlock(p);
324 return(error);
325 }
326 if (new < 0 ||
327 new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
328 new >= maxfiles) {
329 fp_drop(p, old, fp, 1);
330 proc_fdunlock(p);
331 return (EBADF);
332 }
333 if (old == new) {
334 fp_drop(p, old, fp, 1);
335 *retval = new;
336 proc_fdunlock(p);
337 return (0);
338 }
339 if (new < 0 || new >= fdp->fd_nfiles) {
340 if ( (error = fdalloc(p, new, &i)) ) {
341 fp_drop(p, old, fp, 1);
342 proc_fdunlock(p);
343 return (error);
344 }
345 if (new != i) {
346 _fdrelse(p, i);
347 goto closeit;
348 }
349 } else {
350 closeit:
351 while ((fdp->fd_ofileflags[new] & UF_RESERVED) == UF_RESERVED) {
352 fp_drop(p, old, fp, 1);
353 procfdtbl_waitfd(p, new);
354 goto startover;
355 }
356
357 if ((fdp->fd_ofiles[new] != NULL) && ((error = fp_lookup(p, new, &nfp, 1)) == 0)) {
358 fp_drop(p, old, fp, 1);
359 close_internal(p, new, nfp, CLOSEINT_LOCKED | CLOSEINT_NOFDRELSE);
360 procfdtbl_clearfd(p, new);
361 goto startover;
362 } else {
363 procfdtbl_reservefd(p, new);
364 }
365 }
366 error = finishdup(p, fdp, old, new, retval);
367 fp_drop(p, old, fp, 1);
368 proc_fdunlock(p);
369
370 return(error);
371 }
372
373 /*
374 * The file control system call.
375 */
376 int
377 fcntl(p, uap, retval)
378 struct proc *p;
379 struct fcntl_args *uap;
380 register_t *retval;
381 {
382 int fd = uap->fd;
383 struct filedesc *fdp = p->p_fd;
384 struct fileproc *fp;
385 char *pop;
386 struct vnode *vp;
387 int i, tmp, error, error2, flg = F_POSIX;
388 struct flock fl;
389 struct vfs_context context;
390 off_t offset;
391 int newmin;
392 daddr64_t lbn, bn;
393 int devBlockSize = 0;
394 unsigned int fflag;
395 user_addr_t argp;
396
397 AUDIT_ARG(fd, uap->fd);
398 AUDIT_ARG(cmd, uap->cmd);
399
400 proc_fdlock(p);
401 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
402 proc_fdunlock(p);
403 return(error);
404 }
405 context.vc_proc = p;
406 context.vc_ucred = fp->f_cred;
407 if (proc_is64bit(p)) {
408 argp = uap->arg;
409 }
410 else {
411 /* since the arg parameter is defined as a long but may be either
412 * a long or a pointer we must take care to handle sign extension
413 * issues. Our sys call munger will sign extend a long when we are
414 * called from a 32-bit process. Since we can never have an address
415 * greater than 32-bits from a 32-bit process we lop off the top
416 * 32-bits to avoid getting the wrong address
417 */
418 argp = CAST_USER_ADDR_T(uap->arg);
419 }
420
421 pop = &fdp->fd_ofileflags[fd];
422
423 switch (uap->cmd) {
424
425 case F_DUPFD:
426 newmin = CAST_DOWN(int, uap->arg);
427 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
428 newmin >= maxfiles) {
429 error = EINVAL;
430 goto out;
431 }
432 if ( (error = fdalloc(p, newmin, &i)) )
433 goto out;
434 error = finishdup(p, fdp, fd, i, retval);
435 goto out;
436
437 case F_GETFD:
438 *retval = (*pop & UF_EXCLOSE)? 1 : 0;
439 error = 0;
440 goto out;
441
442 case F_SETFD:
443 *pop = (*pop &~ UF_EXCLOSE) |
444 (uap->arg & 1)? UF_EXCLOSE : 0;
445 error = 0;
446 goto out;
447
448 case F_GETFL:
449 *retval = OFLAGS(fp->f_flag);
450 error = 0;
451 goto out;
452
453 case F_SETFL:
454 fp->f_flag &= ~FCNTLFLAGS;
455 tmp = CAST_DOWN(int, uap->arg);
456 fp->f_flag |= FFLAGS(tmp) & FCNTLFLAGS;
457 tmp = fp->f_flag & FNONBLOCK;
458 error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
459 if (error)
460 goto out;
461 tmp = fp->f_flag & FASYNC;
462 error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, p);
463 if (!error)
464 goto out;
465 fp->f_flag &= ~FNONBLOCK;
466 tmp = 0;
467 (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, p);
468 goto out;
469
470 case F_GETOWN:
471 if (fp->f_type == DTYPE_SOCKET) {
472 *retval = ((struct socket *)fp->f_data)->so_pgid;
473 error = 0;
474 goto out;
475 }
476 error = fo_ioctl(fp, (int)TIOCGPGRP, (caddr_t)retval, p);
477 *retval = -*retval;
478 goto out;
479
480 case F_SETOWN:
481 tmp = CAST_DOWN(pid_t, uap->arg);
482 if (fp->f_type == DTYPE_SOCKET) {
483 ((struct socket *)fp->f_data)->so_pgid = tmp;
484 error =0;
485 goto out;
486 }
487 if (fp->f_type == DTYPE_PIPE) {
488 error = fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
489 goto out;
490 }
491
492 if (tmp <= 0) {
493 tmp = -tmp;
494 } else {
495 struct proc *p1 = pfind(tmp);
496 if (p1 == 0) {
497 error = ESRCH;
498 goto out;
499 }
500 tmp = (int)p1->p_pgrp->pg_id;
501 }
502 error = fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&tmp, p);
503 goto out;
504
505 case F_SETLKW:
506 flg |= F_WAIT;
507 /* Fall into F_SETLK */
508
509 case F_SETLK:
510 if (fp->f_type != DTYPE_VNODE) {
511 error = EBADF;
512 goto out;
513 }
514 vp = (struct vnode *)fp->f_data;
515
516 fflag = fp->f_flag;
517 offset = fp->f_offset;
518 proc_fdunlock(p);
519
520 /* Copy in the lock structure */
521 error = copyin(argp, (caddr_t)&fl, sizeof (fl));
522 if (error) {
523 goto outdrop;
524 }
525 if ( (error = vnode_getwithref(vp)) ) {
526 goto outdrop;
527 }
528 if (fl.l_whence == SEEK_CUR)
529 fl.l_start += offset;
530
531 switch (fl.l_type) {
532
533 case F_RDLCK:
534 if ((fflag & FREAD) == 0) {
535 (void)vnode_put(vp);
536 error = EBADF;
537 goto outdrop;
538 }
539 OSBitOrAtomic(P_LADVLOCK, &p->p_ladvflag);
540 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
541 (void)vnode_put(vp);
542 goto outdrop;
543
544 case F_WRLCK:
545 if ((fflag & FWRITE) == 0) {
546 (void)vnode_put(vp);
547 error = EBADF;
548 goto outdrop;
549 }
550 OSBitOrAtomic(P_LADVLOCK, &p->p_ladvflag);
551 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
552 (void)vnode_put(vp);
553 goto outdrop;
554
555 case F_UNLCK:
556 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
557 F_POSIX, &context);
558 (void)vnode_put(vp);
559 goto outdrop;
560
561 default:
562 (void)vnode_put(vp);
563 error = EINVAL;
564 goto outdrop;
565 }
566
567 case F_GETLK:
568 if (fp->f_type != DTYPE_VNODE) {
569 error = EBADF;
570 goto out;
571 }
572 vp = (struct vnode *)fp->f_data;
573
574 offset = fp->f_offset;
575 proc_fdunlock(p);
576
577 /* Copy in the lock structure */
578 error = copyin(argp, (caddr_t)&fl, sizeof (fl));
579 if (error)
580 goto outdrop;
581
582 if ( (error = vnode_getwithref(vp)) == 0 ) {
583 if (fl.l_whence == SEEK_CUR)
584 fl.l_start += offset;
585
586 error = VNOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX, &context);
587
588 (void)vnode_put(vp);
589
590 if (error == 0)
591 error = copyout((caddr_t)&fl, argp, sizeof (fl));
592 }
593 goto outdrop;
594
595 case F_PREALLOCATE: {
596 fstore_t alloc_struct; /* structure for allocate command */
597 u_int32_t alloc_flags = 0;
598
599 if (fp->f_type != DTYPE_VNODE) {
600 error = EBADF;
601 goto out;
602 }
603
604 vp = (struct vnode *)fp->f_data;
605 proc_fdunlock(p);
606
607 /* make sure that we have write permission */
608 if ((fp->f_flag & FWRITE) == 0) {
609 error = EBADF;
610 goto outdrop;
611 }
612
613 error = copyin(argp, (caddr_t)&alloc_struct, sizeof (alloc_struct));
614 if (error)
615 goto outdrop;
616
617 /* now set the space allocated to 0 */
618 alloc_struct.fst_bytesalloc = 0;
619
620 /*
621 * Do some simple parameter checking
622 */
623
624 /* set up the flags */
625
626 alloc_flags |= PREALLOCATE;
627
628 if (alloc_struct.fst_flags & F_ALLOCATECONTIG)
629 alloc_flags |= ALLOCATECONTIG;
630
631 if (alloc_struct.fst_flags & F_ALLOCATEALL)
632 alloc_flags |= ALLOCATEALL;
633
634 /*
635 * Do any position mode specific stuff. The only
636 * position mode supported now is PEOFPOSMODE
637 */
638
639 switch (alloc_struct.fst_posmode) {
640
641 case F_PEOFPOSMODE:
642 if (alloc_struct.fst_offset != 0) {
643 error = EINVAL;
644 goto outdrop;
645 }
646
647 alloc_flags |= ALLOCATEFROMPEOF;
648 break;
649
650 case F_VOLPOSMODE:
651 if (alloc_struct.fst_offset <= 0) {
652 error = EINVAL;
653 goto outdrop;
654 }
655
656 alloc_flags |= ALLOCATEFROMVOL;
657 break;
658
659 default: {
660 error = EINVAL;
661 goto outdrop;
662 }
663 }
664 if ( (error = vnode_getwithref(vp)) == 0 ) {
665 /*
666 * call allocate to get the space
667 */
668 error = VNOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags,
669 &alloc_struct.fst_bytesalloc, alloc_struct.fst_offset,
670 &context);
671 (void)vnode_put(vp);
672
673 error2 = copyout((caddr_t)&alloc_struct, argp, sizeof (alloc_struct));
674
675 if (error == 0)
676 error = error2;
677 }
678 goto outdrop;
679
680 }
681 case F_SETSIZE:
682 if (fp->f_type != DTYPE_VNODE) {
683 error = EBADF;
684 goto out;
685 }
686 proc_fdunlock(p);
687
688 error = copyin(argp, (caddr_t)&offset, sizeof (off_t));
689 if (error)
690 goto outdrop;
691
692 /*
693 * Make sure that we are root. Growing a file
694 * without zero filling the data is a security hole
695 * root would have access anyway so we'll allow it
696 */
697
698 if (!is_suser()) {
699 error = EACCES;
700 goto outdrop;
701 }
702 vp = (struct vnode *)fp->f_data;
703
704 if ( (error = vnode_getwithref(vp)) == 0 ) {
705 /*
706 * set the file size
707 */
708 error = vnode_setsize(vp, offset, IO_NOZEROFILL, &context);
709
710 (void)vnode_put(vp);
711 }
712 goto outdrop;
713
714 case F_RDAHEAD:
715 if (fp->f_type != DTYPE_VNODE) {
716 error = EBADF;
717 goto out;
718 }
719 vp = (struct vnode *)fp->f_data;
720 proc_fdunlock(p);
721
722 if ( (error = vnode_getwithref(vp)) == 0) {
723 if (uap->arg)
724 vnode_clearnoreadahead(vp);
725 else
726 vnode_setnoreadahead(vp);
727
728 (void)vnode_put(vp);
729 }
730 goto outdrop;
731
732 case F_NOCACHE:
733 if (fp->f_type != DTYPE_VNODE) {
734 error = EBADF;
735 goto out;
736 }
737 vp = (struct vnode *)fp->f_data;
738 proc_fdunlock(p);
739
740 if ( (error = vnode_getwithref(vp)) == 0 ) {
741 if (uap->arg)
742 vnode_setnocache(vp);
743 else
744 vnode_clearnocache(vp);
745
746 (void)vnode_put(vp);
747 }
748 goto outdrop;
749
750 case F_GLOBAL_NOCACHE:
751 if (fp->f_type != DTYPE_VNODE) {
752 error = EBADF;
753 goto out;
754 }
755 vp = (struct vnode *)fp->f_data;
756 proc_fdunlock(p);
757
758 if ( (error = vnode_getwithref(vp)) == 0 ) {
759
760 *retval = vnode_isnocache(vp);
761
762 if (uap->arg)
763 vnode_setnocache(vp);
764 else
765 vnode_clearnocache(vp);
766
767 (void)vnode_put(vp);
768 }
769 goto outdrop;
770
771 case F_RDADVISE: {
772 struct radvisory ra_struct;
773
774 if (fp->f_type != DTYPE_VNODE) {
775 error = EBADF;
776 goto out;
777 }
778 vp = (struct vnode *)fp->f_data;
779 proc_fdunlock(p);
780
781 if ( (error = copyin(argp, (caddr_t)&ra_struct, sizeof (ra_struct))) )
782 goto outdrop;
783 if ( (error = vnode_getwithref(vp)) == 0 ) {
784 error = VNOP_IOCTL(vp, F_RDADVISE, (caddr_t)&ra_struct, 0, &context);
785
786 (void)vnode_put(vp);
787 }
788 goto outdrop;
789 }
790
791 case F_READBOOTSTRAP:
792 case F_WRITEBOOTSTRAP: {
793 fbootstraptransfer_t fbt_struct;
794 user_fbootstraptransfer_t user_fbt_struct;
795 int sizeof_struct;
796 caddr_t boot_structp;
797
798 if (fp->f_type != DTYPE_VNODE) {
799 error = EBADF;
800 goto out;
801 }
802 vp = (struct vnode *)fp->f_data;
803 proc_fdunlock(p);
804
805 if (IS_64BIT_PROCESS(p)) {
806 sizeof_struct = sizeof(user_fbt_struct);
807 boot_structp = (caddr_t) &user_fbt_struct;
808 }
809 else {
810 sizeof_struct = sizeof(fbt_struct);
811 boot_structp = (caddr_t) &fbt_struct;
812 }
813 error = copyin(argp, boot_structp, sizeof_struct);
814 if (error)
815 goto outdrop;
816 if ( (error = vnode_getwithref(vp)) ) {
817 goto outdrop;
818 }
819 if (uap->cmd == F_WRITEBOOTSTRAP) {
820 /*
821 * Make sure that we are root. Updating the
822 * bootstrap on a disk could be a security hole
823 */
824 if (!is_suser()) {
825 (void)vnode_put(vp);
826 error = EACCES;
827 goto outdrop;
828 }
829 }
830 if (strcmp(vnode_mount(vp)->mnt_vfsstat.f_fstypename, "hfs") != 0) {
831 error = EINVAL;
832 } else {
833 /*
834 * call vnop_ioctl to handle the I/O
835 */
836 error = VNOP_IOCTL(vp, uap->cmd, boot_structp, 0, &context);
837 }
838 (void)vnode_put(vp);
839 goto outdrop;
840 }
841 case F_LOG2PHYS: {
842 struct log2phys l2p_struct; /* structure for allocate command */
843
844 if (fp->f_type != DTYPE_VNODE) {
845 error = EBADF;
846 goto out;
847 }
848 vp = (struct vnode *)fp->f_data;
849 proc_fdunlock(p);
850 if ( (error = vnode_getwithref(vp)) ) {
851 goto outdrop;
852 }
853 error = VNOP_OFFTOBLK(vp, fp->f_offset, &lbn);
854 if (error) {
855 (void)vnode_put(vp);
856 goto outdrop;
857 }
858 error = VNOP_BLKTOOFF(vp, lbn, &offset);
859 if (error) {
860 (void)vnode_put(vp);
861 goto outdrop;
862 }
863 devBlockSize = vfs_devblocksize(vnode_mount(vp));
864
865 error = VNOP_BLOCKMAP(vp, offset, devBlockSize, &bn, NULL, NULL, 0, &context);
866
867 (void)vnode_put(vp);
868
869 if (!error) {
870 l2p_struct.l2p_flags = 0; /* for now */
871 l2p_struct.l2p_contigbytes = 0; /* for now */
872 l2p_struct.l2p_devoffset = bn * devBlockSize;
873 l2p_struct.l2p_devoffset += fp->f_offset - offset;
874 error = copyout((caddr_t)&l2p_struct, argp, sizeof (l2p_struct));
875 }
876 goto outdrop;
877 }
878 case F_GETPATH: {
879 char *pathbufp;
880 int pathlen;
881
882 if (fp->f_type != DTYPE_VNODE) {
883 error = EBADF;
884 goto out;
885 }
886 vp = (struct vnode *)fp->f_data;
887 proc_fdunlock(p);
888
889 pathlen = MAXPATHLEN;
890 MALLOC(pathbufp, char *, pathlen, M_TEMP, M_WAITOK);
891 if (pathbufp == NULL) {
892 error = ENOMEM;
893 goto outdrop;
894 }
895 if ( (error = vnode_getwithref(vp)) == 0 ) {
896 error = vn_getpath(vp, pathbufp, &pathlen);
897 (void)vnode_put(vp);
898
899 if (error == 0)
900 error = copyout((caddr_t)pathbufp, argp, pathlen);
901 }
902 FREE(pathbufp, M_TEMP);
903 goto outdrop;
904 }
905
906 case F_PATHPKG_CHECK: {
907 char *pathbufp;
908 size_t pathlen;
909
910 if (fp->f_type != DTYPE_VNODE) {
911 error = EBADF;
912 goto out;
913 }
914 vp = (struct vnode *)fp->f_data;
915 proc_fdunlock(p);
916
917 pathlen = MAXPATHLEN;
918 pathbufp = kalloc(MAXPATHLEN);
919
920 if ( (error = copyinstr(argp, pathbufp, MAXPATHLEN, &pathlen)) == 0 ) {
921 if ( (error = vnode_getwithref(vp)) == 0 ) {
922 error = vn_path_package_check(vp, pathbufp, pathlen, retval);
923
924 (void)vnode_put(vp);
925 }
926 }
927 kfree(pathbufp, MAXPATHLEN);
928 goto outdrop;
929 }
930
931 case F_CHKCLEAN: // used by regression tests to see if all dirty pages got cleaned by fsync()
932 case F_FULLFSYNC: // fsync + flush the journal + DKIOCSYNCHRONIZECACHE
933 case F_FREEZE_FS: // freeze all other fs operations for the fs of this fd
934 case F_THAW_FS: { // thaw all frozen fs operations for the fs of this fd
935 if (fp->f_type != DTYPE_VNODE) {
936 error = EBADF;
937 goto out;
938 }
939 vp = (struct vnode *)fp->f_data;
940 proc_fdunlock(p);
941
942 if ( (error = vnode_getwithref(vp)) == 0 ) {
943 error = VNOP_IOCTL(vp, uap->cmd, (caddr_t)NULL, 0, &context);
944
945 (void)vnode_put(vp);
946 }
947 break;
948 }
949
950 default:
951 if (uap->cmd < FCNTL_FS_SPECIFIC_BASE) {
952 error = EINVAL;
953 goto out;
954 }
955
956 // if it's a fs-specific fcntl() then just pass it through
957
958 if (fp->f_type != DTYPE_VNODE) {
959 error = EBADF;
960 goto out;
961 }
962 vp = (struct vnode *)fp->f_data;
963 proc_fdunlock(p);
964
965 if ( (error = vnode_getwithref(vp)) == 0 ) {
966 error = VNOP_IOCTL(vp, uap->cmd, CAST_DOWN(caddr_t, argp), 0, &context);
967
968 (void)vnode_put(vp);
969 }
970 break;
971
972 }
973
974 outdrop:
975 AUDIT_ARG(vnpath_withref, vp, ARG_VNODE1);
976 fp_drop(p, fd, fp, 0);
977 return(error);
978 out:
979 fp_drop(p, fd, fp, 1);
980 proc_fdunlock(p);
981 return(error);
982 }
983
984 /*
985 * Common code for dup, dup2, and fcntl(F_DUPFD).
986 */
987 int
988 finishdup(struct proc * p, struct filedesc *fdp, int old, int new, register_t *retval)
989 {
990 struct fileproc *nfp;
991 struct fileproc *ofp;
992
993 if ((ofp = fdp->fd_ofiles[old]) == NULL ||
994 (fdp->fd_ofileflags[old] & UF_RESERVED)) {
995 _fdrelse(p, new);
996 return (EBADF);
997 }
998 fg_ref(ofp);
999 proc_fdunlock(p);
1000
1001 MALLOC_ZONE(nfp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
1002 bzero(nfp, sizeof(struct fileproc));
1003
1004 proc_fdlock(p);
1005 nfp->f_flags = 0;
1006 nfp->f_fglob = ofp->f_fglob;
1007 nfp->f_iocount = 0;
1008
1009 if (new > fdp->fd_lastfile)
1010 fdp->fd_lastfile = new;
1011 procfdtbl_releasefd(p, new, nfp);
1012 *retval = new;
1013 return (0);
1014 }
1015
1016
1017 int
1018 close(struct proc *p, struct close_args *uap, __unused register_t *retval)
1019 {
1020 struct fileproc *fp;
1021 int fd = uap->fd;
1022 int error =0;
1023
1024 AUDIT_SYSCLOSE(p, fd);
1025
1026 proc_fdlock(p);
1027
1028 if ( (error = fp_lookup(p,fd,&fp, 1)) ) {
1029 proc_fdunlock(p);
1030 return(error);
1031 }
1032
1033 error = close_internal(p, fd, fp, CLOSEINT_LOCKED);
1034
1035 proc_fdunlock(p);
1036
1037 return(error);
1038 }
1039
1040
1041 /*
1042 * Close a file descriptor.
1043 */
1044 int
1045 close_internal(struct proc *p, int fd, struct fileproc *fp, int flags)
1046 {
1047 struct filedesc *fdp = p->p_fd;
1048 int error =0;
1049 int locked = flags & CLOSEINT_LOCKED;
1050 int waitonclose = flags & CLOSEINT_WAITONCLOSE;
1051 int norelse = flags & CLOSEINT_NOFDRELSE;
1052 int nofdref = flags & CLOSEINT_NOFDNOREF;
1053 int slpstate = PRIBIO;
1054
1055 if (!locked)
1056 proc_fdlock(p);
1057
1058 /* Keep people from using the filedesc while we are closing it */
1059 procfdtbl_markclosefd(p, fd);
1060 if ((fp->f_flags & FP_CLOSING) == FP_CLOSING) {
1061 panic("close_internal_locked: being called on already closing fd\n");
1062 }
1063
1064
1065
1066 fp->f_flags |= FP_CLOSING;
1067 if (nofdref)
1068 fp->f_iocount++;
1069
1070 if ( (fp->f_flags & FP_AIOISSUED) || kauth_authorize_fileop_has_listeners() ) {
1071
1072 proc_fdunlock(p);
1073
1074 if ( (fp->f_type == DTYPE_VNODE) && kauth_authorize_fileop_has_listeners() ) {
1075 /*
1076 * call out to allow 3rd party notification of close.
1077 * Ignore result of kauth_authorize_fileop call.
1078 */
1079 if (vnode_getwithref((vnode_t)fp->f_data) == 0) {
1080 u_int fileop_flags = 0;
1081 if ((fp->f_flags & FP_WRITTEN) != 0)
1082 fileop_flags |= KAUTH_FILEOP_CLOSE_MODIFIED;
1083 kauth_authorize_fileop(fp->f_fglob->fg_cred, KAUTH_FILEOP_CLOSE,
1084 (uintptr_t)fp->f_data, (uintptr_t)fileop_flags);
1085 vnode_put((vnode_t)fp->f_data);
1086 }
1087 }
1088 if (fp->f_flags & FP_AIOISSUED)
1089 /*
1090 * cancel all async IO requests that can be cancelled.
1091 */
1092 _aio_close( p, fd );
1093
1094 proc_fdlock(p);
1095 }
1096
1097 if (fd < fdp->fd_knlistsize)
1098 knote_fdclose(p, fd);
1099
1100 if (fp->f_flags & FP_WAITEVENT)
1101 (void)waitevent_close(p, fp);
1102
1103 if ((fp->f_flags & FP_INCHRREAD) == 0)
1104 fileproc_drain(p, fp);
1105 if (norelse == 0)
1106 _fdrelse(p, fd);
1107 error = closef_locked(fp, fp->f_fglob, p);
1108 if ((fp->f_flags & FP_WAITCLOSE) == FP_WAITCLOSE)
1109 wakeup(&fp->f_flags);
1110 fp->f_flags &= ~(FP_WAITCLOSE | FP_CLOSING);
1111
1112 if (!locked)
1113 proc_fdunlock(p);
1114
1115 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
1116 return(error);
1117 }
1118
1119 /*
1120 * Return status information about a file descriptor.
1121 *
1122 * XXX switch on node type is bogus; need a stat in struct fileops instead.
1123 */
1124 static int
1125 fstat1(struct proc *p, int fd, user_addr_t ub, user_addr_t xsecurity, user_addr_t xsecurity_size)
1126 {
1127 struct fileproc *fp;
1128 struct stat sb;
1129 struct user_stat user_sb;
1130 int error, my_size;
1131 int funnel_state;
1132 file_type_t type;
1133 caddr_t data;
1134 kauth_filesec_t fsec;
1135 ssize_t xsecurity_bufsize;
1136 int entrycount;
1137 struct vfs_context context;
1138
1139
1140 AUDIT_ARG(fd, fd);
1141
1142 if ((error = fp_lookup(p, fd, &fp, 0)) != 0)
1143 return(error);
1144 type = fp->f_type;
1145 data = fp->f_data;
1146 fsec = KAUTH_FILESEC_NONE;
1147
1148 switch (type) {
1149
1150 case DTYPE_VNODE:
1151 context.vc_proc = current_proc();
1152 context.vc_ucred = kauth_cred_get();
1153 if ((error = vnode_getwithref((vnode_t)data)) == 0) {
1154 /*
1155 * If the caller has the file open, and is not requesting extended security,
1156 * we are going to let them get the basic stat information.
1157 */
1158 if (xsecurity == USER_ADDR_NULL) {
1159 error = vn_stat_noauth((vnode_t)data, &sb, NULL, &context);
1160 } else {
1161 error = vn_stat((vnode_t)data, &sb, &fsec, &context);
1162 }
1163
1164 AUDIT_ARG(vnpath, (struct vnode *)data, ARG_VNODE1);
1165 (void)vnode_put((vnode_t)data);
1166 }
1167 break;
1168
1169 case DTYPE_SOCKET:
1170 error = soo_stat((struct socket *)data, &sb);
1171 break;
1172
1173 case DTYPE_PIPE:
1174 error = pipe_stat((void *)data, &sb);
1175 break;
1176
1177 case DTYPE_PSXSHM:
1178 error = pshm_stat((void *)data, &sb);
1179 break;
1180
1181 case DTYPE_KQUEUE:
1182 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1183 error = kqueue_stat(fp, &sb, p);
1184 thread_funnel_set(kernel_flock, funnel_state);
1185 break;
1186
1187 default:
1188 error = EBADF;
1189 goto out;
1190 }
1191 /* Zap spare fields */
1192 sb.st_lspare = 0;
1193 sb.st_qspare[0] = 0LL;
1194 sb.st_qspare[1] = 0LL;
1195 if (error == 0) {
1196 caddr_t sbp;
1197 if (IS_64BIT_PROCESS(current_proc())) {
1198 munge_stat(&sb, &user_sb);
1199 my_size = sizeof(user_sb);
1200 sbp = (caddr_t)&user_sb;
1201 }
1202 else {
1203 my_size = sizeof(sb);
1204 sbp = (caddr_t)&sb;
1205 }
1206 error = copyout(sbp, ub, my_size);
1207 }
1208
1209 /* caller wants extended security information? */
1210 if (xsecurity != USER_ADDR_NULL) {
1211
1212 /* did we get any? */
1213 if (fsec == KAUTH_FILESEC_NONE) {
1214 if (susize(xsecurity_size, 0) != 0) {
1215 error = EFAULT;
1216 goto out;
1217 }
1218 } else {
1219 /* find the user buffer size */
1220 xsecurity_bufsize = fusize(xsecurity_size);
1221
1222 /* copy out the actual data size */
1223 if (susize(xsecurity_size, KAUTH_FILESEC_COPYSIZE(fsec)) != 0) {
1224 error = EFAULT;
1225 goto out;
1226 }
1227
1228 /* if the caller supplied enough room, copy out to it */
1229 if (xsecurity_bufsize >= KAUTH_FILESEC_COPYSIZE(fsec))
1230 error = copyout(fsec, xsecurity, KAUTH_FILESEC_COPYSIZE(fsec));
1231 }
1232 }
1233 out:
1234 fp_drop(p, fd, fp, 0);
1235 if (fsec != NULL)
1236 kauth_filesec_free(fsec);
1237 return (error);
1238 }
1239
1240 int
1241 fstat_extended(struct proc *p, struct fstat_extended_args *uap, __unused register_t *retval)
1242 {
1243 return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size));
1244 }
1245
1246 int
1247 fstat(struct proc *p, register struct fstat_args *uap, __unused register_t *retval)
1248 {
1249 return(fstat1(p, uap->fd, uap->ub, 0, 0));
1250 }
1251
1252 /*
1253 * Return pathconf information about a file descriptor.
1254 */
1255 int
1256 fpathconf(p, uap, retval)
1257 struct proc *p;
1258 register struct fpathconf_args *uap;
1259 register_t *retval;
1260 {
1261 int fd = uap->fd;
1262 struct fileproc *fp;
1263 struct vnode *vp;
1264 struct vfs_context context;
1265 int error = 0;
1266 file_type_t type;
1267 caddr_t data;
1268
1269
1270 AUDIT_ARG(fd, uap->fd);
1271 if ( (error = fp_lookup(p, fd, &fp, 0)) )
1272 return(error);
1273 type = fp->f_type;
1274 data = fp->f_data;
1275
1276 switch (type) {
1277
1278 case DTYPE_SOCKET:
1279 if (uap->name != _PC_PIPE_BUF) {
1280 error = EINVAL;
1281 goto out;
1282 }
1283 *retval = PIPE_BUF;
1284 error = 0;
1285 goto out;
1286
1287 case DTYPE_PIPE:
1288 *retval = PIPE_BUF;
1289 error = 0;
1290 goto out;
1291
1292 case DTYPE_VNODE:
1293 vp = (struct vnode *)data;
1294
1295 if ( (error = vnode_getwithref(vp)) == 0) {
1296 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
1297
1298 context.vc_proc = p;
1299 context.vc_ucred = kauth_cred_get();
1300
1301 error = vn_pathconf(vp, uap->name, retval, &context);
1302
1303 (void)vnode_put(vp);
1304 }
1305 goto out;
1306
1307 case DTYPE_PSXSHM:
1308 case DTYPE_PSXSEM:
1309 case DTYPE_KQUEUE:
1310 case DTYPE_FSEVENTS:
1311 error = EINVAL;
1312 goto out;
1313
1314 }
1315 /*NOTREACHED*/
1316 out:
1317 fp_drop(p, fd, fp, 0);
1318 return(error);
1319 }
1320
1321 /*
1322 * Allocate a file descriptor for the process.
1323 */
1324 int fdexpand;
1325
1326 int
1327 fdalloc(p, want, result)
1328 struct proc *p;
1329 int want;
1330 int *result;
1331 {
1332 register struct filedesc *fdp = p->p_fd;
1333 register int i;
1334 int lim, last, numfiles, oldnfiles;
1335 struct fileproc **newofiles, **ofiles;
1336 char *newofileflags;
1337
1338 /*
1339 * Search for a free descriptor starting at the higher
1340 * of want or fd_freefile. If that fails, consider
1341 * expanding the ofile array.
1342 */
1343 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1344 for (;;) {
1345 last = min(fdp->fd_nfiles, lim);
1346 if ((i = want) < fdp->fd_freefile)
1347 i = fdp->fd_freefile;
1348 for (; i < last; i++) {
1349 if (fdp->fd_ofiles[i] == NULL && !(fdp->fd_ofileflags[i] & UF_RESERVED)) {
1350 procfdtbl_reservefd(p, i);
1351 if (i > fdp->fd_lastfile)
1352 fdp->fd_lastfile = i;
1353 if (want <= fdp->fd_freefile)
1354 fdp->fd_freefile = i;
1355 *result = i;
1356 return (0);
1357 }
1358 }
1359
1360 /*
1361 * No space in current array. Expand?
1362 */
1363 if (fdp->fd_nfiles >= lim)
1364 return (EMFILE);
1365 if (fdp->fd_nfiles < NDEXTENT)
1366 numfiles = NDEXTENT;
1367 else
1368 numfiles = 2 * fdp->fd_nfiles;
1369 /* Enforce lim */
1370 if (numfiles > lim)
1371 numfiles = lim;
1372 proc_fdunlock(p);
1373 MALLOC_ZONE(newofiles, struct fileproc **,
1374 numfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
1375 proc_fdlock(p);
1376 if (newofiles == NULL) {
1377 return (ENOMEM);
1378 }
1379 if (fdp->fd_nfiles >= numfiles) {
1380 FREE_ZONE(newofiles, numfiles * OFILESIZE, M_OFILETABL);
1381 continue;
1382 }
1383 newofileflags = (char *) &newofiles[numfiles];
1384 /*
1385 * Copy the existing ofile and ofileflags arrays
1386 * and zero the new portion of each array.
1387 */
1388 oldnfiles = fdp->fd_nfiles;
1389 (void) memcpy(newofiles, fdp->fd_ofiles,
1390 oldnfiles * sizeof *fdp->fd_ofiles);
1391 (void) memset(&newofiles[oldnfiles], 0,
1392 (numfiles - oldnfiles) * sizeof *fdp->fd_ofiles);
1393
1394 (void) memcpy(newofileflags, fdp->fd_ofileflags,
1395 oldnfiles * sizeof *fdp->fd_ofileflags);
1396 (void) memset(&newofileflags[oldnfiles], 0,
1397 (numfiles - oldnfiles) *
1398 sizeof *fdp->fd_ofileflags);
1399 ofiles = fdp->fd_ofiles;
1400 fdp->fd_ofiles = newofiles;
1401 fdp->fd_ofileflags = newofileflags;
1402 fdp->fd_nfiles = numfiles;
1403 FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
1404 fdexpand++;
1405 }
1406 }
1407
1408 /*
1409 * Check to see whether n user file descriptors
1410 * are available to the process p.
1411 */
1412 int
1413 fdavail(p, n)
1414 struct proc *p;
1415 int n;
1416 {
1417 struct filedesc *fdp = p->p_fd;
1418 struct fileproc **fpp;
1419 char *flags;
1420 int i, lim;
1421
1422 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1423 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
1424 return (1);
1425 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
1426 flags = &fdp->fd_ofileflags[fdp->fd_freefile];
1427 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
1428 if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
1429 return (1);
1430 return (0);
1431 }
1432
1433 void
1434 fdrelse(p, fd)
1435 struct proc *p;
1436 int fd;
1437 {
1438 _fdrelse(p, fd);
1439 }
1440
1441 void
1442 fddrop(p, fd)
1443 struct proc *p;
1444 int fd;
1445 {
1446 struct filedesc *fdp = p->p_fd;
1447 struct fileproc *fp;
1448
1449 if (fd < fdp->fd_freefile)
1450 fdp->fd_freefile = fd;
1451 #if DIAGNOSTIC
1452 if (fd > fdp->fd_lastfile)
1453 panic("fdrelse: fd_lastfile inconsistent");
1454 #endif
1455 fp = fdp->fd_ofiles[fd];
1456 fdp->fd_ofiles[fd] = NULL;
1457 fdp->fd_ofileflags[fd] = 0;
1458
1459 while ((fd = fdp->fd_lastfile) > 0 &&
1460 fdp->fd_ofiles[fd] == NULL &&
1461 !(fdp->fd_ofileflags[fd] & UF_RESERVED))
1462 fdp->fd_lastfile--;
1463 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
1464 }
1465
1466
1467 int
1468 fdgetf_noref(p, fd, resultfp)
1469 struct proc *p;
1470 int fd;
1471 struct fileproc **resultfp;
1472 {
1473 struct filedesc *fdp = p->p_fd;
1474 struct fileproc *fp;
1475
1476 if (fd < 0 || fd >= fdp->fd_nfiles ||
1477 (fp = fdp->fd_ofiles[fd]) == NULL ||
1478 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1479 return (EBADF);
1480 }
1481 if (resultfp)
1482 *resultfp = fp;
1483 return (0);
1484 }
1485
1486
1487 /* should be called only when proc_fdlock is held */
1488 void
1489 fp_setflags(proc_t p, struct fileproc * fp, int flags)
1490 {
1491 proc_fdlock(p);
1492 fp->f_flags |= flags;
1493 proc_fdunlock(p);
1494 }
1495
1496 void
1497 fp_clearflags(proc_t p, struct fileproc * fp, int flags)
1498 {
1499
1500 proc_fdlock(p);
1501 if (fp)
1502 fp->f_flags &= ~flags;
1503 proc_fdunlock(p);
1504 }
1505
1506 int
1507 fp_getfvp(p, fd, resultfp, resultvp)
1508 struct proc *p;
1509 int fd;
1510 struct fileproc **resultfp;
1511 struct vnode **resultvp;
1512 {
1513 struct filedesc *fdp = p->p_fd;
1514 struct fileproc *fp;
1515
1516 proc_fdlock(p);
1517 if (fd < 0 || fd >= fdp->fd_nfiles ||
1518 (fp = fdp->fd_ofiles[fd]) == NULL ||
1519 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1520 proc_fdunlock(p);
1521 return (EBADF);
1522 }
1523 if (fp->f_type != DTYPE_VNODE) {
1524 proc_fdunlock(p);
1525 return(ENOTSUP);
1526 }
1527 fp->f_iocount++;
1528
1529 if (resultfp)
1530 *resultfp = fp;
1531 if (resultvp)
1532 *resultvp = (struct vnode *)fp->f_data;
1533 proc_fdunlock(p);
1534
1535 return (0);
1536 }
1537
1538
1539 /*
1540 * Returns: EBADF The file descriptor is invalid
1541 * EOPNOTSUPP The file descriptor is not a socket
1542 * 0 Success
1543 *
1544 * Notes: EOPNOTSUPP should probably be ENOTSOCK; this function is only
1545 * ever called from accept1().
1546 */
1547 int
1548 fp_getfsock(p, fd, resultfp, results)
1549 struct proc *p;
1550 int fd;
1551 struct fileproc **resultfp;
1552 struct socket **results;
1553 {
1554 struct filedesc *fdp = p->p_fd;
1555 struct fileproc *fp;
1556
1557 proc_fdlock(p);
1558 if (fd < 0 || fd >= fdp->fd_nfiles ||
1559 (fp = fdp->fd_ofiles[fd]) == NULL ||
1560 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1561 proc_fdunlock(p);
1562 return (EBADF);
1563 }
1564 if (fp->f_type != DTYPE_SOCKET) {
1565 proc_fdunlock(p);
1566 return(EOPNOTSUPP);
1567 }
1568 fp->f_iocount++;
1569
1570 if (resultfp)
1571 *resultfp = fp;
1572 if (results)
1573 *results = (struct socket *)fp->f_data;
1574 proc_fdunlock(p);
1575
1576 return (0);
1577 }
1578
1579
1580 int
1581 fp_getfkq(p, fd, resultfp, resultkq)
1582 struct proc *p;
1583 int fd;
1584 struct fileproc **resultfp;
1585 struct kqueue **resultkq;
1586 {
1587 struct filedesc *fdp = p->p_fd;
1588 struct fileproc *fp;
1589
1590 proc_fdlock(p);
1591 if ( fd < 0 || fd >= fdp->fd_nfiles ||
1592 (fp = fdp->fd_ofiles[fd]) == NULL ||
1593 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1594 proc_fdunlock(p);
1595 return (EBADF);
1596 }
1597 if (fp->f_type != DTYPE_KQUEUE) {
1598 proc_fdunlock(p);
1599 return(EBADF);
1600 }
1601 fp->f_iocount++;
1602
1603 if (resultfp)
1604 *resultfp = fp;
1605 if (resultkq)
1606 *resultkq = (struct kqueue *)fp->f_data;
1607 proc_fdunlock(p);
1608
1609 return (0);
1610 }
1611
1612 int
1613 fp_getfpshm(p, fd, resultfp, resultpshm)
1614 struct proc *p;
1615 int fd;
1616 struct fileproc **resultfp;
1617 struct pshmnode **resultpshm;
1618 {
1619 struct filedesc *fdp = p->p_fd;
1620 struct fileproc *fp;
1621
1622 proc_fdlock(p);
1623 if (fd < 0 || fd >= fdp->fd_nfiles ||
1624 (fp = fdp->fd_ofiles[fd]) == NULL ||
1625 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1626 proc_fdunlock(p);
1627 return (EBADF);
1628 }
1629 if (fp->f_type != DTYPE_PSXSHM) {
1630
1631 proc_fdunlock(p);
1632 return(EBADF);
1633 }
1634 fp->f_iocount++;
1635
1636 if (resultfp)
1637 *resultfp = fp;
1638 if (resultpshm)
1639 *resultpshm = (struct pshmnode *)fp->f_data;
1640 proc_fdunlock(p);
1641
1642 return (0);
1643 }
1644
1645
1646 int
1647 fp_getfpsem(p, fd, resultfp, resultpsem)
1648 struct proc *p;
1649 int fd;
1650 struct fileproc **resultfp;
1651 struct psemnode **resultpsem;
1652 {
1653 struct filedesc *fdp = p->p_fd;
1654 struct fileproc *fp;
1655
1656 proc_fdlock(p);
1657 if (fd < 0 || fd >= fdp->fd_nfiles ||
1658 (fp = fdp->fd_ofiles[fd]) == NULL ||
1659 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1660 proc_fdunlock(p);
1661 return (EBADF);
1662 }
1663 if (fp->f_type != DTYPE_PSXSEM) {
1664 proc_fdunlock(p);
1665 return(EBADF);
1666 }
1667 fp->f_iocount++;
1668
1669 if (resultfp)
1670 *resultfp = fp;
1671 if (resultpsem)
1672 *resultpsem = (struct psemnode *)fp->f_data;
1673 proc_fdunlock(p);
1674
1675 return (0);
1676 }
1677 int
1678 fp_lookup(p, fd, resultfp, locked)
1679 struct proc *p;
1680 int fd;
1681 struct fileproc **resultfp;
1682 int locked;
1683 {
1684 struct filedesc *fdp = p->p_fd;
1685 struct fileproc *fp;
1686
1687 if (!locked)
1688 proc_fdlock(p);
1689 if (fd < 0 || fd >= fdp->fd_nfiles ||
1690 (fp = fdp->fd_ofiles[fd]) == NULL ||
1691 (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
1692 if (!locked)
1693 proc_fdunlock(p);
1694 return (EBADF);
1695 }
1696 fp->f_iocount++;
1697
1698 if (resultfp)
1699 *resultfp = fp;
1700 if (!locked)
1701 proc_fdunlock(p);
1702
1703 return (0);
1704 }
1705
1706 int
1707 fp_drop_written(proc_t p, int fd, struct fileproc *fp)
1708 {
1709 int error;
1710
1711 proc_fdlock(p);
1712
1713 fp->f_flags |= FP_WRITTEN;
1714
1715 error = fp_drop(p, fd, fp, 1);
1716
1717 proc_fdunlock(p);
1718
1719 return (error);
1720 }
1721
1722
1723 int
1724 fp_drop_event(proc_t p, int fd, struct fileproc *fp)
1725 {
1726 int error;
1727
1728 proc_fdlock(p);
1729
1730 fp->f_flags |= FP_WAITEVENT;
1731
1732 error = fp_drop(p, fd, fp, 1);
1733
1734 proc_fdunlock(p);
1735
1736 return (error);
1737 }
1738
1739 int
1740 fp_drop(p, fd, fp, locked)
1741 struct proc *p;
1742 int fd;
1743 struct fileproc *fp;
1744 int locked;
1745 {
1746 struct filedesc *fdp = p->p_fd;
1747
1748 if (!locked)
1749 proc_fdlock(p);
1750 if ((fp == FILEPROC_NULL) && (fd < 0 || fd >= fdp->fd_nfiles ||
1751 (fp = fdp->fd_ofiles[fd]) == NULL ||
1752 ((fdp->fd_ofileflags[fd] & UF_RESERVED) &&
1753 !(fdp->fd_ofileflags[fd] & UF_CLOSING)))) {
1754 if (!locked)
1755 proc_fdunlock(p);
1756 return (EBADF);
1757 }
1758 fp->f_iocount--;
1759
1760 if (p->p_fpdrainwait && fp->f_iocount == 0) {
1761 p->p_fpdrainwait = 0;
1762 wakeup(&p->p_fpdrainwait);
1763 }
1764 if (!locked)
1765 proc_fdunlock(p);
1766
1767 return (0);
1768 }
1769
1770 int
1771 file_vnode(int fd, struct vnode **vpp)
1772 {
1773 struct proc * p = current_proc();
1774 struct fileproc *fp;
1775 int error;
1776
1777 proc_fdlock(p);
1778 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
1779 proc_fdunlock(p);
1780 return(error);
1781 }
1782 if (fp->f_type != DTYPE_VNODE) {
1783 fp_drop(p, fd, fp,1);
1784 proc_fdunlock(p);
1785 return(EINVAL);
1786 }
1787 *vpp = (struct vnode *)fp->f_data;
1788 proc_fdunlock(p);
1789
1790 return(0);
1791 }
1792
1793
1794 int
1795 file_socket(int fd, struct socket **sp)
1796 {
1797 struct proc * p = current_proc();
1798 struct fileproc *fp;
1799 int error;
1800
1801 proc_fdlock(p);
1802 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
1803 proc_fdunlock(p);
1804 return(error);
1805 }
1806 if (fp->f_type != DTYPE_SOCKET) {
1807 fp_drop(p, fd, fp,1);
1808 proc_fdunlock(p);
1809 return(ENOTSOCK);
1810 }
1811 *sp = (struct socket *)fp->f_data;
1812 proc_fdunlock(p);
1813
1814 return(0);
1815 }
1816
1817 int
1818 file_flags(int fd, int * flags)
1819 {
1820
1821 struct proc * p = current_proc();
1822 struct fileproc *fp;
1823 int error;
1824
1825 proc_fdlock(p);
1826 if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
1827 proc_fdunlock(p);
1828 return(error);
1829 }
1830 *flags = (int)fp->f_flag;
1831 fp_drop(p, fd, fp,1);
1832 proc_fdunlock(p);
1833
1834 return(0);
1835 }
1836
1837
1838 int
1839 file_drop(int fd)
1840 {
1841 struct fileproc *fp;
1842 struct proc *p = current_proc();
1843
1844 proc_fdlock(p);
1845 if (fd < 0 || fd >= p->p_fd->fd_nfiles ||
1846 (fp = p->p_fd->fd_ofiles[fd]) == NULL ||
1847 ((p->p_fd->fd_ofileflags[fd] & UF_RESERVED) &&
1848 !(p->p_fd->fd_ofileflags[fd] & UF_CLOSING))) {
1849 proc_fdunlock(p);
1850 return (EBADF);
1851 }
1852 fp->f_iocount --;
1853
1854 if (p->p_fpdrainwait && fp->f_iocount == 0) {
1855 p->p_fpdrainwait = 0;
1856 wakeup(&p->p_fpdrainwait);
1857 }
1858 proc_fdunlock(p);
1859 return(0);
1860
1861
1862 }
1863
1864 int
1865 falloc(p, resultfp, resultfd )
1866 struct proc *p;
1867 struct fileproc **resultfp;
1868 int *resultfd;
1869 {
1870 int error;
1871
1872 proc_fdlock(p);
1873 error = falloc_locked(p, resultfp, resultfd, 1);
1874 proc_fdunlock(p);
1875
1876 return(error);
1877 }
1878 /*
1879 * Create a new open file structure and allocate
1880 * a file decriptor for the process that refers to it.
1881 */
1882 int
1883 falloc_locked(p, resultfp, resultfd, locked)
1884 struct proc *p;
1885 struct fileproc **resultfp;
1886 int *resultfd;
1887 int locked;
1888 {
1889 struct fileproc *fp, *fq;
1890 struct fileglob *fg;
1891 int error, nfd;
1892
1893 if (!locked)
1894 proc_fdlock(p);
1895 if ( (error = fdalloc(p, 0, &nfd)) ) {
1896 if (!locked)
1897 proc_fdunlock(p);
1898 return (error);
1899 }
1900 if (nfiles >= maxfiles) {
1901 if (!locked)
1902 proc_fdunlock(p);
1903 tablefull("file");
1904 return (ENFILE);
1905 }
1906 /*
1907 * Allocate a new file descriptor.
1908 * If the process has file descriptor zero open, add to the list
1909 * of open files at that point, otherwise put it at the front of
1910 * the list of open files.
1911 */
1912 proc_fdunlock(p);
1913
1914 MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
1915 MALLOC_ZONE(fg, struct fileglob *, sizeof(struct fileglob), M_FILEGLOB, M_WAITOK);
1916 bzero(fp, sizeof(struct fileproc));
1917 bzero(fg, sizeof(struct fileglob));
1918 lck_mtx_init(&fg->fg_lock, file_lck_grp, file_lck_attr);
1919
1920 fp->f_iocount = 1;
1921 fg->fg_count = 1;
1922 fp->f_fglob = fg;
1923
1924 proc_fdlock(p);
1925
1926 fp->f_cred = kauth_cred_proc_ref(p);
1927
1928 lck_mtx_lock(file_flist_lock);
1929
1930 nfiles++;
1931
1932 if ( (fq = p->p_fd->fd_ofiles[0]) ) {
1933 LIST_INSERT_AFTER(fq->f_fglob, fg, f_list);
1934 } else {
1935 LIST_INSERT_HEAD(&filehead, fg, f_list);
1936 }
1937 lck_mtx_unlock(file_flist_lock);
1938
1939 p->p_fd->fd_ofiles[nfd] = fp;
1940
1941 if (!locked)
1942 proc_fdunlock(p);
1943
1944 if (resultfp)
1945 *resultfp = fp;
1946 if (resultfd)
1947 *resultfd = nfd;
1948
1949 return (0);
1950 }
1951
1952 /*
1953 * Free a file structure.
1954 */
1955 void
1956 fg_free(fg)
1957 struct fileglob *fg;
1958 {
1959 kauth_cred_t cred;
1960
1961 lck_mtx_lock(file_flist_lock);
1962 LIST_REMOVE(fg, f_list);
1963 nfiles--;
1964 lck_mtx_unlock(file_flist_lock);
1965
1966 cred = fg->fg_cred;
1967 if (cred != NOCRED) {
1968 fg->fg_cred = NOCRED;
1969 kauth_cred_rele(cred);
1970 }
1971 lck_mtx_destroy(&fg->fg_lock, file_lck_grp);
1972
1973 FREE_ZONE(fg, sizeof *fg, M_FILEGLOB);
1974 }
1975
1976 void
1977 fdexec(p)
1978 struct proc *p;
1979 {
1980 struct filedesc *fdp = p->p_fd;
1981 int i = fdp->fd_lastfile;
1982 struct fileproc *fp;
1983 int funnel_state;
1984
1985 funnel_state = thread_funnel_set(kernel_flock, FALSE);
1986 proc_fdlock(p);
1987
1988 while (i >= 0) {
1989 fp = fdp->fd_ofiles[i];
1990 if ((fdp->fd_ofileflags[i] & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE) {
1991
1992 if (i < fdp->fd_knlistsize)
1993 knote_fdclose(p, i);
1994
1995 procfdtbl_clearfd(p, i);
1996 if (i == fdp->fd_lastfile && i > 0)
1997 fdp->fd_lastfile--;
1998 if (i < fdp->fd_freefile)
1999 fdp->fd_freefile = i;
2000 closef_locked(fp, fp->f_fglob, p);
2001 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
2002 }
2003
2004 i--;
2005 }
2006 proc_fdunlock(p);
2007 thread_funnel_set(kernel_flock, funnel_state);
2008 }
2009
2010 /*
2011 * Copy a filedesc structure.
2012 */
2013 struct filedesc *
2014 fdcopy(p)
2015 struct proc *p;
2016 {
2017 struct filedesc *newfdp, *fdp = p->p_fd;
2018 int i;
2019 struct fileproc *ofp, *fp;
2020 vnode_t v_dir;
2021
2022 MALLOC_ZONE(newfdp, struct filedesc *,
2023 sizeof(*newfdp), M_FILEDESC, M_WAITOK);
2024 if (newfdp == NULL)
2025 return(NULL);
2026
2027 proc_fdlock(p);
2028
2029 /*
2030 * the FD_CHROOT flag will be inherited via this copy
2031 */
2032 (void) memcpy(newfdp, fdp, sizeof(*newfdp));
2033
2034 /*
2035 * for both fd_cdir and fd_rdir make sure we get
2036 * a valid reference... if we can't, than set
2037 * set the pointer(s) to NULL in the child... this
2038 * will keep us from using a non-referenced vp
2039 * and allows us to do the vnode_rele only on
2040 * a properly referenced vp
2041 */
2042 if ( (v_dir = newfdp->fd_cdir) ) {
2043 if (vnode_getwithref(v_dir) == 0) {
2044 if ( (vnode_ref(v_dir)) )
2045 newfdp->fd_cdir = NULL;
2046 vnode_put(v_dir);
2047 } else
2048 newfdp->fd_cdir = NULL;
2049 }
2050 if (newfdp->fd_cdir == NULL && fdp->fd_cdir) {
2051 /*
2052 * we couldn't get a new reference on
2053 * the current working directory being
2054 * inherited... we might as well drop
2055 * our reference from the parent also
2056 * since the vnode has gone DEAD making
2057 * it useless... by dropping it we'll
2058 * be that much closer to recyling it
2059 */
2060 vnode_rele(fdp->fd_cdir);
2061 fdp->fd_cdir = NULL;
2062 }
2063
2064 if ( (v_dir = newfdp->fd_rdir) ) {
2065 if (vnode_getwithref(v_dir) == 0) {
2066 if ( (vnode_ref(v_dir)) )
2067 newfdp->fd_rdir = NULL;
2068 vnode_put(v_dir);
2069 } else
2070 newfdp->fd_rdir = NULL;
2071 }
2072 if (newfdp->fd_rdir == NULL && fdp->fd_rdir) {
2073 /*
2074 * we couldn't get a new reference on
2075 * the root directory being
2076 * inherited... we might as well drop
2077 * our reference from the parent also
2078 * since the vnode has gone DEAD making
2079 * it useless... by dropping it we'll
2080 * be that much closer to recyling it
2081 */
2082 vnode_rele(fdp->fd_rdir);
2083 fdp->fd_rdir = NULL;
2084 }
2085 newfdp->fd_refcnt = 1;
2086
2087 /*
2088 * If the number of open files fits in the internal arrays
2089 * of the open file structure, use them, otherwise allocate
2090 * additional memory for the number of descriptors currently
2091 * in use.
2092 */
2093 if (newfdp->fd_lastfile < NDFILE)
2094 i = NDFILE;
2095 else {
2096 /*
2097 * Compute the smallest multiple of NDEXTENT needed
2098 * for the file descriptors currently in use,
2099 * allowing the table to shrink.
2100 */
2101 i = newfdp->fd_nfiles;
2102 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
2103 i /= 2;
2104 }
2105 proc_fdunlock(p);
2106
2107 MALLOC_ZONE(newfdp->fd_ofiles, struct fileproc **,
2108 i * OFILESIZE, M_OFILETABL, M_WAITOK);
2109 if (newfdp->fd_ofiles == NULL) {
2110 if (newfdp->fd_cdir)
2111 vnode_rele(newfdp->fd_cdir);
2112 if (newfdp->fd_rdir)
2113 vnode_rele(newfdp->fd_rdir);
2114
2115 FREE_ZONE(newfdp, sizeof *newfdp, M_FILEDESC);
2116 return(NULL);
2117 }
2118 (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
2119 proc_fdlock(p);
2120
2121 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
2122 newfdp->fd_nfiles = i;
2123
2124 if (fdp->fd_nfiles > 0) {
2125 struct fileproc **fpp;
2126 char *flags;
2127
2128 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
2129 (newfdp->fd_lastfile + 1) * sizeof *fdp->fd_ofiles);
2130 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
2131 (newfdp->fd_lastfile + 1) * sizeof *fdp->fd_ofileflags);
2132
2133 /*
2134 * kq descriptors cannot be copied.
2135 */
2136 if (newfdp->fd_knlistsize != -1) {
2137 fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
2138 for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
2139 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
2140 *fpp = NULL;
2141 if (i < newfdp->fd_freefile)
2142 newfdp->fd_freefile = i;
2143 }
2144 if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
2145 newfdp->fd_lastfile--;
2146 }
2147 newfdp->fd_knlist = NULL;
2148 newfdp->fd_knlistsize = -1;
2149 newfdp->fd_knhash = NULL;
2150 newfdp->fd_knhashmask = 0;
2151 }
2152 fpp = newfdp->fd_ofiles;
2153 flags = newfdp->fd_ofileflags;
2154
2155 for (i = newfdp->fd_lastfile + 1; --i >= 0; fpp++, flags++)
2156 if ((ofp = *fpp) != NULL && !(*flags & UF_RESERVED)) {
2157 MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
2158 bzero(fp, sizeof(struct fileproc));
2159 fp->f_flags = ofp->f_flags;
2160 //fp->f_iocount = ofp->f_iocount;
2161 fp->f_iocount = 0;
2162 fp->f_fglob = ofp->f_fglob;
2163 (void)fg_ref(fp);
2164 *fpp = fp;
2165 } else {
2166 if (i < newfdp->fd_freefile)
2167 newfdp->fd_freefile = i;
2168 *fpp = NULL;
2169 *flags = 0;
2170 }
2171 }
2172
2173 proc_fdunlock(p);
2174 return (newfdp);
2175 }
2176
2177 /*
2178 * Release a filedesc structure.
2179 */
2180 void
2181 fdfree(p)
2182 struct proc *p;
2183 {
2184 struct filedesc *fdp;
2185 struct fileproc *fp;
2186 int i;
2187
2188 proc_fdlock(p);
2189
2190 /* Certain daemons might not have file descriptors */
2191 fdp = p->p_fd;
2192
2193 if ((fdp == NULL) || (--fdp->fd_refcnt > 0)) {
2194 proc_fdunlock(p);
2195 return;
2196 }
2197 if (fdp->fd_refcnt == 0xffff)
2198 panic("fdfree: bad fd_refcnt");
2199
2200 /* Last reference: the structure can't change out from under us */
2201
2202 if (fdp->fd_nfiles > 0 && fdp->fd_ofiles) {
2203 for (i = fdp->fd_lastfile; i >= 0; i--) {
2204 if ((fp = fdp->fd_ofiles[i]) != NULL) {
2205
2206 if (fdp->fd_ofileflags[i] & UF_RESERVED)
2207 panic("fdfree: found fp with UF_RESERVED\n");
2208
2209 /* closef drops the iocount ... */
2210 if ((fp->f_flags & FP_INCHRREAD) != 0)
2211 fp->f_iocount++;
2212 procfdtbl_reservefd(p, i);
2213
2214 if (i < fdp->fd_knlistsize)
2215 knote_fdclose(p, i);
2216 if (fp->f_flags & FP_WAITEVENT)
2217 (void)waitevent_close(p, fp);
2218 (void) closef_locked(fp, fp->f_fglob, p);
2219 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
2220 }
2221 }
2222 FREE_ZONE(fdp->fd_ofiles, fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
2223 fdp->fd_ofiles = NULL;
2224 fdp->fd_nfiles = 0;
2225 }
2226
2227 proc_fdunlock(p);
2228
2229 if (fdp->fd_cdir)
2230 vnode_rele(fdp->fd_cdir);
2231 if (fdp->fd_rdir)
2232 vnode_rele(fdp->fd_rdir);
2233
2234 proc_fdlock(p);
2235 p->p_fd = NULL;
2236 proc_fdunlock(p);
2237
2238 if (fdp->fd_knlist)
2239 FREE(fdp->fd_knlist, M_KQUEUE);
2240 if (fdp->fd_knhash)
2241 FREE(fdp->fd_knhash, M_KQUEUE);
2242
2243 FREE_ZONE(fdp, sizeof *fdp, M_FILEDESC);
2244 }
2245
2246 static int
2247 closef_finish(fp, fg, p)
2248 struct fileproc *fp;
2249 struct fileglob *fg;
2250 struct proc *p;
2251 {
2252 struct vnode *vp;
2253 struct flock lf;
2254 int error;
2255 struct vfs_context context;
2256
2257 if ((fg->fg_flag & FHASLOCK) && fg->fg_type == DTYPE_VNODE) {
2258 lf.l_whence = SEEK_SET;
2259 lf.l_start = 0;
2260 lf.l_len = 0;
2261 lf.l_type = F_UNLCK;
2262 vp = (struct vnode *)fg->fg_data;
2263 context.vc_proc = p;
2264 context.vc_ucred = fg->fg_cred;
2265
2266 (void) VNOP_ADVLOCK(vp, (caddr_t)fg, F_UNLCK, &lf, F_FLOCK, &context);
2267 }
2268 if (fg->fg_ops)
2269 error = fo_close(fg, p);
2270 else
2271 error = 0;
2272
2273 if (((fp != (struct fileproc *)0) && ((fp->f_flags & FP_INCHRREAD) != 0))) {
2274 proc_fdlock(p);
2275 if ( ((fp->f_flags & FP_INCHRREAD) != 0) ) {
2276 fileproc_drain(p, fp);
2277 }
2278 proc_fdunlock(p);
2279 }
2280 fg_free(fg);
2281
2282 return (error);
2283 }
2284
2285 int
2286 closef(fg, p)
2287 struct fileglob *fg;
2288 struct proc *p;
2289 {
2290 int error;
2291
2292 proc_fdlock(p);
2293 error = closef_locked((struct fileproc *)0, fg, p);
2294 proc_fdunlock(p);
2295
2296 return(error);
2297 }
2298 /*
2299 * Internal form of close.
2300 * Decrement reference count on file structure.
2301 * Note: p may be NULL when closing a file
2302 * that was being passed in a message.
2303 */
2304 int
2305 closef_locked(fp, fg, p)
2306 struct fileproc *fp;
2307 struct fileglob *fg;
2308 struct proc *p;
2309 {
2310 struct vnode *vp;
2311 struct flock lf;
2312 struct vfs_context context;
2313 int error;
2314
2315 if (fg == NULL) {
2316 return (0);
2317 }
2318 /*
2319 * POSIX record locking dictates that any close releases ALL
2320 * locks owned by this process. This is handled by setting
2321 * a flag in the unlock to free ONLY locks obeying POSIX
2322 * semantics, and not to free BSD-style file locks.
2323 * If the descriptor was in a message, POSIX-style locks
2324 * aren't passed with the descriptor.
2325 */
2326 if (p && (p->p_ladvflag & P_LADVLOCK) && fg->fg_type == DTYPE_VNODE) {
2327 proc_fdunlock(p);
2328
2329 lf.l_whence = SEEK_SET;
2330 lf.l_start = 0;
2331 lf.l_len = 0;
2332 lf.l_type = F_UNLCK;
2333 vp = (struct vnode *)fg->fg_data;
2334
2335 if ( (error = vnode_getwithref(vp)) == 0 ) {
2336 context.vc_proc = p;
2337 context.vc_ucred = fg->fg_cred;
2338 (void) VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX, &context);
2339
2340 (void)vnode_put(vp);
2341 }
2342 proc_fdlock(p);
2343 }
2344 lck_mtx_lock(&fg->fg_lock);
2345 fg->fg_count--;
2346
2347 if (fg->fg_count > 0) {
2348 lck_mtx_unlock(&fg->fg_lock);
2349 return (0);
2350 }
2351 if (fg->fg_count != 0)
2352 panic("fg: being freed with bad fg_count (%d)", fg, fg->fg_count);
2353
2354 if (fp && (fp->f_flags & FP_WRITTEN))
2355 fg->fg_flag |= FWASWRITTEN;
2356
2357 fg->fg_lflags |= FG_TERM;
2358 lck_mtx_unlock(&fg->fg_lock);
2359
2360 proc_fdunlock(p);
2361 error = closef_finish(fp, fg, p);
2362 proc_fdlock(p);
2363
2364 return(error);
2365 }
2366
2367
2368 extern int selwait;
2369 void
2370 fileproc_drain(struct proc *p, struct fileproc * fp)
2371 {
2372 fp->f_iocount-- ; /* (the one the close holds) */
2373
2374 while (fp->f_iocount) {
2375 if (((fp->f_flags & FP_INSELECT)== FP_INSELECT)) {
2376 wait_queue_wakeup_all((wait_queue_t)fp->f_waddr, &selwait, THREAD_INTERRUPTED);
2377 } else {
2378 if (fp->f_fglob->fg_ops->fo_drain) {
2379 (*fp->f_fglob->fg_ops->fo_drain)(fp, p);
2380 }
2381 }
2382 p->p_fpdrainwait = 1;
2383
2384 msleep(&p->p_fpdrainwait, &p->p_fdmlock, PRIBIO, "fpdrain",0);
2385
2386 //panic("successful wait after drain\n");
2387 }
2388 }
2389
2390 int
2391 fp_free(struct proc * p, int fd, struct fileproc * fp)
2392 {
2393 proc_fdlock(p);
2394 fdrelse(p, fd);
2395 proc_fdunlock(p);
2396
2397 fg_free(fp->f_fglob);
2398 FREE_ZONE(fp, sizeof *fp, M_FILEPROC);
2399 }
2400
2401
2402 /*
2403 * Apply an advisory lock on a file descriptor.
2404 *
2405 * Just attempt to get a record lock of the requested type on
2406 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
2407 */
2408 int
2409 flock(struct proc *p, register struct flock_args *uap, __unused register_t *retval)
2410 {
2411 int fd = uap->fd;
2412 int how = uap->how;
2413 struct fileproc *fp;
2414 struct vnode *vp;
2415 struct flock lf;
2416 struct vfs_context context;
2417 int error=0;
2418
2419 AUDIT_ARG(fd, uap->fd);
2420 if ( (error = fp_getfvp(p, fd, &fp, &vp)) ) {
2421 return(error);
2422 }
2423 if ( (error = vnode_getwithref(vp)) ) {
2424 goto out1;
2425 }
2426 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
2427
2428 context.vc_proc = p;
2429 context.vc_ucred = fp->f_cred;
2430
2431 lf.l_whence = SEEK_SET;
2432 lf.l_start = 0;
2433 lf.l_len = 0;
2434 if (how & LOCK_UN) {
2435 lf.l_type = F_UNLCK;
2436 fp->f_flag &= ~FHASLOCK;
2437 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_UNLCK, &lf, F_FLOCK, &context);
2438 goto out;
2439 }
2440 if (how & LOCK_EX)
2441 lf.l_type = F_WRLCK;
2442 else if (how & LOCK_SH)
2443 lf.l_type = F_RDLCK;
2444 else {
2445 error = EBADF;
2446 goto out;
2447 }
2448 fp->f_flag |= FHASLOCK;
2449 if (how & LOCK_NB) {
2450 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK, &context);
2451 goto out;
2452 }
2453 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK|F_WAIT, &context);
2454 out:
2455 (void)vnode_put(vp);
2456 out1:
2457 fp_drop(p, fd, fp, 0);
2458 return(error);
2459
2460 }
2461
2462 /*
2463 * File Descriptor pseudo-device driver (/dev/fd/).
2464 *
2465 * Opening minor device N dup()s the file (if any) connected to file
2466 * descriptor N belonging to the calling process. Note that this driver
2467 * consists of only the ``open()'' routine, because all subsequent
2468 * references to this file will be direct to the other driver.
2469 */
2470 int
2471 fdopen(dev_t dev, __unused int mode, __unused int type, struct proc *p)
2472 {
2473
2474 /*
2475 * XXX Kludge: set curproc->p_dupfd to contain the value of the
2476 * the file descriptor being sought for duplication. The error
2477 * return ensures that the vnode for this device will be released
2478 * by vn_open. Open will detect this special error and take the
2479 * actions in dupfdopen below. Other callers of vn_open or vnop_open
2480 * will simply report the error.
2481 */
2482 p->p_dupfd = minor(dev);
2483 return (ENODEV);
2484 }
2485
2486 /*
2487 * Duplicate the specified descriptor to a free descriptor.
2488 */
2489 int
2490 dupfdopen(fdp, indx, dfd, mode, error)
2491 register struct filedesc *fdp;
2492 register int indx, dfd;
2493 int mode;
2494 int error;
2495 {
2496 struct fileproc *wfp;
2497 struct fileproc *fp;
2498 struct proc * p = current_proc();
2499
2500 /*
2501 * If the to-be-dup'd fd number is greater than the allowed number
2502 * of file descriptors, or the fd to be dup'd has already been
2503 * closed, reject. Note, check for new == old is necessary as
2504 * falloc could allocate an already closed to-be-dup'd descriptor
2505 * as the new descriptor.
2506 */
2507 proc_fdlock(p);
2508
2509 fp = fdp->fd_ofiles[indx];
2510 if (dfd < 0 || dfd >= fdp->fd_nfiles ||
2511 (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
2512 (fdp->fd_ofileflags[dfd] & UF_RESERVED)) {
2513
2514 proc_fdunlock(p);
2515 return (EBADF);
2516 }
2517 /*
2518 * There are two cases of interest here.
2519 *
2520 * For ENODEV simply dup (dfd) to file descriptor
2521 * (indx) and return.
2522 *
2523 * For ENXIO steal away the file structure from (dfd) and
2524 * store it in (indx). (dfd) is effectively closed by
2525 * this operation.
2526 *
2527 * Any other error code is just returned.
2528 */
2529 switch (error) {
2530 case ENODEV:
2531 /*
2532 * Check that the mode the file is being opened for is a
2533 * subset of the mode of the existing descriptor.
2534 */
2535 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
2536 proc_fdunlock(p);
2537 return (EACCES);
2538 }
2539 if (indx > fdp->fd_lastfile)
2540 fdp->fd_lastfile = indx;
2541 (void)fg_ref(wfp);
2542
2543 if (fp->f_fglob)
2544 fg_free(fp->f_fglob);
2545 fp->f_fglob = wfp->f_fglob;
2546
2547 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
2548
2549 proc_fdunlock(p);
2550 return (0);
2551
2552 default:
2553 proc_fdunlock(p);
2554 return (error);
2555 }
2556 /* NOTREACHED */
2557 }
2558
2559 void
2560 fg_ref(struct fileproc * fp)
2561 {
2562 struct fileglob *fg;
2563
2564 fg = fp->f_fglob;
2565
2566 lck_mtx_lock(&fg->fg_lock);
2567 fg->fg_count++;
2568 lck_mtx_unlock(&fg->fg_lock);
2569 }
2570
2571 void
2572 fg_drop(struct fileproc * fp)
2573 {
2574 struct fileglob *fg;
2575
2576 fg = fp->f_fglob;
2577 lck_mtx_lock(&fg->fg_lock);
2578 fg->fg_count--;
2579 lck_mtx_unlock(&fg->fg_lock);
2580 }
2581
2582
2583 void
2584 fg_insertuipc(struct fileglob * fg)
2585 {
2586 int insertque = 0;
2587
2588 lck_mtx_lock(&fg->fg_lock);
2589
2590 while (fg->fg_lflags & FG_RMMSGQ) {
2591 fg->fg_lflags |= FG_WRMMSGQ;
2592 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_insertuipc", 0);
2593 }
2594
2595 fg->fg_count++;
2596 fg->fg_msgcount++;
2597 if (fg->fg_msgcount == 1) {
2598 fg->fg_lflags |= FG_INSMSGQ;
2599 insertque=1;
2600 }
2601 lck_mtx_unlock(&fg->fg_lock);
2602
2603 if (insertque) {
2604 lck_mtx_lock(uipc_lock);
2605 unp_gc_wait();
2606 LIST_INSERT_HEAD(&fmsghead, fg, f_msglist);
2607 lck_mtx_unlock(uipc_lock);
2608 lck_mtx_lock(&fg->fg_lock);
2609 fg->fg_lflags &= ~FG_INSMSGQ;
2610 if (fg->fg_lflags & FG_WINSMSGQ) {
2611 fg->fg_lflags &= ~FG_WINSMSGQ;
2612 wakeup(&fg->fg_lflags);
2613 }
2614 lck_mtx_unlock(&fg->fg_lock);
2615 }
2616
2617 }
2618
2619 void
2620 fg_removeuipc(struct fileglob * fg)
2621 {
2622 int removeque = 0;
2623
2624 lck_mtx_lock(&fg->fg_lock);
2625 while (fg->fg_lflags & FG_INSMSGQ) {
2626 fg->fg_lflags |= FG_WINSMSGQ;
2627 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_removeuipc", 0);
2628 }
2629 fg->fg_msgcount--;
2630 if (fg->fg_msgcount == 0) {
2631 fg->fg_lflags |= FG_RMMSGQ;
2632 removeque=1;
2633 }
2634 lck_mtx_unlock(&fg->fg_lock);
2635
2636 if (removeque) {
2637 lck_mtx_lock(uipc_lock);
2638 unp_gc_wait();
2639 LIST_REMOVE(fg, f_msglist);
2640 lck_mtx_unlock(uipc_lock);
2641 lck_mtx_lock(&fg->fg_lock);
2642 fg->fg_lflags &= ~FG_RMMSGQ;
2643 if (fg->fg_lflags & FG_WRMMSGQ) {
2644 fg->fg_lflags &= ~FG_WRMMSGQ;
2645 wakeup(&fg->fg_lflags);
2646 }
2647 lck_mtx_unlock(&fg->fg_lock);
2648 }
2649 }
2650
2651
2652 int
2653 fo_read(struct fileproc *fp, struct uio *uio, kauth_cred_t cred, int flags, struct proc *p)
2654 {
2655 return ((*fp->f_ops->fo_read)(fp, uio, cred, flags, p));
2656 }
2657
2658 int
2659 fo_write(struct fileproc *fp, struct uio *uio, kauth_cred_t cred, int flags, struct proc *p)
2660 {
2661 return((*fp->f_ops->fo_write)(fp, uio, cred, flags, p));
2662 }
2663
2664 int
2665 fo_ioctl(struct fileproc *fp, u_long com, caddr_t data, struct proc *p)
2666 {
2667 int error;
2668
2669 proc_fdunlock(p);
2670 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
2671 proc_fdlock(p);
2672 return(error);
2673 }
2674
2675 int
2676 fo_select(struct fileproc *fp, int which, void *wql, struct proc *p)
2677 {
2678 return((*fp->f_ops->fo_select)(fp, which, wql, p));
2679 }
2680
2681 int
2682 fo_close(struct fileglob *fg, struct proc *p)
2683 {
2684 return((*fg->fg_ops->fo_close)(fg, p));
2685 }
2686
2687 int
2688 fo_kqfilter(struct fileproc *fp, struct knote *kn, struct proc *p)
2689 {
2690 return ((*fp->f_ops->fo_kqfilter)(fp, kn, p));
2691 }
2692