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