2 * Copyright (c) 2012 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 <vfs/vfs_support.h>
39 #include <security/audit/audit.h>
42 * Experimental guarded file descriptor support.
45 kern_return_t
task_exception_notify(exception_type_t exception
,
46 mach_exception_data_type_t code
, mach_exception_data_type_t subcode
);
49 * Most fd's have an underlying fileproc struct; but some may be
50 * guarded_fileproc structs which implement guarded fds. The latter
51 * struct (below) embeds the former.
53 * The two types should be distinguished by the "type" portion of f_flags.
54 * There's also a magic number to help catch misuse and bugs.
56 * This is a bit unpleasant, but results from the desire to allow
57 * alternate file behaviours for a few file descriptors without
58 * growing the fileproc data structure.
61 struct guarded_fileproc
{
62 struct fileproc gf_fileproc
;
71 const size_t sizeof_guarded_fileproc
= sizeof (struct guarded_fileproc
);
73 #define FP_TO_GFP(fp) ((struct guarded_fileproc *)(fp))
74 #define GFP_TO_FP(gfp) (&(gfp)->gf_fileproc)
76 #define GUARDED_FILEPROC_MAGIC 0x29083
83 static struct fileproc
*
84 guarded_fileproc_alloc_init(void *crarg
)
86 struct gfp_crarg
*aarg
= crarg
;
87 struct guarded_fileproc
*gfp
;
89 if ((gfp
= kalloc(sizeof (*gfp
))) == NULL
)
92 bzero(gfp
, sizeof (*gfp
));
93 gfp
->gf_fileproc
.f_flags
= FTYPE_GUARDED
;
94 gfp
->gf_magic
= GUARDED_FILEPROC_MAGIC
;
95 gfp
->gf_guard
= aarg
->gca_guard
;
96 gfp
->gf_attrs
= aarg
->gca_attrs
;
98 return (GFP_TO_FP(gfp
));
102 guarded_fileproc_free(struct fileproc
*fp
)
104 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
106 if (FILEPROC_TYPE(fp
) != FTYPE_GUARDED
||
107 GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
108 panic("%s: corrupt fp %p flags %x", __func__
, fp
, fp
->f_flags
);
110 kfree(gfp
, sizeof (*gfp
));
114 fp_lookup_guarded(proc_t p
, int fd
, guardid_t guard
,
115 struct guarded_fileproc
**gfpp
)
120 if ((error
= fp_lookup(p
, fd
, &fp
, 1)) != 0)
122 if (FILEPROC_TYPE(fp
) != FTYPE_GUARDED
) {
123 (void) fp_drop(p
, fd
, fp
, 1);
126 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
128 if (GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
129 panic("%s: corrupt fp %p", __func__
, fp
);
131 if (guard
!= gfp
->gf_guard
) {
132 (void) fp_drop(p
, fd
, fp
, 1);
133 return (EPERM
); /* *not* a mismatch exception */
141 * Expected use pattern:
143 * if (FP_ISGUARDED(fp, GUARD_CLOSE)) {
144 * error = fp_guard_exception(p, fd, fp, kGUARD_EXC_CLOSE);
151 fp_isguarded(struct fileproc
*fp
, u_int attrs
)
153 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
154 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
156 if (GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
157 panic("%s: corrupt gfp %p flags %x",
158 __func__
, gfp
, fp
->f_flags
);
159 return ((attrs
& gfp
->gf_attrs
) ? 1 : 0);
164 extern char *proc_name_address(void *p
);
167 fp_guard_exception(proc_t p
, int fd
, struct fileproc
*fp
, u_int code
)
169 if (FILEPROC_TYPE(fp
) != FTYPE_GUARDED
)
170 panic("%s corrupt fp %p flags %x", __func__
, fp
, fp
->f_flags
);
172 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
174 /* all gfd fields protected via proc_fdlock() */
175 proc_fdlock_assert(p
, LCK_MTX_ASSERT_OWNED
);
177 if (NULL
== gfp
->gf_thread
) {
178 thread_t t
= current_thread();
181 gfp
->gf_exc_code
= code
;
184 * This thread was the first to attempt the
185 * operation that violated the guard on this fd;
186 * generate an exception.
188 printf("%s: guarded fd exception: "
189 "fd %d code 0x%x guard 0x%llx\n",
190 proc_name_address(p
), gfp
->gf_exc_fd
,
191 gfp
->gf_exc_code
, gfp
->gf_guard
);
193 thread_guard_violation(t
, GUARD_TYPE_FD
);
196 * We already recorded a violation on this fd for a
197 * different thread, so posting an exception is
198 * already in progress. We could pause for a bit
199 * and check again, or we could panic (though that seems
200 * heavy handed), or we could just press on with the
201 * error return alone. For now, resort to printf.
203 printf("%s: guarded fd exception+: "
204 "fd %d code 0x%x guard 0x%llx\n",
205 proc_name_address(p
), gfp
->gf_exc_fd
,
206 gfp
->gf_exc_code
, gfp
->gf_guard
);
213 * (Invoked before returning to userland from the syscall handler.)
216 fd_guard_ast(thread_t t
)
218 proc_t p
= current_proc();
219 struct filedesc
*fdp
= p
->p_fd
;
223 for (i
= fdp
->fd_lastfile
; i
>= 0; i
--) {
224 struct fileproc
*fp
= fdp
->fd_ofiles
[i
];
227 FILEPROC_TYPE(fp
) != FTYPE_GUARDED
)
230 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
232 if (GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
233 panic("%s: corrupt gfp %p flags %x",
234 __func__
, gfp
, fp
->f_flags
);
236 if (gfp
->gf_thread
== t
) {
237 mach_exception_data_type_t code
, subcode
;
239 gfp
->gf_thread
= NULL
;
242 * EXC_GUARD exception code namespace.
245 * +-------------------------------------------------+
246 * | [63:61] guard type | [60:0] guard-specific data |
247 * +-------------------------------------------------+
250 * +-------------------------------------------------+
251 * | [63:0] guard-specific data |
252 * +-------------------------------------------------+
254 * At the moment, we have just one guard type: file
257 * File descriptor guards use the exception codes like
261 * +--------------------------------------------------+
262 * |[63:61] GUARD_TYPE_FD | [60:32] flavor | [31:0] fd|
263 * +--------------------------------------------------+
266 * +--------------------------------------------------+
267 * | [63:0] guard value |
268 * +--------------------------------------------------+
270 code
= (((uint64_t)GUARD_TYPE_FD
) << 61) |
271 (((uint64_t)gfp
->gf_exc_code
) << 32) |
272 ((uint64_t)gfp
->gf_exc_fd
);
273 subcode
= gfp
->gf_guard
;
276 (void) task_exception_notify(EXC_GUARD
, code
, subcode
);
286 * Experimental guarded file descriptor SPIs
290 * int guarded_open_np(const char *pathname, int flags,
291 * const guardid_t *guard, u_int guardflags, ...);
293 * In this initial implementation, GUARD_DUP must be specified.
294 * GUARD_CLOSE, GUARD_SOCKET_IPC and GUARD_FILEPORT are optional.
296 * If GUARD_DUP wasn't specified, then we'd have to do the (extra) work
297 * to allow dup-ing a descriptor to inherit the guard onto the new
298 * descriptor. (Perhaps GUARD_DUP behaviours should just always be true
299 * for a guarded fd? Or, more sanely, all the dup operations should
300 * just always propagate the guard?)
302 * Guarded descriptors are always close-on-exec, and GUARD_CLOSE
303 * requires close-on-fork; O_CLOEXEC must be set in flags.
304 * This setting is immutable; attempts to clear the flag will
305 * cause a guard exception.
308 guarded_open_np(proc_t p
, struct guarded_open_np_args
*uap
, int32_t *retval
)
310 if ((uap
->flags
& O_CLOEXEC
) == 0)
313 #define GUARD_REQUIRED (GUARD_DUP)
314 #define GUARD_ALL (GUARD_REQUIRED | \
315 (GUARD_CLOSE | GUARD_SOCKET_IPC | GUARD_FILEPORT))
317 if (((uap
->guardflags
& GUARD_REQUIRED
) != GUARD_REQUIRED
) ||
318 ((uap
->guardflags
& ~GUARD_ALL
) != 0))
322 struct gfp_crarg crarg
= {
323 .gca_attrs
= uap
->guardflags
326 if ((error
= copyin(uap
->guard
,
327 &(crarg
.gca_guard
), sizeof (crarg
.gca_guard
))) != 0)
331 * Disallow certain guard values -- is zero enough?
333 if (crarg
.gca_guard
== 0)
336 struct filedesc
*fdp
= p
->p_fd
;
337 struct vnode_attr va
;
339 vfs_context_t ctx
= vfs_context_current();
343 cmode
= ((uap
->mode
& ~fdp
->fd_cmask
) & ALLPERMS
) & ~S_ISTXT
;
344 VATTR_SET(&va
, va_mode
, cmode
& ACCESSPERMS
);
346 NDINIT(&nd
, LOOKUP
, OP_OPEN
, FOLLOW
| AUDITVNPATH1
, UIO_USERSPACE
,
349 return (open1(ctx
, &nd
, uap
->flags
| O_CLOFORK
, &va
,
350 guarded_fileproc_alloc_init
, &crarg
, retval
));
354 * int guarded_kqueue_np(const guardid_t *guard, u_int guardflags);
356 * Create a guarded kqueue descriptor with guardid and guardflags.
358 * Same restrictions on guardflags as for guarded_open_np().
359 * All kqueues are -always- close-on-exec and close-on-fork by themselves.
361 * XXX Is it ever sensible to allow a kqueue fd (guarded or not) to
362 * be sent to another process via a fileport or socket?
365 guarded_kqueue_np(proc_t p
, struct guarded_kqueue_np_args
*uap
, int32_t *retval
)
367 if (((uap
->guardflags
& GUARD_REQUIRED
) != GUARD_REQUIRED
) ||
368 ((uap
->guardflags
& ~GUARD_ALL
) != 0))
372 struct gfp_crarg crarg
= {
373 .gca_attrs
= uap
->guardflags
376 if ((error
= copyin(uap
->guard
,
377 &(crarg
.gca_guard
), sizeof (crarg
.gca_guard
))) != 0)
380 if (crarg
.gca_guard
== 0)
383 return (kqueue_body(p
, guarded_fileproc_alloc_init
, &crarg
, retval
));
387 * int guarded_close_np(int fd, const guardid_t *guard);
390 guarded_close_np(proc_t p
, struct guarded_close_np_args
*uap
,
391 __unused
int32_t *retval
)
393 struct guarded_fileproc
*gfp
;
398 AUDIT_SYSCLOSE(p
, fd
);
400 if ((error
= copyin(uap
->guard
, &uguard
, sizeof (uguard
))) != 0)
404 if ((error
= fp_lookup_guarded(p
, fd
, uguard
, &gfp
)) != 0) {
408 error
= close_internal_locked(p
, fd
, GFP_TO_FP(gfp
), 0);
415 * change_fdguard_np(int fd, const guardid_t *guard, u_int guardflags,
416 * const guardid_t *nguard, u_int nguardflags, int *fdflagsp);
418 * Given a file descriptor, atomically exchange <guard, guardflags> for
419 * a new guard <nguard, nguardflags>, returning the previous fd
420 * flags (see fcntl:F_SETFD) in *fdflagsp.
422 * This syscall can be used to either (a) add a new guard to an existing
423 * unguarded file descriptor (b) remove the old guard from an existing
424 * guarded file descriptor or (c) change the guard (guardid and/or
425 * guardflags) on a guarded file descriptor.
427 * If 'guard' is NULL, fd must be unguarded at entry. If the call completes
428 * successfully the fd will be guarded with <nguard, nguardflags>.
430 * Guarding a file descriptor has some side-effects on the "fdflags"
431 * associated with the descriptor - in particular FD_CLOEXEC is
432 * forced ON unconditionally, and FD_CLOFORK is forced ON by GUARD_CLOSE.
433 * Callers who wish to subsequently restore the state of the fd should save
434 * the value of *fdflagsp after a successful invocation.
436 * If 'nguard' is NULL, fd must be guarded at entry, <guard, guardflags>
437 * must match with what's already guarding the descriptor, and the
438 * result will be to completely remove the guard. Note also that the
439 * fdflags are copied to the descriptor from the incoming *fdflagsp argument.
441 * If the descriptor is guarded, and neither 'guard' nor 'nguard' is NULL
442 * and <guard, guardflags> matches what's already guarding the descriptor,
443 * then <nguard, nguardflags> becomes the new guard. In this case, even if
444 * the GUARD_CLOSE flag is being cleared, it is still possible to continue
445 * to keep FD_CLOFORK on the descriptor by passing FD_CLOFORK via fdflagsp.
447 * Example 1: Guard an unguarded descriptor during a set of operations,
448 * then restore the original state of the descriptor.
451 * change_fdguard_np(fd, NULL, 0, &myguard, GUARD_CLOSE, &sav_flags);
452 * // do things with now guarded 'fd'
453 * change_fdguard_np(fd, &myguard, GUARD_CLOSE, NULL, 0, &sav_flags);
454 * // fd now unguarded.
456 * Example 2: Change the guard of a guarded descriptor during a set of
457 * operations, then restore the original state of the descriptor.
459 * int sav_flags = (gdflags & GUARD_CLOSE) ? FD_CLOFORK : 0;
460 * change_fdguard_np(fd, &gd, gdflags, &myguard, GUARD_CLOSE, &sav_flags);
461 * // do things with 'fd' with a different guard
462 * change_fdguard_np(fd, &myg, GUARD_CLOSE, &gd, gdflags, &sav_flags);
463 * // back to original guarded state
466 #define FDFLAGS_GET(p, fd) (*fdflags(p, fd) & (UF_EXCLOSE|UF_FORKCLOSE))
467 #define FDFLAGS_SET(p, fd, bits) \
468 (*fdflags(p, fd) |= ((bits) & (UF_EXCLOSE|UF_FORKCLOSE)))
469 #define FDFLAGS_CLR(p, fd, bits) \
470 (*fdflags(p, fd) &= ~((bits) & (UF_EXCLOSE|UF_FORKCLOSE)))
473 change_fdguard_np(proc_t p
, struct change_fdguard_np_args
*uap
,
474 __unused
int32_t *retval
)
479 guardid_t oldg
= 0, newg
= 0;
482 if (0 != uap
->guard
&&
483 0 != (error
= copyin(uap
->guard
, &oldg
, sizeof (oldg
))))
484 return (error
); /* can't copyin current guard */
486 if (0 != uap
->nguard
&&
487 0 != (error
= copyin(uap
->nguard
, &newg
, sizeof (newg
))))
488 return (error
); /* can't copyin new guard */
490 if (0 != uap
->fdflagsp
&&
491 0 != (error
= copyin(uap
->fdflagsp
, &nfdflags
, sizeof (nfdflags
))))
492 return (error
); /* can't copyin new fdflags */
496 if ((error
= fp_lookup(p
, fd
, &fp
, 1)) != 0) {
501 if (0 != uap
->fdflagsp
) {
502 int ofdflags
= FDFLAGS_GET(p
, fd
);
503 int ofl
= ((ofdflags
& UF_EXCLOSE
) ? FD_CLOEXEC
: 0) |
504 ((ofdflags
& UF_FORKCLOSE
) ? FD_CLOFORK
: 0);
506 if (0 != (error
= copyout(&ofl
, uap
->fdflagsp
, sizeof (ofl
)))) {
508 goto dropout
; /* can't copyout old fdflags */
513 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
514 if (0 == uap
->guard
|| 0 == uap
->guardflags
)
515 error
= EINVAL
; /* missing guard! */
517 error
= EPERM
; /* guardids cannot be zero */
519 if (0 != uap
->guard
|| 0 != uap
->guardflags
)
520 error
= EINVAL
; /* guard provided, but none needed! */
526 if (0 != uap
->nguard
) {
528 * There's a new guard in town.
531 error
= EINVAL
; /* guards cannot contain zero */
532 else if (0 == uap
->nguardflags
)
533 error
= EINVAL
; /* attributes cannot be zero */
534 else if (((uap
->nguardflags
& GUARD_REQUIRED
) != GUARD_REQUIRED
) ||
535 ((uap
->guardflags
& ~GUARD_ALL
) != 0))
536 error
= EINVAL
; /* must have valid attributes too */
541 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
543 * Replace old guard with new guard
545 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
547 if (GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
548 panic("%s: corrupt gfp %p flags %x",
549 __func__
, gfp
, fp
->f_flags
);
551 if (oldg
== gfp
->gf_guard
&&
552 uap
->guardflags
== gfp
->gf_attrs
) {
554 * Must match existing guard + attributes
555 * before we'll swap them to new ones, managing
556 * fdflags "side-effects" as we go. Note that
557 * userland can request FD_CLOFORK semantics.
559 if (gfp
->gf_attrs
& GUARD_CLOSE
)
560 FDFLAGS_CLR(p
, fd
, UF_FORKCLOSE
);
561 gfp
->gf_guard
= newg
;
562 gfp
->gf_attrs
= uap
->nguardflags
;
563 if (gfp
->gf_attrs
& GUARD_CLOSE
)
564 FDFLAGS_SET(p
, fd
, UF_FORKCLOSE
);
566 (nfdflags
& FD_CLOFORK
) ? UF_FORKCLOSE
: 0);
573 * Add a guard to a previously unguarded descriptor
575 switch (FILEGLOB_DTYPE(fp
->f_fglob
)) {
588 struct gfp_crarg crarg
= {
590 .gca_attrs
= uap
->nguardflags
592 struct fileproc
*nfp
=
593 guarded_fileproc_alloc_init(&crarg
);
597 switch (error
= fp_tryswap(p
, fd
, nfp
)) {
598 struct guarded_fileproc
*gfp
;
600 case 0: /* guarded-ness comes with side-effects */
601 gfp
= FP_TO_GFP(nfp
);
602 if (gfp
->gf_attrs
& GUARD_CLOSE
)
603 FDFLAGS_SET(p
, fd
, UF_FORKCLOSE
);
604 FDFLAGS_SET(p
, fd
, UF_EXCLOSE
);
605 (void) fp_drop(p
, fd
, nfp
, 1);
608 case EKEEPLOOKING
: /* f_iocount indicates a collision */
609 (void) fp_drop(p
, fd
, fp
, 1);
613 (void) fp_drop(p
, fd
, fp
, 1);
624 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) {
626 * Remove the guard altogether.
628 struct guarded_fileproc
*gfp
= FP_TO_GFP(fp
);
630 if (0 != uap
->nguardflags
) {
635 if (GUARDED_FILEPROC_MAGIC
!= gfp
->gf_magic
)
636 panic("%s: corrupt gfp %p flags %x",
637 __func__
, gfp
, fp
->f_flags
);
639 if (oldg
!= gfp
->gf_guard
||
640 uap
->guardflags
!= gfp
->gf_attrs
) {
646 struct fileproc
*nfp
= fileproc_alloc_init(NULL
);
649 switch (error
= fp_tryswap(p
, fd
, nfp
)) {
650 case 0: /* undo side-effects of guarded-ness */
651 FDFLAGS_CLR(p
, fd
, UF_FORKCLOSE
| UF_EXCLOSE
);
653 (nfdflags
& FD_CLOFORK
) ? UF_FORKCLOSE
: 0);
655 (nfdflags
& FD_CLOEXEC
) ? UF_EXCLOSE
: 0);
656 (void) fp_drop(p
, fd
, nfp
, 1);
659 case EKEEPLOOKING
: /* f_iocount indicates collision */
660 (void) fp_drop(p
, fd
, fp
, 1);
664 (void) fp_drop(p
, fd
, fp
, 1);
672 * Not already guarded, and no new guard?
679 (void) fp_drop(p
, fd
, fp
, 1);