]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_authorization.c
xnu-792.22.5.tar.gz
[apple/xnu.git] / bsd / kern / kern_authorization.c
index b5dbe67061af387bb82c1c1dc1c93440c2e64441..93eebc05d0cfe68253eaa972b96d15eac2d0fd00 100644 (file)
@@ -1,23 +1,29 @@
 /*
  * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * 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
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * 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.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * 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_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
 /*
@@ -858,14 +864,32 @@ out:
 
 /*
  * Optimistically copy in a kauth_filesec structure
+ *
  * Parameters: xsecurity               user space kauth_filesec_t
- *             xsecdstpp               pointer to kauth_filesec_t
+ *             xsecdstpp               pointer to kauth_filesec_t to be
+ *                                     modified to contain the contain a
+ *                                     pointer to an allocated copy of the
+ *                                     user space argument
+ *
+ * Returns:    0                       Success
+ *             ENOMEM                  Insufficient memory for the copy.
+ *             EINVAL                  The user space data was invalid, or
+ *                                     there were too many ACE entries.
+ *             EFAULT                  The user space address was invalid;
+ *                                     this may mean 'fsec_entrycount' in
+ *                                     the user copy is corrupt/incorrect.
+ *
+ * Implicit returns: xsecdestpp, modified (only if successful!)
+ *
+ * Notes:      The returned kauth_filesec_t is in host byte order
  *
- * Returns: 0 on success, EINVAL or EFAULT depending on failure mode.
- * Modifies: xsecdestpp, which contains a pointer to an allocated
- *          and copied-in kauth_filesec_t
+ *             The caller is responsible for freeing the returned
+ *             kauth_filesec_t in the success case using the function
+ *             kauth_filesec_free()
+ *
+ *             Our largest initial guess is 32; this needs to move to
+ *             a manifest constant in <sys/kauth.h>.
  */
-
 int
 kauth_copyinfilesec(user_addr_t xsecurity, kauth_filesec_t *xsecdestpp)
 {
@@ -913,6 +937,7 @@ restart:
        if ((fsec->fsec_entrycount != KAUTH_FILESEC_NOACL) &&
            (fsec->fsec_entrycount > count)) {
                if (fsec->fsec_entrycount > KAUTH_ACL_MAX_ENTRIES) {
+                       /* XXX This should be E2BIG */
                        error = EINVAL;
                        goto out;
                }
@@ -932,7 +957,23 @@ out:
 }
 
 /*
- * Allocate a filesec structure.
+ * Allocate a block of memory containing a filesec structure, immediately
+ * followed by 'count' kauth_ace structures.
+ *
+ * Parameters: count                   Number of kauth_ace structures needed
+ *
+ * Returns:    !NULL                   A pointer to the allocated block
+ *             NULL                    Invalid 'count' or insufficient memory
+ *
+ * Notes:      Returned memory area assumes that the structures are packed
+ *             densely, so this function may only be used by code that also
+ *             assumes no padding following structures.
+ *
+ *             The returned structure must be freed by the caller using the
+ *             function kauth_filesec_free(), in case we decide to use an
+ *             allocation mechanism that is aware of the object size at some
+ *             point, since the object size is only available by introspecting
+ *             the object itself.
  */
 kauth_filesec_t
 kauth_filesec_alloc(int count)
@@ -954,6 +995,18 @@ kauth_filesec_alloc(int count)
        return(fsp);
 }      
 
+/*
+ * Free a kauth_filesec_t that was previous allocated, either by a direct
+ * call to kauth_filesec_alloc() or by calling a function that calls it.
+ *
+ * Parameters: fsp                     kauth_filesec_t to free
+ *
+ * Returns:    (void)
+ *
+ * Notes:      The kauth_filesec_t to be freed is assumed to be in host
+ *             byte order so that this function can introspect it in the
+ *             future to determine its size, if necesssary.
+ */
 void
 kauth_filesec_free(kauth_filesec_t fsp)
 {
@@ -966,6 +1019,73 @@ kauth_filesec_free(kauth_filesec_t fsp)
        FREE(fsp, M_KAUTH);
 }
 
+/*
+ * 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.
+ *
+ * Parameters: kendian                 The endianness to set; this is either
+ *                                     KAUTH_ENDIAN_HOST or KAUTH_ENDIAN_DISK.
+ *             fsec                    The filesec to convert.
+ *             acl                     The ACL to convert (optional)
+ *
+ * Returns:    (void)
+ *
+ * Notes:      We use ntohl() because it has a transitive property on Intel
+ *             machines and no effect on PPC mancines.  This guarantees us
+ *             that the swapping only occurs if the endiannes is wrong.
+ */
+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;
+
+       if (compare_magic == invert_magic)
+               return;
+
+       /* If no ACL, use ACL interior to 'fsec' instead */
+       if (acl == NULL)
+               acl = &fsec->fsec_acl;
+
+       compare_acl_entrycount = acl->acl_entrycount;
+
+       /*
+        * Only convert what needs to be converted, and only if the arguments
+        * 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)
+                       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)
+                       return;
+               break;
+       default:                        /* bad argument */
+               return;
+       }
+       
+       /* We are go for conversion */
+       fsec->fsec_magic = ntohl(fsec->fsec_magic);
+       acl->acl_entrycount = ntohl(acl->acl_entrycount);
+       if (compare_acl_entrycount != KAUTH_FILESEC_NOACL) {
+               acl->acl_flags = ntohl(acl->acl_flags);
+
+               /* swap ACE rights and flags */
+               for (i = 0; i < compare_acl_entrycount; i++) {
+                       acl->acl_ace[i].ace_flags = ntohl(acl->acl_ace[i].ace_flags);
+                       acl->acl_ace[i].ace_rights = ntohl(acl->acl_ace[i].ace_rights);
+               }
+       }
+ }
+
 
 /*
  * Allocate an ACL buffer.