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