From owner-p4-projects@FreeBSD.ORG Thu Feb 5 07:21:17 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id D306316A4D0; Thu, 5 Feb 2004 07:21:16 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8772A16A4CE for ; Thu, 5 Feb 2004 07:21:16 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3200143D67 for ; Thu, 5 Feb 2004 07:20:08 -0800 (PST) (envelope-from areisse@nailabs.com) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.10/8.12.10) with ESMTP id i15FK70B042375 for ; Thu, 5 Feb 2004 07:20:07 -0800 (PST) (envelope-from areisse@nailabs.com) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.10/8.12.10/Submit) id i15FK7dh042372 for perforce@freebsd.org; Thu, 5 Feb 2004 07:20:07 -0800 (PST) (envelope-from areisse@nailabs.com) Date: Thu, 5 Feb 2004 07:20:07 -0800 (PST) Message-Id: <200402051520.i15FK7dh042372@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to areisse@nailabs.com using -f From: Andrew Reisse To: Perforce Change Reviews Subject: PERFORCE change 46537 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Feb 2004 15:21:17 -0000 http://perforce.freebsd.org/chv.cgi?CH=46537 Change 46537 by areisse@areisse_ibook on 2004/02/05 07:19:54 Initial support for label handles that use the same namespace as ports. The label cannot be changed after creation, allowing them to be shared in the future. A new access control query, mac_check_port_access uses ports (or label handles) for both the subject and object. Affected files ... .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/conf/files#3 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_entry.h#2 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_init.c#2 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_labelh.c#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_labelh.h#1 add .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_object.c#3 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_object.h#2 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_right.c#3 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/mach_port.c#3 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/kern/task.c#3 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/mach/port.h#2 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/mach/security.defs#2 edit Differences ... ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/conf/files#3 (text+ko) ==== @@ -135,6 +135,7 @@ osfmk/ipc/ipc_space.c standard osfmk/ipc/ipc_splay.c standard osfmk/ipc/ipc_table.c standard +osfmk/ipc/ipc_labelh.c standard osfmk/ipc/mach_debug.c standard osfmk/ipc/mach_msg.c standard osfmk/ipc/mach_port.c standard ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_entry.h#2 (text+ko) ==== @@ -114,7 +114,7 @@ #define IE_BITS_UREFS_MASK 0x0000ffff /* 16 bits of user-reference */ #define IE_BITS_UREFS(bits) ((bits) & IE_BITS_UREFS_MASK) -#define IE_BITS_TYPE_MASK 0x001f0000 /* 5 bits of capability type */ +#define IE_BITS_TYPE_MASK 0x003f0000 /* 6 bits of capability type */ #define IE_BITS_TYPE(bits) ((bits) & IE_BITS_TYPE_MASK) #define IE_BITS_COLLISION 0x00800000 /* 1 bit for collisions */ ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_init.c#2 (text+ko) ==== @@ -76,6 +76,7 @@ #include #include #include /* NDR_record */ +#include vm_map_t ipc_kernel_map; vm_size_t ipc_kernel_map_size = 1024 * 1024; @@ -153,6 +154,12 @@ /* make it exhaustible */ zone_change(ipc_object_zones[IOT_PORT_SET], Z_EXHAUST, TRUE); + ipc_object_zones[IOT_LABELH] = + zinit(sizeof(struct ipc_labelh), + ipc_port_max * sizeof(struct ipc_labelh), + sizeof(struct ipc_labelh), + "label handles"); + /* create special spaces */ kr = ipc_space_create_special(&ipc_space_kernel); ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_object.c#3 (text+ko) ==== @@ -72,6 +72,7 @@ #include #include #include +#include zone_t ipc_object_zones[IOT_NUMBER]; @@ -972,6 +973,19 @@ return kr; } +struct label *io_getlabel (ipc_object_t objp) +{ + switch (io_otype (objp)) + { + case IOT_PORT: + return &((ipc_port_t) objp)->ip_label; + + case IOT_LABELH: + return &((ipc_labelh_t) objp)->lh_label; + } + return NULL; +} + #if MACH_ASSERT /* * Check whether the object is a port if so, free it. But @@ -992,7 +1006,11 @@ #ifdef MAC mac_destroy_port_label (&port->ip_label); -#endif + } + else if (otype == IOT_LABELH) { + ipc_labelh_t lh = (ipc_labelh_t) object; + mac_destroy_port_label (&lh->lh_label); +#endif } zfree(ipc_object_zones[otype], (vm_offset_t) object); } ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_object.h#2 (text+ko) ==== @@ -133,7 +133,8 @@ */ #define IOT_PORT 0 #define IOT_PORT_SET 1 -#define IOT_NUMBER 2 /* number of types used */ +#define IOT_LABELH 2 /* a label handle */ +#define IOT_NUMBER 3 /* number of types used */ extern zone_t ipc_object_zones[IOT_NUMBER]; @@ -223,6 +224,43 @@ (io)->io_references--; \ MACRO_END +/* There doesn't seem to be an established lock order for two + ipc_objects of the same type */ +extern inline void io_lock2 (ipc_object_t a, ipc_object_t b) +{ + if (a == b) + io_lock (a); + else if (a < b) + { + io_lock (a); + io_lock (b); + } + else + { + io_lock (b); + io_lock (a); + } +} + +extern inline void io_unlock2 (ipc_object_t a, ipc_object_t b) +{ + if (a == b) + io_unlock (a); + else if (a < b) + { + io_unlock (b); + io_unlock (a); + } + else + { + io_unlock (a); + io_unlock (b); + } +} + +struct label; +extern struct label *io_getlabel (ipc_object_t obj); + /* * Exported interfaces */ ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/ipc_right.c#3 (text+ko) ==== @@ -551,6 +551,10 @@ break; } + case MACH_PORT_TYPE_LABELH: + ipc_object_release (entry->ie_object); + break; + case MACH_PORT_TYPE_SEND: case MACH_PORT_TYPE_RECEIVE: case MACH_PORT_TYPE_SEND_RECEIVE: @@ -665,6 +669,14 @@ break; } + case MACH_PORT_TYPE_LABELH: { + ipc_object_t lh = entry->ie_object; + entry->ie_object = IO_NULL; + ipc_entry_dealloc (space, name, entry); + ipc_object_release (lh); + break; + } + case MACH_PORT_TYPE_SEND: case MACH_PORT_TYPE_RECEIVE: case MACH_PORT_TYPE_SEND_RECEIVE: @@ -999,6 +1011,21 @@ break; } + case MACH_PORT_RIGHT_LABELH: { + ipc_object_t lh = entry->ie_object; + if ((bits & MACH_PORT_TYPE_LABELH) == 0) + goto invalid_right; + if (delta == 0) + goto success; + else if (delta != -1) + goto invalid_value; + entry->ie_object = IO_NULL; + ipc_entry_dealloc (space, name, entry); + ipc_object_release (lh); + is_write_unlock (space); + break; + } + case MACH_PORT_RIGHT_RECEIVE: { ipc_port_t port; ipc_port_t dnrequest = IP_NULL; ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/ipc/mach_port.c#3 (text+ko) ==== @@ -81,6 +81,7 @@ #include #include #include +#include #include /* @@ -1753,7 +1754,7 @@ return kr; } -/* Don't pass something other than a port, it doesn't check the type yet. */ +/* also works on label handles */ kern_return_t mach_get_port_label (ipc_space_t space, mach_port_name_t name, vm_offset_t outlabel) @@ -1771,6 +1772,9 @@ if (kr != KERN_SUCCESS) return kr; + switch (io_otype (entry->ie_object)) + { + case IOT_PORT:{ ipc_port_t port = (ipc_port_t) entry->ie_object; ip_lock (port); @@ -1778,7 +1782,22 @@ mac_externalize_port_label (&port->ip_label, "sebsd", outlabel, 512, 0); ip_unlock (port); - return kr; + } + return 0; + + case IOT_LABELH: + { + ipc_labelh_t lh = (ipc_labelh_t) entry->ie_object; + io_lock (&lh->lh_object); + is_write_unlock (space); + mac_externalize_port_label (&lh->lh_label, "sebsd", outlabel, 512, 0); + io_unlock (&lh->lh_object); + } + return 0; + } + + is_write_unlock (space); + return KERN_INVALID_ARGUMENT; } kern_return_t @@ -1803,6 +1822,11 @@ if (kr != KERN_SUCCESS) return kr; + if (IOT_PORT != io_otype(entry->ie_object)) { + is_write_unlock (space); + return KERN_INVALID_RIGHT; + } + ipc_port_t port = (ipc_port_t) entry->ie_object; ip_lock (port); ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/kern/task.c#3 (text+ko) ==== @@ -1824,8 +1824,9 @@ { struct label subjl; ipc_entry_t entry; - ipc_port_t objp; + ipc_object_t objp; kern_return_t kr; + struct label *objl; if (space == IS_NULL || space->is_task == NULL) return KERN_INVALID_TASK; @@ -1848,18 +1849,71 @@ return kr; } - objp = (ipc_port_t) entry->ie_object; + objp = entry->ie_object; + io_lock (objp); + is_write_unlock (space); + + objl = io_getlabel (objp); + if (objl == NULL) { + io_unlock (objp); + return KERN_INVALID_ARGUMENT; + } + + rc = mac_check_service_access (&subjl, objl, serv, perm); + io_unlock (objp); + + mac_destroy_task_label (&subjl); + if (rc == /*EINVAL*/ 22) + return KERN_INVALID_ARGUMENT; + else if (rc != 0) + return KERN_NO_ACCESS; + else + return 0; +} + +kern_return_t +mac_check_port_access (ipc_space_t space, mach_port_name_t sub, mach_port_name_t obj, + vm_offset_t serv, vm_offset_t perm) +{ + ipc_entry_t subi, obji; + ipc_object_t subp, objp; + kern_return_t kr; + struct label *objl, *subl; + int rc; + + if (space == IS_NULL || space->is_task == NULL) + return KERN_INVALID_TASK; + + if (!MACH_PORT_VALID(obj) || !MACH_PORT_VALID(sub)) + return KERN_INVALID_NAME; + + kr = ipc_right_lookup_two_write(space, obj, &obji, sub, &subi); + if (kr != KERN_SUCCESS) + return kr; - ip_lock (objp); - rc = mac_check_service_access (&subjl, &objp->ip_label, serv, perm); - ip_unlock (objp); + objp = obji->ie_object; + subp = subi->ie_object; is_write_unlock (space); - mac_destroy_task_label (&subjl); + io_lock2 (objp, subp); + objl = io_getlabel (objp); + if (objl == NULL) + goto errout; + subl = io_getlabel (subp); + if (subl == NULL) + goto errout; + + rc = mac_check_service_access (subl, objl, serv, perm); + io_unlock2 (subp, objp); + if (rc == /*EINVAL*/ 22) return KERN_INVALID_ARGUMENT; else if (rc != 0) return KERN_NO_ACCESS; else return 0; + + errout: + io_unlock2 (subp, objp); + return KERN_INVALID_ARGUMENT; } ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/mach/port.h#2 (text+ko) ==== @@ -192,7 +192,8 @@ #define MACH_PORT_RIGHT_SEND_ONCE ((mach_port_right_t) 2) #define MACH_PORT_RIGHT_PORT_SET ((mach_port_right_t) 3) #define MACH_PORT_RIGHT_DEAD_NAME ((mach_port_right_t) 4) -#define MACH_PORT_RIGHT_NUMBER ((mach_port_right_t) 5) +#define MACH_PORT_RIGHT_LABELH ((mach_port_right_t) 5) +#define MACH_PORT_RIGHT_NUMBER ((mach_port_right_t) 6) typedef natural_t mach_port_type_t; typedef mach_port_type_t *mach_port_type_array_t; @@ -206,6 +207,7 @@ #define MACH_PORT_TYPE_SEND_ONCE MACH_PORT_TYPE(MACH_PORT_RIGHT_SEND_ONCE) #define MACH_PORT_TYPE_PORT_SET MACH_PORT_TYPE(MACH_PORT_RIGHT_PORT_SET) #define MACH_PORT_TYPE_DEAD_NAME MACH_PORT_TYPE(MACH_PORT_RIGHT_DEAD_NAME) +#define MACH_PORT_TYPE_LABELH MACH_PORT_TYPE(MACH_PORT_RIGHT_LABELH) /* Convenient combinations. */ ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/osfmk/mach/security.defs#2 (text+ko) ==== @@ -24,6 +24,8 @@ routine mach_get_task_label(task : task_t; out label : labelstr_t); +/* also works on label handles */ + routine mach_get_port_label(task : ipc_space_t; name : mach_port_name_t; out label : labelstr_t); @@ -45,3 +47,15 @@ object : mach_port_name_t; service : labelstr_t; perm : labelstr_t); + +/* Uses ports (or label handles) for both subject and object. */ + +routine mac_check_port_access(task : ipc_space_t; + subject : mach_port_name_t; + object : mach_port_name_t; + service : labelstr_t; + perm : labelstr_t); + +routine mac_label_new(task : ipc_space_t; + out name : mach_port_name_t; + label : labelstr_t);