]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_authorization.c
xnu-7195.81.3.tar.gz
[apple/xnu.git] / bsd / kern / kern_authorization.c
index 630a4c1003017e4efb0685154a6bc7b223892856..0181ee93de8d2c4a120183cacb21675835dad8e4 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2004-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
@@ -31,7 +31,7 @@
  */
 
 #include <sys/appleapiopts.h>
-#include <sys/param.h> /* XXX trim includes */
+#include <sys/param.h>  /* XXX trim includes */
 #include <sys/acct.h>
 #include <sys/systm.h>
 #include <sys/ucred.h>
@@ -59,8 +59,8 @@
 
 lck_grp_t *kauth_lck_grp;
 static lck_mtx_t *kauth_scope_mtx;
-#define KAUTH_SCOPELOCK()      lck_mtx_lock(kauth_scope_mtx);
-#define KAUTH_SCOPEUNLOCK()    lck_mtx_unlock(kauth_scope_mtx);
+#define KAUTH_SCOPELOCK()       lck_mtx_lock(kauth_scope_mtx);
+#define KAUTH_SCOPEUNLOCK()     lck_mtx_unlock(kauth_scope_mtx);
 
 /*
  * We support listeners for scopes that have not been registered yet.
@@ -69,72 +69,72 @@ static lck_mtx_t *kauth_scope_mtx;
  * remove it from kauth_dangling_listeners and add it to the active scope.
  */
 struct kauth_listener {
-       TAILQ_ENTRY(kauth_listener)     kl_link;
-       const char *                            kl_identifier;
-       kauth_scope_callback_t          kl_callback;
-       void *                                          kl_idata;
+       TAILQ_ENTRY(kauth_listener)     kl_link;
+       const char *                            kl_identifier;
+       kauth_scope_callback_t          kl_callback;
+       void *                                          kl_idata;
 };
 
 /* XXX - kauth_todo - there is a race if a scope listener is removed while we
  * we are in the kauth_authorize_action code path.  We intentionally do not take
- * a scope lock in order to get the best possible performance.  we will fix this 
- * post Tiger. 
- * Until the race is fixed our kext clients are responsible for all active 
+ * a scope lock in order to get the best possible performance.  we will fix this
+ * post Tiger.
+ * Until the race is fixed our kext clients are responsible for all active
  * requests that may be in their callback code or on the way to their callback
  * code before they free kauth_listener.kl_callback or kauth_listener.kl_idata.
- * We keep copies of these in our kauth_local_listener in an attempt to limit 
- * our expose to unlisten race. 
+ * We keep copies of these in our kauth_local_listener in an attempt to limit
+ * our expose to unlisten race.
  */
 struct kauth_local_listener {
-       kauth_listener_t                        kll_listenerp;
-       kauth_scope_callback_t          kll_callback;
-       void *                                          kll_idata;
+       kauth_listener_t                        kll_listenerp;
+       kauth_scope_callback_t          kll_callback;
+       void *                                          kll_idata;
 };
 typedef struct kauth_local_listener *kauth_local_listener_t;
 
-static TAILQ_HEAD(,kauth_listener) kauth_dangling_listeners;
+static TAILQ_HEAD(, kauth_listener) kauth_dangling_listeners;
 
-/* 
+/*
  * Scope listeners need to be reworked to be dynamic.
- * We intentionally used a static table to avoid locking issues with linked 
+ * We intentionally used a static table to avoid locking issues with linked
  * lists.  The listeners may be called quite often.
  * XXX - kauth_todo
  */
 #define KAUTH_SCOPE_MAX_LISTENERS  15
 
 struct kauth_scope {
-       TAILQ_ENTRY(kauth_scope)        ks_link;
+       TAILQ_ENTRY(kauth_scope)        ks_link;
        volatile struct kauth_local_listener  ks_listeners[KAUTH_SCOPE_MAX_LISTENERS];
-       const char *                            ks_identifier;
-       kauth_scope_callback_t          ks_callback;
-       void *                                          ks_idata;
-       u_int                                           ks_flags;
+       const char *                            ks_identifier;
+       kauth_scope_callback_t          ks_callback;
+       void *                                          ks_idata;
+       u_int                                           ks_flags;
 };
 
 /* values for kauth_scope.ks_flags */
-#define KS_F_HAS_LISTENERS             (1 << 0)
+#define KS_F_HAS_LISTENERS              (1 << 0)
 
-static TAILQ_HEAD(,kauth_scope)        kauth_scopes;
+static TAILQ_HEAD(, kauth_scope) kauth_scopes;
 
 static int kauth_add_callback_to_scope(kauth_scope_t sp, kauth_listener_t klp);
-static void    kauth_scope_init(void);
+static void     kauth_scope_init(void);
 static kauth_scope_t kauth_alloc_scope(const char *identifier, kauth_scope_callback_t callback, void *idata);
 static kauth_listener_t kauth_alloc_listener(const char *identifier, kauth_scope_callback_t callback, void *idata);
 #if 0
-static int     kauth_scope_valid(kauth_scope_t scope);
+static int      kauth_scope_valid(kauth_scope_t scope);
 #endif
 
