2 * Copyright (c) 2015-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/filedesc.h>
32 #include <sys/kernel.h>
33 #include <sys/file_internal.h>
34 #include <sys/guarded.h>
35 #include <kern/kalloc.h>
36 #include <sys/sysproto.h>
37 #include <sys/vnode.h>
38 #include <sys/vnode_internal.h>
39 #include <sys/uio_internal.h>
40 #include <sys/ubc_internal.h>
41 #include <vfs/vfs_support.h>
42 #include <security/audit/audit.h>
43 #include <sys/syscall.h>
44 #include <sys/kauth.h>
45 #include <sys/kdebug.h>
47 #include <vm/vm_protos.h>
50 #define f_flag f_fglob->fg_flag
51 #define f_type f_fglob->fg_ops->fo_type
52 extern int dofilewrite(vfs_context_t ctx
, struct fileproc
*fp
,
53 user_addr_t bufp
, user_size_t nbyte
, off_t offset
,
54 int flags
, user_ssize_t
*retval
);
55 extern int wr_uio(struct proc
*p
, struct fileproc
*fp
, uio_t uio
, user_ssize_t
*retval
);
58 * Experimental guarded file descriptor support.
61 kern_return_t
task_exception_notify(exception_type_t exception
,
62 mach_exception_data_type_t code
, mach_exception_data_type_t subcode
);
65 * Most fd's have an underlying fileproc struct; but some may be
66 * guarded_fileproc structs which implement guarded fds. The latter
67 * struct (below) embeds the former.
69 * The two types should be distinguished by the "type" portion of f_flags.
70 * There's also a magic number to help catch misuse and bugs.
72 * This is a bit unpleasant, but results from the desire to allow
73 * alternate file behaviours for a few file descriptors without
74 * growing the fileproc data structure.
77 struct guarded_fileproc
{
78 struct fileproc gf_fileproc
;
87 const size_t sizeof_guarded_fileproc
= sizeof (struct guarded_fileproc
);
89 #define FP_TO_GFP(fp) ((struct guarded_fileproc *)(fp))
90 #define GFP_TO_FP(gfp) (&(gfp)->gf_fileproc)
92 #define GUARDED_FILEPROC_MAGIC 0x29083
99 static struct fileproc
*
100 guarded_fileproc_alloc_init(void *crarg
)
102 struct gfp_crarg
*aarg
= crarg
;
103 struct guarded_fileproc
*gfp
;
105 if ((gfp
= kalloc(sizeof (*gfp
))) == NULL
)
108 bzero(gfp
, sizeof (*gfp
));
109 gfp
->gf_fileproc
.f_flags
= FTYPE_GUARDED
;
110 gfp
->gf_magic
= GUARDED_FILEPROC_MAGIC
;
111 gfp
->gf_guard
= aarg
->gca_guard
;
112 gfp
->gf_attrs
= aarg
->gca_attrs
;
114 return (GFP_TO_FP(gfp
));
118 guarded_fileproc_free(struct fileproc
*fp
)
120 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
122 if (FILEPROC_TYPE(fp
) != FTYPE_GUARDED
||
123 GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
124 panic("%s: corrupt fp %p flags %x", __func__
, fp
, fp
->f_flags
);
126 kfree(gfp
, sizeof (*gfp
));
130 fp_lookup_guarded(proc_t p
, int fd
, guardid_t guard
,
131 struct guarded_fileproc
**gfpp
, int locked
)
136 if ((error
= fp_lookup(p
, fd
, &fp
, locked
)) != 0)
138 if (FILEPROC_TYPE(fp
) != FTYPE_GUARDED
) {
139 (void) fp_drop(p
, fd
, fp
, locked
);
142 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
144 if (GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
145 panic("%s: corrupt fp %p", __func__
, fp
);
147 if (guard
!= gfp
->gf_guard
) {
148 (void) fp_drop(p
, fd
, fp
, locked
);
149 return (EPERM
); /* *not* a mismatch exception */
157 * Expected use pattern:
159 * if (FP_ISGUARDED(fp, GUARD_CLOSE)) {
160 * error = fp_guard_exception(p, fd, fp, kGUARD_EXC_CLOSE);
167 fp_isguarded(struct fileproc
*fp
, u_int attrs
)
169 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
170 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
172 if (GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
173 panic("%s: corrupt gfp %p flags %x",
174 __func__
, gfp
, fp
->f_flags
);
175 return ((attrs
& gfp
->gf_attrs
) == attrs
);
180 extern char *proc_name_address(void *p
);
183 fp_guard_exception(proc_t p
, int fd
, struct fileproc
*fp
, u_int code
)
185 if (FILEPROC_TYPE(fp
) != FTYPE_GUARDED
)
186 panic("%s corrupt fp %p flags %x", __func__
, fp
, fp
->f_flags
);
188 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
190 /* all gfd fields protected via proc_fdlock() */
191 proc_fdlock_assert(p
, LCK_MTX_ASSERT_OWNED
);
193 if (NULL
== gfp
->gf_thread
) {
194 thread_t t
= current_thread();
197 gfp
->gf_exc_code
= code
;
200 * This thread was the first to attempt the
201 * operation that violated the guard on this fd;
202 * generate an exception.
204 printf("%s: guarded fd exception: "
205 "fd %d code 0x%x guard 0x%llx\n",
206 proc_name_address(p
), gfp
->gf_exc_fd
,
207 gfp
->gf_exc_code
, gfp
->gf_guard
);
209 thread_guard_violation(t
, GUARD_TYPE_FD
);
212 * We already recorded a violation on this fd for a
213 * different thread, so posting an exception is
214 * already in progress. We could pause for a bit
215 * and check again, or we could panic (though that seems
216 * heavy handed), or we could just press on with the
217 * error return alone. For now, resort to printf.
219 printf("%s: guarded fd exception+: "
220 "fd %d code 0x%x guard 0x%llx\n",
221 proc_name_address(p
), gfp
->gf_exc_fd
,
222 gfp
->gf_exc_code
, gfp
->gf_guard
);
229 * (Invoked before returning to userland from the syscall handler.)
232 fd_guard_ast(thread_t t
)
234 proc_t p
= current_proc();
235 struct filedesc
*fdp
= p
->p_fd
;
239 for (i
= fdp
->fd_lastfile
; i
>= 0; i
--) {
240 struct fileproc
*fp
= fdp
->fd_ofiles
[i
];
243 FILEPROC_TYPE(fp
) != FTYPE_GUARDED
)
246 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
248 if (GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
249 panic("%s: corrupt gfp %p flags %x",
250 __func__
, gfp
, fp
->f_flags
);
252 if (gfp
->gf_thread
== t
) {
253 mach_exception_data_type_t code
, subcode
;
255 gfp
->gf_thread
= NULL
;
258 * EXC_GUARD exception code namespace.
261 * +-------------------------------------------------+
262 * | [63:61] guard type | [60:0] guard-specific data |
263 * +-------------------------------------------------+
266 * +-------------------------------------------------+
267 * | [63:0] guard-specific data |
268 * +-------------------------------------------------+
270 * At the moment, we have just one guard type: file
273 * File descriptor guards use the exception codes like
277 * +--------------------------------------------------+
278 * |[63:61] GUARD_TYPE_FD | [60:32] flavor | [31:0] fd|
279 * +--------------------------------------------------+
282 * +--------------------------------------------------+
283 * | [63:0] guard value |
284 * +--------------------------------------------------+
286 code
= (((uint64_t)GUARD_TYPE_FD
) << 61) |
287 (((uint64_t)gfp
->gf_exc_code
) << 32) |
288 ((uint64_t)gfp
->gf_exc_fd
);
289 subcode
= gfp
->gf_guard
;
292 (void) task_exception_notify(EXC_GUARD
, code
, subcode
);
302 * Experimental guarded file descriptor SPIs
306 * int guarded_open_np(const char *pathname, int flags,
307 * const guardid_t *guard, u_int guardflags, ...);
309 * In this initial implementation, GUARD_DUP must be specified.
310 * GUARD_CLOSE, GUARD_SOCKET_IPC and GUARD_FILEPORT are optional.
312 * If GUARD_DUP wasn't specified, then we'd have to do the (extra) work
313 * to allow dup-ing a descriptor to inherit the guard onto the new
314 * descriptor. (Perhaps GUARD_DUP behaviours should just always be true
315 * for a guarded fd? Or, more sanely, all the dup operations should
316 * just always propagate the guard?)
318 * Guarded descriptors are always close-on-exec, and GUARD_CLOSE
319 * requires close-on-fork; O_CLOEXEC must be set in flags.
320 * This setting is immutable; attempts to clear the flag will
321 * cause a guard exception.
323 * XXX It's somewhat broken that change_fdguard_np() can completely
324 * remove the guard and thus revoke down the immutability
325 * promises above. Ick.
328 guarded_open_np(proc_t p
, struct guarded_open_np_args
*uap
, int32_t *retval
)
330 if ((uap
->flags
& O_CLOEXEC
) == 0)
333 #define GUARD_REQUIRED (GUARD_DUP)
334 #define GUARD_ALL (GUARD_REQUIRED | \
335 (GUARD_CLOSE | GUARD_SOCKET_IPC | GUARD_FILEPORT | GUARD_WRITE))
337 if (((uap
->guardflags
& GUARD_REQUIRED
) != GUARD_REQUIRED
) ||
338 ((uap
->guardflags
& ~GUARD_ALL
) != 0))
342 struct gfp_crarg crarg
= {
343 .gca_attrs
= uap
->guardflags
346 if ((error
= copyin(uap
->guard
,
347 &(crarg
.gca_guard
), sizeof (crarg
.gca_guard
))) != 0)
351 * Disallow certain guard values -- is zero enough?
353 if (crarg
.gca_guard
== 0)
356 struct filedesc
*fdp
= p
->p_fd
;
357 struct vnode_attr va
;
359 vfs_context_t ctx
= vfs_context_current();
363 cmode
= ((uap
->mode
& ~fdp
->fd_cmask
) & ALLPERMS
) & ~S_ISTXT
;
364 VATTR_SET(&va
, va_mode
, cmode
& ACCESSPERMS
);
366 NDINIT(&nd
, LOOKUP
, OP_OPEN
, FOLLOW
| AUDITVNPATH1
, UIO_USERSPACE
,
369 return (open1(ctx
, &nd
, uap
->flags
| O_CLOFORK
, &va
,
370 guarded_fileproc_alloc_init
, &crarg
, retval
));
374 * int guarded_open_dprotected_np(const char *pathname, int flags,
375 * const guardid_t *guard, u_int guardflags, int dpclass, int dpflags, ...);
377 * This SPI is extension of guarded_open_np() to include dataprotection class on creation
378 * in "dpclass" and dataprotection flags 'dpflags'. Otherwise behaviors are same as in
382 guarded_open_dprotected_np(proc_t p
, struct guarded_open_dprotected_np_args
*uap
, int32_t *retval
)
384 if ((uap
->flags
& O_CLOEXEC
) == 0)
387 if (((uap
->guardflags
& GUARD_REQUIRED
) != GUARD_REQUIRED
) ||
388 ((uap
->guardflags
& ~GUARD_ALL
) != 0))
392 struct gfp_crarg crarg
= {
393 .gca_attrs
= uap
->guardflags
396 if ((error
= copyin(uap
->guard
,
397 &(crarg
.gca_guard
), sizeof (crarg
.gca_guard
))) != 0)
401 * Disallow certain guard values -- is zero enough?
403 if (crarg
.gca_guard
== 0)
406 struct filedesc
*fdp
= p
->p_fd
;
407 struct vnode_attr va
;
409 vfs_context_t ctx
= vfs_context_current();
413 cmode
= ((uap
->mode
& ~fdp
->fd_cmask
) & ALLPERMS
) & ~S_ISTXT
;
414 VATTR_SET(&va
, va_mode
, cmode
& ACCESSPERMS
);
416 NDINIT(&nd
, LOOKUP
, OP_OPEN
, FOLLOW
| AUDITVNPATH1
, UIO_USERSPACE
,
420 * Initialize the extra fields in vnode_attr to pass down dataprotection
422 * 1. target cprotect class.
423 * 2. set a flag to mark it as requiring open-raw-encrypted semantics.
425 if (uap
->flags
& O_CREAT
) {
426 VATTR_SET(&va
, va_dataprotect_class
, uap
->dpclass
);
429 if (uap
->dpflags
& (O_DP_GETRAWENCRYPTED
|O_DP_GETRAWUNENCRYPTED
)) {
430 if ( uap
->flags
& (O_RDWR
| O_WRONLY
)) {
431 /* Not allowed to write raw encrypted bytes */
434 if (uap
->dpflags
& O_DP_GETRAWENCRYPTED
) {
435 VATTR_SET(&va
, va_dataprotect_flags
, VA_DP_RAWENCRYPTED
);
437 if (uap
->dpflags
& O_DP_GETRAWUNENCRYPTED
) {
438 VATTR_SET(&va
, va_dataprotect_flags
, VA_DP_RAWUNENCRYPTED
);
442 return (open1(ctx
, &nd
, uap
->flags
| O_CLOFORK
, &va
,
443 guarded_fileproc_alloc_init
, &crarg
, retval
));
447 * int guarded_kqueue_np(const guardid_t *guard, u_int guardflags);
449 * Create a guarded kqueue descriptor with guardid and guardflags.
451 * Same restrictions on guardflags as for guarded_open_np().
452 * All kqueues are -always- close-on-exec and close-on-fork by themselves
453 * and are not sendable.
456 guarded_kqueue_np(proc_t p
, struct guarded_kqueue_np_args
*uap
, int32_t *retval
)
458 if (((uap
->guardflags
& GUARD_REQUIRED
) != GUARD_REQUIRED
) ||
459 ((uap
->guardflags
& ~GUARD_ALL
) != 0))
463 struct gfp_crarg crarg
= {
464 .gca_attrs
= uap
->guardflags
467 if ((error
= copyin(uap
->guard
,
468 &(crarg
.gca_guard
), sizeof (crarg
.gca_guard
))) != 0)
471 if (crarg
.gca_guard
== 0)
474 return (kqueue_body(p
, guarded_fileproc_alloc_init
, &crarg
, retval
));
478 * int guarded_close_np(int fd, const guardid_t *guard);
481 guarded_close_np(proc_t p
, struct guarded_close_np_args
*uap
,
482 __unused
int32_t *retval
)
484 struct guarded_fileproc
*gfp
;
489 AUDIT_SYSCLOSE(p
, fd
);
491 if ((error
= copyin(uap
->guard
, &uguard
, sizeof (uguard
))) != 0)
495 if ((error
= fp_lookup_guarded(p
, fd
, uguard
, &gfp
, 1)) != 0) {
499 error
= close_internal_locked(p
, fd
, GFP_TO_FP(gfp
), 0);
506 * change_fdguard_np(int fd, const guardid_t *guard, u_int guardflags,
507 * const guardid_t *nguard, u_int nguardflags, int *fdflagsp);
509 * Given a file descriptor, atomically exchange <guard, guardflags> for
510 * a new guard <nguard, nguardflags>, returning the previous fd
511 * flags (see fcntl:F_SETFD) in *fdflagsp.
513 * This syscall can be used to either (a) add a new guard to an existing
514 * unguarded file descriptor (b) remove the old guard from an existing
515 * guarded file descriptor or (c) change the guard (guardid and/or
516 * guardflags) on a guarded file descriptor.
518 * If 'guard' is NULL, fd must be unguarded at entry. If the call completes
519 * successfully the fd will be guarded with <nguard, nguardflags>.
521 * Guarding a file descriptor has some side-effects on the "fdflags"
522 * associated with the descriptor - in particular FD_CLOEXEC is
523 * forced ON unconditionally, and FD_CLOFORK is forced ON by GUARD_CLOSE.
524 * Callers who wish to subsequently restore the state of the fd should save
525 * the value of *fdflagsp after a successful invocation.
527 * If 'nguard' is NULL, fd must be guarded at entry, <guard, guardflags>
528 * must match with what's already guarding the descriptor, and the
529 * result will be to completely remove the guard. Note also that the
530 * fdflags are copied to the descriptor from the incoming *fdflagsp argument.
532 * If the descriptor is guarded, and neither 'guard' nor 'nguard' is NULL
533 * and <guard, guardflags> matches what's already guarding the descriptor,
534 * then <nguard, nguardflags> becomes the new guard. In this case, even if
535 * the GUARD_CLOSE flag is being cleared, it is still possible to continue
536 * to keep FD_CLOFORK on the descriptor by passing FD_CLOFORK via fdflagsp.
538 * (File descriptors whose underlying fileglobs are marked FG_CONFINED are
539 * still close-on-fork, regardless of the setting of FD_CLOFORK.)
541 * Example 1: Guard an unguarded descriptor during a set of operations,
542 * then restore the original state of the descriptor.
545 * change_fdguard_np(fd, NULL, 0, &myguard, GUARD_CLOSE, &sav_flags);
546 * // do things with now guarded 'fd'
547 * change_fdguard_np(fd, &myguard, GUARD_CLOSE, NULL, 0, &sav_flags);
548 * // fd now unguarded.
550 * Example 2: Change the guard of a guarded descriptor during a set of
551 * operations, then restore the original state of the descriptor.
553 * int sav_flags = (gdflags & GUARD_CLOSE) ? FD_CLOFORK : 0;
554 * change_fdguard_np(fd, &gd, gdflags, &myguard, GUARD_CLOSE, &sav_flags);
555 * // do things with 'fd' with a different guard
556 * change_fdguard_np(fd, &myg, GUARD_CLOSE, &gd, gdflags, &sav_flags);
557 * // back to original guarded state
559 * XXX This SPI is too much of a chainsaw and should be revised.
563 change_fdguard_np(proc_t p
, struct change_fdguard_np_args
*uap
,
564 __unused
int32_t *retval
)
569 guardid_t oldg
= 0, newg
= 0;
572 if (0 != uap
->guard
&&
573 0 != (error
= copyin(uap
->guard
, &oldg
, sizeof (oldg
))))
574 return (error
); /* can't copyin current guard */
576 if (0 != uap
->nguard
&&
577 0 != (error
= copyin(uap
->nguard
, &newg
, sizeof (newg
))))
578 return (error
); /* can't copyin new guard */
580 if (0 != uap
->fdflagsp
&&
581 0 != (error
= copyin(uap
->fdflagsp
, &nfdflags
, sizeof (nfdflags
))))
582 return (error
); /* can't copyin new fdflags */
586 if ((error
= fp_lookup(p
, fd
, &fp
, 1)) != 0) {
591 if (0 != uap
->fdflagsp
) {
592 int ofdflags
= FDFLAGS_GET(p
, fd
);
593 int ofl
= ((ofdflags
& UF_EXCLOSE
) ? FD_CLOEXEC
: 0) |
594 ((ofdflags
& UF_FORKCLOSE
) ? FD_CLOFORK
: 0);
596 if (0 != (error
= copyout(&ofl
, uap
->fdflagsp
, sizeof (ofl
)))) {
598 goto dropout
; /* can't copyout old fdflags */
603 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
604 if (0 == uap
->guard
|| 0 == uap
->guardflags
)
605 error
= EINVAL
; /* missing guard! */
607 error
= EPERM
; /* guardids cannot be zero */
609 if (0 != uap
->guard
|| 0 != uap
->guardflags
)
610 error
= EINVAL
; /* guard provided, but none needed! */
616 if (0 != uap
->nguard
) {
618 * There's a new guard in town.
621 error
= EINVAL
; /* guards cannot contain zero */
622 else if (((uap
->nguardflags
& GUARD_REQUIRED
) != GUARD_REQUIRED
) ||
623 ((uap
->nguardflags
& ~GUARD_ALL
) != 0))
624 error
= EINVAL
; /* must have valid attributes too */
628 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
630 * Replace old guard with new guard
632 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
634 if (GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
635 panic("%s: corrupt gfp %p flags %x",
636 __func__
, gfp
, fp
->f_flags
);
638 if (oldg
== gfp
->gf_guard
&&
639 uap
->guardflags
== gfp
->gf_attrs
) {
641 * Must match existing guard + attributes
642 * before we'll swap them to new ones, managing
643 * fdflags "side-effects" as we go. Note that
644 * userland can request FD_CLOFORK semantics.
646 if (gfp
->gf_attrs
& GUARD_CLOSE
)
647 FDFLAGS_CLR(p
, fd
, UF_FORKCLOSE
);
648 gfp
->gf_guard
= newg
;
649 gfp
->gf_attrs
= uap
->nguardflags
;
650 if (gfp
->gf_attrs
& GUARD_CLOSE
)
651 FDFLAGS_SET(p
, fd
, UF_FORKCLOSE
);
653 (nfdflags
& FD_CLOFORK
) ? UF_FORKCLOSE
: 0);
654 /* FG_CONFINED enforced regardless */
661 * Add a guard to a previously unguarded descriptor
663 switch (FILEGLOB_DTYPE(fp
->f_fglob
)) {
676 struct gfp_crarg crarg
= {
678 .gca_attrs
= uap
->nguardflags
680 struct fileproc
*nfp
=
681 guarded_fileproc_alloc_init(&crarg
);
682 struct guarded_fileproc
*gfp
;
686 switch (error
= fp_tryswap(p
, fd
, nfp
)) {
687 case 0: /* guarded-ness comes with side-effects */
688 gfp
= FP_TO_GFP(nfp
);
689 if (gfp
->gf_attrs
& GUARD_CLOSE
)
690 FDFLAGS_SET(p
, fd
, UF_FORKCLOSE
);
691 FDFLAGS_SET(p
, fd
, UF_EXCLOSE
);
692 (void) fp_drop(p
, fd
, nfp
, 1);
695 case EKEEPLOOKING
: /* f_iocount indicates a collision */
696 (void) fp_drop(p
, fd
, fp
, 1);
700 (void) fp_drop(p
, fd
, fp
, 1);
711 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
713 * Remove the guard altogether.
715 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
717 if (0 != uap
->nguardflags
) {
722 if (GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
723 panic("%s: corrupt gfp %p flags %x",
724 __func__
, gfp
, fp
->f_flags
);
726 if (oldg
!= gfp
->gf_guard
||
727 uap
->guardflags
!= gfp
->gf_attrs
) {
733 struct fileproc
*nfp
= fileproc_alloc_init(NULL
);
736 switch (error
= fp_tryswap(p
, fd
, nfp
)) {
737 case 0: /* undo side-effects of guarded-ness */
738 FDFLAGS_CLR(p
, fd
, UF_FORKCLOSE
| UF_EXCLOSE
);
740 (nfdflags
& FD_CLOFORK
) ? UF_FORKCLOSE
: 0);
741 /* FG_CONFINED enforced regardless */
743 (nfdflags
& FD_CLOEXEC
) ? UF_EXCLOSE
: 0);
744 (void) fp_drop(p
, fd
, nfp
, 1);
747 case EKEEPLOOKING
: /* f_iocount indicates collision */
748 (void) fp_drop(p
, fd
, fp
, 1);
752 (void) fp_drop(p
, fd
, fp
, 1);
760 * Not already guarded, and no new guard?
767 (void) fp_drop(p
, fd
, fp
, 1);
773 * user_ssize_t guarded_write_np(int fd, const guardid_t *guard,
774 * user_addr_t cbuf, user_ssize_t nbyte);
776 * Initial implementation of guarded writes.
779 guarded_write_np(struct proc
*p
, struct guarded_write_np_args
*uap
, user_ssize_t
*retval
)
785 struct guarded_fileproc
*gfp
;
786 bool wrote_some
= false;
790 if ((error
= copyin(uap
->guard
, &uguard
, sizeof (uguard
))) != 0)
793 error
= fp_lookup_guarded(p
, fd
, uguard
, &gfp
, 0);
798 if ((fp
->f_flag
& FWRITE
) == 0) {
802 struct vfs_context context
= *(vfs_context_current());
803 context
.vc_ucred
= fp
->f_fglob
->fg_cred
;
805 error
= dofilewrite(&context
, fp
, uap
->cbuf
, uap
->nbyte
,
806 (off_t
)-1, 0, retval
);
807 wrote_some
= *retval
> 0;
810 fp_drop_written(p
, fd
, fp
);
812 fp_drop(p
, fd
, fp
, 0);
817 * user_ssize_t guarded_pwrite_np(int fd, const guardid_t *guard,
818 * user_addr_t buf, user_size_t nbyte, off_t offset);
820 * Initial implementation of guarded pwrites.
823 guarded_pwrite_np(struct proc
*p
, struct guarded_pwrite_np_args
*uap
, user_ssize_t
*retval
)
828 vnode_t vp
= (vnode_t
)0;
830 struct guarded_fileproc
*gfp
;
831 bool wrote_some
= false;
835 if ((error
= copyin(uap
->guard
, &uguard
, sizeof (uguard
))) != 0)
838 error
= fp_lookup_guarded(p
, fd
, uguard
, &gfp
, 0);
843 if ((fp
->f_flag
& FWRITE
) == 0) {
846 struct vfs_context context
= *vfs_context_current();
847 context
.vc_ucred
= fp
->f_fglob
->fg_cred
;
849 if (fp
->f_type
!= DTYPE_VNODE
) {
853 vp
= (vnode_t
)fp
->f_fglob
->fg_data
;
854 if (vnode_isfifo(vp
)) {
858 if ((vp
->v_flag
& VISTTY
)) {
862 if (uap
->offset
== (off_t
)-1) {
867 error
= dofilewrite(&context
, fp
, uap
->buf
, uap
->nbyte
,
868 uap
->offset
, FOF_OFFSET
, retval
);
869 wrote_some
= *retval
> 0;
873 fp_drop_written(p
, fd
, fp
);
875 fp_drop(p
, fd
, fp
, 0);
877 KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_SC_EXTENDED_INFO
, SYS_guarded_pwrite_np
) | DBG_FUNC_NONE
),
878 uap
->fd
, uap
->nbyte
, (unsigned int)((uap
->offset
>> 32)), (unsigned int)(uap
->offset
), 0);
884 * user_ssize_t guarded_writev_np(int fd, const guardid_t *guard,
885 * struct iovec *iovp, u_int iovcnt);
887 * Initial implementation of guarded writev.
891 guarded_writev_np(struct proc
*p
, struct guarded_writev_np_args
*uap
, user_ssize_t
*retval
)
896 struct user_iovec
*iovp
;
898 struct guarded_fileproc
*gfp
;
899 bool wrote_some
= false;
901 AUDIT_ARG(fd
, uap
->fd
);
903 /* Verify range bedfore calling uio_create() */
904 if (uap
->iovcnt
<= 0 || uap
->iovcnt
> UIO_MAXIOV
)
907 /* allocate a uio large enough to hold the number of iovecs passed */
908 auio
= uio_create(uap
->iovcnt
, 0,
909 (IS_64BIT_PROCESS(p
) ? UIO_USERSPACE64
: UIO_USERSPACE32
),
912 /* get location of iovecs within the uio. then copyin the iovecs from
915 iovp
= uio_iovsaddr(auio
);
918 goto ExitThisRoutine
;
920 error
= copyin_user_iovec_array(uap
->iovp
,
921 IS_64BIT_PROCESS(p
) ? UIO_USERSPACE64
: UIO_USERSPACE32
,
924 goto ExitThisRoutine
;
927 /* finalize uio_t for use and do the IO
929 error
= uio_calculateresid(auio
);
931 goto ExitThisRoutine
;
934 if ((error
= copyin(uap
->guard
, &uguard
, sizeof (uguard
))) != 0)
935 goto ExitThisRoutine
;
937 error
= fp_lookup_guarded(p
, uap
->fd
, uguard
, &gfp
, 0);
939 goto ExitThisRoutine
;
942 if ((fp
->f_flag
& FWRITE
) == 0) {
945 error
= wr_uio(p
, fp
, auio
, retval
);
946 wrote_some
= *retval
> 0;
950 fp_drop_written(p
, uap
->fd
, fp
);
952 fp_drop(p
, uap
->fd
, fp
, 0);
961 * int falloc_guarded(struct proc *p, struct fileproc **fp, int *fd,
962 * vfs_context_t ctx, const guardid_t *guard, u_int attrs);
964 * This SPI is the guarded variant of falloc(). It borrows the same
965 * restrictions as those used by the rest of the guarded_* routines.
968 falloc_guarded(struct proc
*p
, struct fileproc
**fp
, int *fd
,
969 vfs_context_t ctx
, const guardid_t
*guard
, u_int attrs
)
971 struct gfp_crarg crarg
;
973 if (((attrs
& GUARD_REQUIRED
) != GUARD_REQUIRED
) ||
974 ((attrs
& ~GUARD_ALL
) != 0) || (*guard
== 0))
977 bzero(&crarg
, sizeof (crarg
));
978 crarg
.gca_guard
= *guard
;
979 crarg
.gca_attrs
= attrs
;
981 return (falloc_withalloc(p
, fp
, fd
, ctx
, guarded_fileproc_alloc_init
,