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