-kauth_scope_t  kauth_scope_process;
-static int     kauth_authorize_process_callback(kauth_cred_t _credential, void *_idata, kauth_action_t _action,
+kauth_scope_t   kauth_scope_process;
+static int      kauth_authorize_process_callback(kauth_cred_t _credential, void *_idata, kauth_action_t _action,
     uintptr_t arg0, uintptr_t arg1, __unused uintptr_t arg2, __unused uintptr_t arg3);
-kauth_scope_t  kauth_scope_generic;
-static int     kauth_authorize_generic_callback(kauth_cred_t _credential, void *_idata, kauth_action_t _action,
+kauth_scope_t   kauth_scope_generic;
+static int      kauth_authorize_generic_callback(kauth_cred_t _credential, void *_idata, kauth_action_t _action,
     uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
-kauth_scope_t  kauth_scope_fileop;
+kauth_scope_t   kauth_scope_fileop;
 
-extern int             cansignal(struct proc *, kauth_cred_t, struct proc *, int, int);
-extern char *  get_pathbuff(void);
-extern void            release_pathbuff(char *path);
+extern int              cansignal(struct proc *, kauth_cred_t, struct proc *, int);
+extern char *   get_pathbuff(void);
+extern void             release_pathbuff(char *path);
 
 /*
  * Initialization.
@@ -142,7 +142,7 @@ extern void         release_pathbuff(char *path);
 void
 kauth_init(void)
 {
-       lck_grp_attr_t  *grp_attributes;
+       lck_grp_attr_t  *grp_attributes;
 
        TAILQ_INIT(&kauth_scopes);
        TAILQ_INIT(&kauth_dangling_listeners);
@@ -183,19 +183,20 @@ kauth_scope_init(void)
 static kauth_scope_t
 kauth_alloc_scope(const char *identifier, kauth_scope_callback_t callback, void *idata)
 {
-       kauth_scope_t   sp;
+       kauth_scope_t   sp;
 
        /*
         * Allocate and populate the scope structure.
         */
        MALLOC(sp, kauth_scope_t, sizeof(*sp), M_KAUTH, M_WAITOK | M_ZERO);
-       if (sp == NULL)
-               return(NULL);
+       if (sp == NULL) {
+               return NULL;
+       }
        sp->ks_flags = 0;
        sp->ks_identifier = identifier;
        sp->ks_idata = idata;
        sp->ks_callback = callback;
-       return(sp);
+       return sp;
 }
 
 static kauth_listener_t
@@ -207,22 +208,24 @@ kauth_alloc_listener(const char *identifier, kauth_scope_callback_t callback, vo
         * Allocate and populate the listener structure.
         */
        MALLOC(lsp, kauth_listener_t, sizeof(*lsp), M_KAUTH, M_WAITOK);
-       if (lsp == NULL)
-               return(NULL);
+       if (lsp == NULL) {
+               return NULL;
+       }
        lsp->kl_identifier = identifier;
        lsp->kl_idata = idata;
        lsp->kl_callback = callback;
-       return(lsp);
+       return lsp;
 }
 
 kauth_scope_t
 kauth_register_scope(const char *identifier, kauth_scope_callback_t callback, void *idata)
 {
-       kauth_scope_t           sp, tsp;
-       kauth_listener_t        klp;
+       kauth_scope_t           sp, tsp;
+       kauth_listener_t        klp;
 
-       if ((sp = kauth_alloc_scope(identifier, callback, idata)) == NULL)
-               return(NULL);
+       if ((sp = kauth_alloc_scope(identifier, callback, idata)) == NULL) {
+               return NULL;
+       }
 
        /*
         * Lock the list and insert.
@@ -230,11 +233,11 @@ kauth_register_scope(const char *identifier, kauth_scope_callback_t callback, vo
        KAUTH_SCOPELOCK();
        TAILQ_FOREACH(tsp, &kauth_scopes, ks_link) {
                /* duplicate! */
-               if (strncmp(tsp->ks_identifier, identifier, 
-                                       strlen(tsp->ks_identifier) + 1) == 0) {
+               if (strncmp(tsp->ks_identifier, identifier,
+                   strlen(tsp->ks_identifier) + 1) == 0) {
                        KAUTH_SCOPEUNLOCK();
                        FREE(sp, M_KAUTH);
-                       return(NULL);
+                       return NULL;
                }
        }
        TAILQ_INSERT_TAIL(&kauth_scopes, sp, ks_link);
@@ -248,14 +251,13 @@ kauth_register_scope(const char *identifier, kauth_scope_callback_t callback, vo
 restart:
        TAILQ_FOREACH(klp, &kauth_dangling_listeners, kl_link) {
                if (strncmp(klp->kl_identifier, sp->ks_identifier,
-                                       strlen(klp->kl_identifier) + 1) == 0) {
+                   strlen(klp->kl_identifier) + 1) == 0) {
                        /* found a match on the dangling listener list.  add it to the
                         * the active scope.
                         */
                        if (kauth_add_callback_to_scope(sp, klp) == 0) {
                                TAILQ_REMOVE(&kauth_dangling_listeners, klp, kl_link);
-                       }
-                       else {
+                       } else {
 #if 0
                                printf("%s - failed to add listener to scope \"%s\" \n", __FUNCTION__, sp->ks_identifier);
 #endif
@@ -266,7 +268,7 @@ restart:
        }
 
        KAUTH_SCOPEUNLOCK();
-       return(sp);
+       return sp;
 }
 
 
@@ -274,18 +276,18 @@ restart:
 void
 kauth_deregister_scope(kauth_scope_t scope)
 {
-       int             i;
+       int             i;
 
        KAUTH_SCOPELOCK();
 
        TAILQ_REMOVE(&kauth_scopes, scope, ks_link);
-       
+
        /* relocate listeners back to the waiting list */
        for (i = 0; i < KAUTH_SCOPE_MAX_LISTENERS; i++) {
                if (scope->ks_listeners[i].kll_listenerp != NULL) {
                        TAILQ_INSERT_TAIL(&kauth_dangling_listeners, scope->ks_listeners[i].kll_listenerp, kl_link);
                        scope->ks_listeners[i].kll_listenerp = NULL;
-                       /* 
+                       /*
                         * XXX - kauth_todo - WARNING, do not clear kll_callback or
                         * kll_idata here.  they are part of our scope unlisten race hack
                         */
@@ -293,7 +295,7 @@ kauth_deregister_scope(kauth_scope_t scope)
        }
        KAUTH_SCOPEUNLOCK();
        FREE(scope, M_KAUTH);
-       
+
        return;
 }
 
@@ -301,10 +303,11 @@ kauth_listener_t
 kauth_listen_scope(const char *identifier, kauth_scope_callback_t callback, void *idata)
 {
        kauth_listener_t klp;
-       kauth_scope_t   sp;
+       kauth_scope_t   sp;
 
-       if ((klp = kauth_alloc_listener(identifier, callback, idata)) == NULL)
-               return(NULL);
+       if ((klp = kauth_alloc_listener(identifier, callback, idata)) == NULL) {
+               return NULL;
+       }
 
        /*
         * Lock the scope list and check to see whether this scope already exists.
@@ -312,34 +315,34 @@ kauth_listen_scope(const char *identifier, kauth_scope_callback_t callback, void
        KAUTH_SCOPELOCK();
        TAILQ_FOREACH(sp, &kauth_scopes, ks_link) {
                if (strncmp(sp->ks_identifier, identifier,
-                                       strlen(sp->ks_identifier) + 1) == 0) {
+                   strlen(sp->ks_identifier) + 1) == 0) {
                        /* scope exists, add it to scope listener table */
                        if (kauth_add_callback_to_scope(sp, klp) == 0) {
                                KAUTH_SCOPEUNLOCK();
-                               return(klp);
+                               return klp;
                        }
                        /* table already full */
                        KAUTH_SCOPEUNLOCK();
                        FREE(klp, M_KAUTH);
-                       return(NULL);
+                       return NULL;
                }
        }
-       
+
        /* scope doesn't exist, put on waiting list. */
        TAILQ_INSERT_TAIL(&kauth_dangling_listeners, klp, kl_link);
 
        KAUTH_SCOPEUNLOCK();
 
-       return(klp);
+       return klp;
 }
 
 void
 kauth_unlisten_scope(kauth_listener_t listener)
 {
-       kauth_scope_t           sp;
-       kauth_listener_t        klp;
-       int                                     i, listener_count, do_free;
-       
+       kauth_scope_t           sp;
+       kauth_listener_t        klp;
+       int                                     i, listener_count, do_free;
+
        KAUTH_SCOPELOCK();
 
        /* search the active scope for this listener */
@@ -351,12 +354,11 @@ kauth_unlisten_scope(kauth_listener_t listener)
                                if (sp->ks_listeners[i].kll_listenerp == listener) {
                                        sp->ks_listeners[i].kll_listenerp = NULL;
                                        do_free = 1;
-                                       /* 
+                                       /*
                                         * XXX - kauth_todo - WARNING, do not clear kll_callback or
                                         * kll_idata here.  they are part of our scope unlisten race hack
                                         */
-                               }
-                               else if (sp->ks_listeners[i].kll_listenerp != NULL) {
+                               } else if (sp->ks_listeners[i].kll_listenerp != NULL) {
                                        listener_count++;
                                }
                        }
@@ -401,36 +403,39 @@ kauth_authorize_action(kauth_scope_t scope, kauth_cred_t credential, kauth_actio
        int result, ret, i;
 
        /* ask the scope */
-       if (scope->ks_callback != NULL)
+       if (scope->ks_callback != NULL) {
                result = scope->ks_callback(credential, scope->ks_idata, action, arg0, arg1, arg2, arg3);
-       else
+       } else {
                result = KAUTH_RESULT_DEFER;
+       }
 
        /* check with listeners */
        if ((scope->ks_flags & KS_F_HAS_LISTENERS) != 0) {
                for (i = 0; i < KAUTH_SCOPE_MAX_LISTENERS; i++) {
-                       /* XXX - kauth_todo - there is a race here if listener is removed - we will fix this post Tiger. 
+                       /* XXX - kauth_todo - there is a race here if listener is removed - we will fix this post Tiger.
                         * Until the race is fixed our kext clients are responsible for all active requests that may
                         * be in their callbacks or on the way to their callbacks before they free kl_callback or kl_idata.
-                        * We keep copies of these in our kauth_local_listener in an attempt to limit our expose to 
-                        * unlisten race. 
+                        * We keep copies of these in our kauth_local_listener in an attempt to limit our expose to
+                        * unlisten race.
                         */
-                       if (scope->ks_listeners[i].kll_listenerp == NULL || 
-                               scope->ks_listeners[i].kll_callback == NULL) 
+                       if (scope->ks_listeners[i].kll_listenerp == NULL ||
+                           scope->ks_listeners[i].kll_callback == NULL) {
                                continue;
+                       }
 
                        ret = scope->ks_listeners[i].kll_callback(
-                                       credential, scope->ks_listeners[i].kll_idata, 
-                                       action, arg0, arg1, arg2, arg3);
+                               credential, scope->ks_listeners[i].kll_idata,
+                               action, arg0, arg1, arg2, arg3);
                        if ((ret == KAUTH_RESULT_DENY) ||
-                               (result == KAUTH_RESULT_DEFER))
+                           (result == KAUTH_RESULT_DEFER)) {
                                result = ret;
+                       }
                }
        }
 
        /* we need an explicit allow, or the auth fails */
-       /* XXX need a mechanism for auth failure to be signalled vs. denial */
-       return(result == KAUTH_RESULT_ALLOW ? 0 : EPERM);
+       /* XXX need a mechanism for auth failure to be signalled vs. denial */
+       return result == KAUTH_RESULT_ALLOW ? 0 : EPERM;
 }
 
 /*
@@ -438,10 +443,9 @@ kauth_authorize_action(kauth_scope_t scope, kauth_cred_t credential, kauth_actio
  */
 int
 kauth_authorize_allow(__unused kauth_cred_t credential, __unused void *idata, __unused kauth_action_t action,
-     __unused uintptr_t arg0, __unused uintptr_t arg1, __unused uintptr_t arg2, __unused uintptr_t arg3)
+    __unused uintptr_t arg0, __unused uintptr_t arg1, __unused uintptr_t arg2, __unused uintptr_t arg3)
 {
-
-       return(KAUTH_RESULT_ALLOW);
+       return KAUTH_RESULT_ALLOW;
 }
 
 #if 0
@@ -451,15 +455,16 @@ kauth_authorize_allow(__unused kauth_cred_t credential, __unused void *idata, __
 static int
 kauth_scope_valid(kauth_scope_t scope)
 {
-       kauth_scope_t   sp;
+       kauth_scope_t   sp;
 
        KAUTH_SCOPELOCK();
        TAILQ_FOREACH(sp, &kauth_scopes, ks_link) {
-               if (sp == scope)
+               if (sp == scope) {
                        break;
+               }
        }
        KAUTH_SCOPEUNLOCK();
-       return((sp == NULL) ? 0 : 1);
+       return (sp == NULL) ? 0 : 1;
 }
 #endif
 
@@ -470,35 +475,37 @@ kauth_scope_valid(kauth_scope_t scope)
 int
 kauth_authorize_process(kauth_cred_t credential, kauth_action_t action, struct proc *process, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
 {
-       return(kauth_authorize_action(kauth_scope_process, credential, action, (uintptr_t)process, arg1, arg2, arg3));
+       return kauth_authorize_action(kauth_scope_process, credential, action, (uintptr_t)process, arg1, arg2, arg3);
 }
 
 static int
 kauth_authorize_process_callback(kauth_cred_t credential, __unused void *idata, kauth_action_t action,
     uintptr_t arg0, uintptr_t arg1, __unused uintptr_t arg2, __unused uintptr_t arg3)
 {
-       switch(action) {
+       switch (action) {
        case KAUTH_PROCESS_CANSIGNAL:
                panic("KAUTH_PROCESS_CANSIGNAL not implemented");
                /* XXX credential wrong here */
                /* arg0 - process to signal
                 * arg1 - signal to send the process
                 */
-               if (cansignal(current_proc(), credential, (struct proc *)arg0, (int)arg1, 0))
-                       return(KAUTH_RESULT_ALLOW);
+               if (cansignal(current_proc(), credential, (struct proc *)arg0, (int)arg1)) {
+                       return KAUTH_RESULT_ALLOW;
+               }
                break;
        case KAUTH_PROCESS_CANTRACE:
-               /* current_proc() - process that will do the tracing 
-                * arg0 - process to be traced 
-                * arg1 - pointer to int - reason (errno) for denial 
+               /* current_proc() - process that will do the tracing
+                * arg0 - process to be traced
+                * arg1 - pointer to int - reason (errno) for denial
                 */
-               if (cantrace(current_proc(), credential, (proc_t)arg0, (int *)arg1))
-                       return(KAUTH_RESULT_ALLOW);
+               if (cantrace(current_proc(), credential, (proc_t)arg0, (int *)arg1)) {
+                       return KAUTH_RESULT_ALLOW;
+               }
                break;
        }
 
        /* no explicit result, so defer to others in the chain */
-       return(KAUTH_RESULT_DEFER);
+       return KAUTH_RESULT_DEFER;
 }
 
 /*
@@ -512,6 +519,10 @@ kauth_authorize_process_callback(kauth_cred_t credential, __unused void *idata,
  *             arg0 is pointer to vnode (vnode *) for file to be closed.
  *             arg1 is pointer to path (char *) of file to be closed.
  *             arg2 is close flags.
+ * arguments passed to KAUTH_FILEOP_WILL_RENAME listeners
+ *             arg0 is pointer to vnode (vnode *) of the file being renamed
+ *             arg1 is pointer to the "from" path (char *)
+ *             arg2 is pointer to the "to" path (char *)
  * arguments passed to KAUTH_FILEOP_RENAME listeners
  *             arg0 is pointer to "from" path (char *).
  *             arg1 is pointer to "to" path (char *).
@@ -531,46 +542,56 @@ kauth_authorize_fileop_has_listeners(void)
         * otherwize return 0
         */
        if ((kauth_scope_fileop->ks_flags & KS_F_HAS_LISTENERS) != 0) {
-               return(1);
+               return 1;
        }
-       return (0);
+       return 0;
 }
 
 int
 kauth_authorize_fileop(kauth_cred_t credential, kauth_action_t action, uintptr_t arg0, uintptr_t arg1)
 {
-       char            *namep = NULL;
-       int                     name_len;
-       uintptr_t       arg2 = 0;
-       
-       /* we do not have a primary handler for the fileop scope so bail out if 
+       char            *namep = NULL;
+       int                     name_len;
+       uintptr_t       arg2 = 0;
+
+       /* we do not have a primary handler for the fileop scope so bail out if
         * there are no listeners.
         */
        if ((kauth_scope_fileop->ks_flags & KS_F_HAS_LISTENERS) == 0) {
-               return(0);
+               return 0;
        }
 
-       if (action == KAUTH_FILEOP_OPEN || action == KAUTH_FILEOP_CLOSE || action == KAUTH_FILEOP_EXEC) {
+       if (action == KAUTH_FILEOP_OPEN ||
+           action == KAUTH_FILEOP_CLOSE ||
+           action == KAUTH_FILEOP_EXEC ||
+           action == KAUTH_FILEOP_WILL_RENAME) {
                /* get path to the given vnode as a convenience to our listeners.
                 */
                namep = get_pathbuff();
                name_len = MAXPATHLEN;
                if (vn_getpath((vnode_t)arg0, namep, &name_len) != 0) {
                        release_pathbuff(namep);
-                       return(0);
+                       return 0;
                }
-               if (action == KAUTH_FILEOP_CLOSE) {
-                       arg2 = arg1;  /* close has some flags that come in via arg1 */
+               if (action == KAUTH_FILEOP_CLOSE ||
+                   action == KAUTH_FILEOP_WILL_RENAME) {
+                       /*
+                        * - Close has some flags that come in via arg1.
+                        * - Will-rename wants to pass the vnode and
+                        *   both paths to the listeners ("to" path
+                        *   starts in arg1, moves to arg2).
+                        */
+                       arg2 = arg1;
                }
                arg1 = (uintptr_t)namep;
-       }       
+       }
        kauth_authorize_action(kauth_scope_fileop, credential, action, arg0, arg1, arg2, 0);
-       
+
        if (namep != NULL) {
                release_pathbuff(namep);
        }
-       
-       return(0);
+
+       return 0;
 }
 
 /*
@@ -580,26 +601,26 @@ kauth_authorize_fileop(kauth_cred_t credential, kauth_action_t action, uintptr_t
 int
 kauth_authorize_generic(kauth_cred_t credential, kauth_action_t action)
 {
-       if (credential == NULL)
+       if (credential == NULL) {
                panic("auth against NULL credential");
+       }
 
-       return(kauth_authorize_action(kauth_scope_generic, credential, action, 0, 0, 0, 0));
-               
+       return kauth_authorize_action(kauth_scope_generic, credential, action, 0, 0, 0, 0);
 }
 
 static int
 kauth_authorize_generic_callback(kauth_cred_t credential, __unused void *idata, kauth_action_t action,
-     __unused uintptr_t arg0, __unused uintptr_t arg1, __unused uintptr_t arg2, __unused uintptr_t arg3)
+    __unused uintptr_t arg0, __unused uintptr_t arg1, __unused uintptr_t arg2, __unused uintptr_t arg3)
 {
-       switch(action) {
+       switch (action) {
        case KAUTH_GENERIC_ISSUSER:
                /* XXX == 0 ? */
-               return((kauth_cred_getuid(credential) == 0) ?
-                   KAUTH_RESULT_ALLOW : KAUTH_RESULT_DENY);
+               return (kauth_cred_getuid(credential) == 0) ?
+                      KAUTH_RESULT_ALLOW : KAUTH_RESULT_DENY;
        }
 
        /* no explicit result, so defer to others in the chain */
-       return(KAUTH_RESULT_DEFER);
+       return KAUTH_RESULT_DEFER;
 }
 
 /*
@@ -623,7 +644,7 @@ kauth_acl_evaluate(kauth_cred_t cred, kauth_acl_eval_t eval)
        /* always allowed to do nothing */
        if (eval->ae_requested == 0) {
                eval->ae_result = KAUTH_RESULT_ALLOW;
-               return(0);
+               return 0;
        }
 
        eval->ae_residual = eval->ae_requested;
@@ -642,59 +663,66 @@ kauth_acl_evaluate(kauth_cred_t cred, kauth_acl_eval_t eval)
 
        KAUTH_DEBUG("    ACL - %d entries, initial residual %x", eval->ae_count, eval->ae_residual);
        for (i = 0, ace = eval->ae_acl; i < eval->ae_count; i++, ace++) {
-
                /*
                 * Skip inherit-only entries.
                 */
-               if (ace->ace_flags & KAUTH_ACE_ONLY_INHERIT)
+               if (ace->ace_flags & KAUTH_ACE_ONLY_INHERIT) {
                        continue;
+               }
 
                /*
                 * Expand generic rights, if appropriate.
                 */
                rights = ace->ace_rights;
-               if (rights & KAUTH_ACE_GENERIC_ALL)
+               if (rights & KAUTH_ACE_GENERIC_ALL) {
                        rights |= eval->ae_exp_gall;
-               if (rights & KAUTH_ACE_GENERIC_READ)
+               }
+               if (rights & KAUTH_ACE_GENERIC_READ) {
                        rights |= eval->ae_exp_gread;
-               if (rights & KAUTH_ACE_GENERIC_WRITE)
+               }
+               if (rights & KAUTH_ACE_GENERIC_WRITE) {
                        rights |= eval->ae_exp_gwrite;
-               if (rights & KAUTH_ACE_GENERIC_EXECUTE)
+               }
+               if (rights & KAUTH_ACE_GENERIC_EXECUTE) {
                        rights |= eval->ae_exp_gexec;
+               }
 
                /*
                 * Determine whether this entry applies to the current request.  This
                 * saves us checking the GUID if the entry has nothing to do with what
                 * we're currently doing.
                 */
-               switch(ace->ace_flags & KAUTH_ACE_KINDMASK) {
+               switch (ace->ace_flags & KAUTH_ACE_KINDMASK) {
                case KAUTH_ACE_PERMIT:
-                       if (!(eval->ae_residual & rights))
+                       if (!(eval->ae_residual & rights)) {
                                continue;
+                       }
                        break;
                case KAUTH_ACE_DENY:
-                       if (!(eval->ae_requested & rights))
+                       if (!(eval->ae_requested & rights)) {
                                continue;
+                       }
                        eval->ae_found_deny = TRUE;
                        break;
                default:
                        /* we don't recognise this ACE, skip it */
                        continue;
                }
-       
+
                /*
                 * Verify whether this entry applies to the credential.
                 */
                wkguid = kauth_wellknown_guid(&ace->ace_applicable);
-               switch(wkguid) {
+               switch (wkguid) {
                case KAUTH_WKG_OWNER:
                        applies = eval->ae_options & KAUTH_AEVAL_IS_OWNER;
                        break;
                case KAUTH_WKG_GROUP:
-                       if (!gotguid || (eval->ae_options & KAUTH_AEVAL_IN_GROUP_UNKNOWN))
+                       if (!gotguid || (eval->ae_options & KAUTH_AEVAL_IN_GROUP_UNKNOWN)) {
                                applies = ((ace->ace_flags & KAUTH_ACE_KINDMASK) == KAUTH_ACE_DENY);
-                       else
+                       } else {
                                applies = eval->ae_options & KAUTH_AEVAL_IN_GROUP;
+                       }
                        break;
                /* we short-circuit these here rather than wasting time calling the group membership code */
                case KAUTH_WKG_EVERYBODY:
@@ -709,7 +737,7 @@ kauth_acl_evaluate(kauth_cred_t cred, kauth_acl_eval_t eval)
                        applies = !gotguid ? 0 : kauth_guid_equal(&guid, &ace->ace_applicable);
                        KAUTH_DEBUG("    ACL - ACE applicable " K_UUID_FMT " caller " K_UUID_FMT " %smatched",
                            K_UUID_ARG(ace->ace_applicable), K_UUID_ARG(guid), applies ? "" : "not ");
-               
+
                        if (!applies) {
                                error = !gotguid ? ENOENT : kauth_cred_ismember_guid(cred, &ace->ace_applicable, &applies);
                                /*
@@ -720,7 +748,7 @@ kauth_acl_evaluate(kauth_cred_t cred, kauth_acl_eval_t eval)
                                 */
                                if (error != 0) {
                                        KAUTH_DEBUG("    ACL[%d] - can't get membership, making pessimistic assumption", i);
-                                       switch(ace->ace_flags & KAUTH_ACE_KINDMASK) {
+                                       switch (ace->ace_flags & KAUTH_ACE_KINDMASK) {
                                        case KAUTH_ACE_PERMIT:
                                                applies = 0;
                                                break;
@@ -735,13 +763,14 @@ kauth_acl_evaluate(kauth_cred_t cred, kauth_acl_eval_t eval)
                                KAUTH_DEBUG("    ACL - entry matches caller");
                        }
                }
-               if (!applies)
+               if (!applies) {
                        continue;
+               }
 
                /*
                 * Apply ACE to outstanding rights.
                 */
-               switch(ace->ace_flags & KAUTH_ACE_KINDMASK) {
+               switch (ace->ace_flags & KAUTH_ACE_KINDMASK) {
                case KAUTH_ACE_PERMIT:
                        /* satisfy any rights that this ACE grants */
                        eval->ae_residual = eval->ae_residual & ~rights;
@@ -749,7 +778,7 @@ kauth_acl_evaluate(kauth_cred_t cred, kauth_acl_eval_t eval)
                        /* all rights satisfied? */
                        if (eval->ae_residual == 0) {
                                eval->ae_result = KAUTH_RESULT_ALLOW;
-                               return(0);
+                               return 0;
                        }
                        break;
                case KAUTH_ACE_DENY:
@@ -757,7 +786,7 @@ kauth_acl_evaluate(kauth_cred_t cred, kauth_acl_eval_t eval)
                        if (eval->ae_requested & rights) {
                                KAUTH_DEBUG("    ACL[%d] - denying based on %x", i, rights);
                                eval->ae_result = KAUTH_RESULT_DENY;
-                               return(0);
+                               return 0;
                        }
                        break;
                default:
@@ -767,7 +796,7 @@ kauth_acl_evaluate(kauth_cred_t cred, kauth_acl_eval_t eval)
        }
        /* if not permitted, defer to other modes of authorisation */
        eval->ae_result = KAUTH_RESULT_DEFER;
-       return(0);
+       return 0;
 }
 
 /*
@@ -782,7 +811,7 @@ kauth_acl_evaluate(kauth_cred_t cred, kauth_acl_eval_t eval)
 int
 kauth_acl_inherit(vnode_t dvp, kauth_acl_t initial, kauth_acl_t *product, int isdir, vfs_context_t ctx)
 {
-       int     entries, error, index;
+       int     entries, error, index;
        unsigned int i;
        struct vnode_attr dva;
        kauth_acl_t inherit, result;
@@ -811,10 +840,11 @@ kauth_acl_inherit(vnode_t dvp, kauth_acl_t initial, kauth_acl_t *product, int is
                VATTR_WANTED(&dva, va_acl);
                if ((error = vnode_getattr(dvp, &dva, ctx)) != 0) {
                        KAUTH_DEBUG("    ERROR - could not get parent directory ACL for inheritance");
-                       return(error);
+                       return error;
                }
-               if (VATTR_IS_SUPPORTED(&dva, va_acl))
+               if (VATTR_IS_SUPPORTED(&dva, va_acl)) {
                        inherit = dva.va_acl;
+               }
        }
 
        /*
@@ -824,8 +854,9 @@ kauth_acl_inherit(vnode_t dvp, kauth_acl_t initial, kauth_acl_t *product, int is
        entries = 0;
        if (inherit != NULL) {
                for (i = 0; i < inherit->acl_entrycount; i++) {
-                       if (inherit->acl_ace[i].ace_flags & (isdir ? KAUTH_ACE_DIRECTORY_INHERIT : KAUTH_ACE_FILE_INHERIT))
+                       if (inherit->acl_ace[i].ace_flags & (isdir ? KAUTH_ACE_DIRECTORY_INHERIT : KAUTH_ACE_FILE_INHERIT)) {
                                entries++;
+                       }
                }
        }
 
@@ -838,10 +869,11 @@ kauth_acl_inherit(vnode_t dvp, kauth_acl_t initial, kauth_acl_t *product, int is
        }
 
        if (initial != NULL) {
-               if (initial->acl_entrycount != KAUTH_FILESEC_NOACL)
+               if (initial->acl_entrycount != KAUTH_FILESEC_NOACL) {
                        entries += initial->acl_entrycount;
-               else
+               } else {
                        initial = NULL;
+               }
        }
 
        /*
@@ -855,7 +887,7 @@ kauth_acl_inherit(vnode_t dvp, kauth_acl_t initial, kauth_acl_t *product, int is
                error = 0;
                goto out;
        }
-       
+
        /*
         * Allocate the result buffer.
         */
@@ -912,9 +944,10 @@ kauth_acl_inherit(vnode_t dvp, kauth_acl_t initial, kauth_acl_t *product, int is
        KAUTH_DEBUG("    INHERIT - product ACL has %d entries", index);
        error = 0;
 out:
-       if (inherit != NULL)
+       if (inherit != NULL) {
                kauth_acl_free(inherit);
-       return(error);
+       }
+       return error;
 }
 
 /*
@@ -948,12 +981,11 @@ out:
 int
 kauth_copyinfilesec(user_addr_t xsecurity, kauth_filesec_t *xsecdestpp)
 {
-       user_addr_t uaddr, known_bound;
        int error;
        kauth_filesec_t fsec;
-       u_int32_t count;
+       size_t count;
        size_t copysize;
-       
+
        error = 0;
        fsec = NULL;
 
@@ -965,20 +997,30 @@ kauth_copyinfilesec(user_addr_t xsecurity, kauth_filesec_t *xsecdestpp)
         *
         * The upper bound must be less than KAUTH_ACL_MAX_ENTRIES.  The
         * value here is fairly arbitrary.  It's ok to have a zero count.
+        *
+        * Because we're just using these values to make a guess about the
+        * number of entries, the actual address doesn't matter, only their
+        * relative offsets into the page.  We take advantage of this to
+        * avoid an overflow in the rounding step (this is a user-provided
+        * parameter, so caution pays off).
         */
-       known_bound = xsecurity +  KAUTH_FILESEC_SIZE(0);
-       uaddr = mach_vm_round_page(known_bound);
-       count = (uaddr - known_bound) / sizeof(struct kauth_ace);
-       if (count > 32)
+       {
+               user_addr_t known_bound = (xsecurity & PAGE_MASK) + KAUTH_FILESEC_SIZE(0);
+               user_addr_t uaddr = (user_addr_t)mach_vm_round_page(known_bound);
+               count = (uaddr - known_bound) / sizeof(struct kauth_ace);
+       }
+       if (count > 32) {
                count = 32;
+       }
 restart:
-       if ((fsec = kauth_filesec_alloc(count)) == NULL) {
+       if ((fsec = kauth_filesec_alloc((int)count)) == NULL) {
                error = ENOMEM;
                goto out;
        }
        copysize = KAUTH_FILESEC_SIZE(count);
-       if ((error = copyin(xsecurity, (caddr_t)fsec, copysize)) != 0)
+       if ((error = copyin(xsecurity, (caddr_t)fsec, copysize)) != 0) {
                goto out;
+       }
 
        /* validate the filesec header */
        if (fsec->fsec_magic != KAUTH_FILESEC_MAGIC) {
@@ -1000,16 +1042,17 @@ restart:
                kauth_filesec_free(fsec);
                goto restart;
        }
-       
+
 out:
        if (error) {
-               if (fsec)
+               if (fsec) {
                        kauth_filesec_free(fsec);
+               }
        } else {
                *xsecdestpp = fsec;
                AUDIT_ARG(opaque, fsec, copysize);
        }
-       return(error);
+       return error;
 }
 
 /*
@@ -1034,11 +1077,12 @@ out:
 kauth_filesec_t
 kauth_filesec_alloc(int count)
 {
-       kauth_filesec_t fsp;
-       
+       kauth_filesec_t fsp;
+
        /* if the caller hasn't given us a valid size hint, assume the worst */
-       if ((count < 0) || (count > KAUTH_ACL_MAX_ENTRIES))
-               return(NULL);
+       if ((count < 0) || (count > KAUTH_ACL_MAX_ENTRIES)) {
+               return NULL;
+       }
 
        MALLOC(fsp, kauth_filesec_t, KAUTH_FILESEC_SIZE(count), M_KAUTH, M_WAITOK);
        if (fsp != NULL) {
@@ -1048,8 +1092,8 @@ kauth_filesec_alloc(int count)
                fsp->fsec_entrycount = KAUTH_FILESEC_NOACL;
                fsp->fsec_flags = 0;
        }
-       return(fsp);
-}      
+       return fsp;
+}
 
 /*
  * Free a kauth_filesec_t that was previous allocated, either by a direct
@@ -1067,16 +1111,18 @@ void
 kauth_filesec_free(kauth_filesec_t fsp)
 {
 #ifdef KAUTH_DEBUG_ENABLE
-       if (fsp == KAUTH_FILESEC_NONE)
+       if (fsp == KAUTH_FILESEC_NONE) {
                panic("freeing KAUTH_FILESEC_NONE");
-       if (fsp == KAUTH_FILESEC_WANTED)
+       }
+       if (fsp == KAUTH_FILESEC_WANTED) {
                panic("freeing KAUTH_FILESEC_WANTED");
+       }
 #endif
        FREE(fsp, M_KAUTH);
 }
 
 /*
- * Set the endianness of a filesec and an ACL; if 'acl' is NULL, use the 
+ * Set the endianness of a filesec and an ACL; if 'acl' is NULL, use the
  * ACL interior to 'fsec' instead.  If the endianness doesn't change, then
  * this function will have no effect.
  *
@@ -1094,17 +1140,19 @@ kauth_filesec_free(kauth_filesec_t fsp)
 void
 kauth_filesec_acl_setendian(int kendian, kauth_filesec_t fsec, kauth_acl_t acl)
 {
-       uint32_t        compare_magic = KAUTH_FILESEC_MAGIC;
-       uint32_t        invert_magic = ntohl(KAUTH_FILESEC_MAGIC);
-       uint32_t        compare_acl_entrycount;
-       uint32_t        i;
+       uint32_t        compare_magic = KAUTH_FILESEC_MAGIC;
+       uint32_t        invert_magic = ntohl(KAUTH_FILESEC_MAGIC);
+       uint32_t        compare_acl_entrycount;
+       uint32_t        i;
 
-       if (compare_magic == invert_magic)
+       if (compare_magic == invert_magic) {
                return;
+       }
 
        /* If no ACL, use ACL interior to 'fsec' instead */
-       if (acl == NULL)
+       if (acl == NULL) {
                acl = &fsec->fsec_acl;
+       }
 
        compare_acl_entrycount = acl->acl_entrycount;
 
@@ -1113,21 +1161,23 @@ kauth_filesec_acl_setendian(int kendian, kauth_filesec_t fsec, kauth_acl_t acl)
         * are valid.  The following switch and tests effectively reject
         * conversions on invalid magic numbers as a desirable side effect.
         */
-       switch(kendian) {
-       case KAUTH_ENDIAN_HOST:         /* not in host, convert to host */
-               if (fsec->fsec_magic != invert_magic)
+       switch (kendian) {
+       case KAUTH_ENDIAN_HOST:         /* not in host, convert to host */
+               if (fsec->fsec_magic != invert_magic) {
                        return;
+               }
                /* acl_entrycount is byteswapped */
                compare_acl_entrycount = ntohl(acl->acl_entrycount);
                break;
-       case KAUTH_ENDIAN_DISK:         /* not in disk, convert to disk */
-               if (fsec->fsec_magic != compare_magic)
+       case KAUTH_ENDIAN_DISK:         /* not in disk, convert to disk */
+               if (fsec->fsec_magic != compare_magic) {
                        return;
+               }
                break;
-       default:                        /* bad argument */
+       default:                        /* bad argument */
                return;
        }
-       
+
        /* We are go for conversion */
        fsec->fsec_magic = ntohl(fsec->fsec_magic);
        acl->acl_entrycount = ntohl(acl->acl_entrycount);
@@ -1140,7 +1190,7 @@ kauth_filesec_acl_setendian(int kendian, kauth_filesec_t fsec, kauth_acl_t acl)
                        acl->acl_ace[i].ace_rights = ntohl(acl->acl_ace[i].ace_rights);
                }
        }
- }
+}
 
 
 /*
@@ -1149,33 +1199,39 @@ kauth_filesec_acl_setendian(int kendian, kauth_filesec_t fsec, kauth_acl_t acl)
 kauth_acl_t
 kauth_acl_alloc(int count)
 {
-       kauth_acl_t     aclp;
-       
+       kauth_acl_t     aclp;
+
        /* if the caller hasn't given us a valid size hint, assume the worst */
-       if ((count < 0) || (count > KAUTH_ACL_MAX_ENTRIES))
-               return(NULL);
+       if ((count < 0) || (count > KAUTH_ACL_MAX_ENTRIES)) {
+               return NULL;
+       }
 
        MALLOC(aclp, kauth_acl_t, KAUTH_ACL_SIZE(count), M_KAUTH, M_WAITOK);
        if (aclp != NULL) {
                aclp->acl_entrycount = 0;
                aclp->acl_flags = 0;
        }
-       return(aclp);
-}      
+       return aclp;
+}
 
 void
 kauth_acl_free(kauth_acl_t aclp)
 {
-       FREE(aclp, M_KAUTH);
+       /*
+        * It's possible this may have have been allocated in a kext using
+        * MALLOC. Using KHEAP_ANY will allow us to free it here.
+        */
+       kheap_free_addr(KHEAP_ANY, aclp);
 }
 
 
 /*
  * WARNING - caller must hold KAUTH_SCOPELOCK
  */
-static int kauth_add_callback_to_scope(kauth_scope_t sp, kauth_listener_t klp)
+static int
+kauth_add_callback_to_scope(kauth_scope_t sp, kauth_listener_t klp)
 {
-       int             i;
+       int             i;
 
        for (i = 0; i < KAUTH_SCOPE_MAX_LISTENERS; i++) {
                if (sp->ks_listeners[i].kll_listenerp == NULL) {
@@ -1183,8 +1239,8 @@ static int kauth_add_callback_to_scope(kauth_scope_t sp, kauth_listener_t klp)
                        sp->ks_listeners[i].kll_idata = klp->kl_idata;
                        sp->ks_listeners[i].kll_listenerp = klp;
                        sp->ks_flags |= KS_F_HAS_LISTENERS;
-                       return(0);
+                       return 0;
                }
        }
-       return(ENOSPC);
+       return ENOSPC;
 }