From owner-p4-projects@FreeBSD.ORG Thu Jun 16 18:24:45 2005 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id AAFAA16A420; Thu, 16 Jun 2005 18:24:44 +0000 (GMT) X-Original-To: perforce@freebsd.org 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 6D4AB16A41C for ; Thu, 16 Jun 2005 18:24:44 +0000 (GMT) (envelope-from areisse@nailabs.com) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 46D4043D49 for ; Thu, 16 Jun 2005 18:24:44 +0000 (GMT) (envelope-from areisse@nailabs.com) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j5GIOiEj041858 for ; Thu, 16 Jun 2005 18:24:44 GMT (envelope-from areisse@nailabs.com) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j5GIOhPD041855 for perforce@freebsd.org; Thu, 16 Jun 2005 18:24:43 GMT (envelope-from areisse@nailabs.com) Date: Thu, 16 Jun 2005 18:24:43 GMT Message-Id: <200506161824.j5GIOhPD041855@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 Cc: Subject: PERFORCE change 78641 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 16 Jun 2005 18:24:45 -0000 http://perforce.freebsd.org/chv.cgi?CH=78641 Change 78641 by areisse@areisse_ibook on 2005/06/16 18:24:09 Many label handle related fixes: -Use the zone allocator and properly free the ports. -Locking fixes. -Move the security.defs calls to a new file, kern/security.c. Affected files ... .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/conf/files#2 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_init.c#3 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.c#3 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.h#3 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_object.c#3 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_object.h#3 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/mach_port.c#3 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/ipc_kobject.c#2 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/security.c#1 add .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/task.c#3 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/task.h#3 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/mach/security.defs#2 edit Differences ... ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/conf/files#2 (text+ko) ==== @@ -168,6 +168,7 @@ osfmk/kern/processor.c standard osfmk/kern/queue.c standard osfmk/kern/sched_prim.c standard +osfmk/kern/security.c standard osfmk/kern/sscanf.c standard osfmk/kern/startup.c standard osfmk/kern/sync_lock.c standard ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_init.c#3 (text+ko) ==== @@ -165,6 +165,12 @@ /* make it exhaustible */ zone_change(ipc_object_zones[IOT_PORT_SET], Z_EXHAUST, TRUE); + ipc_labelh_zone = + 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/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.c#3 (text+ko) ==== @@ -4,6 +4,8 @@ #include #include +zone_t ipc_labelh_zone; + kern_return_t mac_label_new (ipc_space_t task, mach_port_name_t *name, vm_offset_t labelstr) { @@ -21,7 +23,7 @@ port = ipc_port_alloc_kernel(); - lh = kalloc(sizeof(struct ipc_labelh)); + lh = (ipc_labelh_t) zalloc(ipc_labelh_zone); io_lock_init(lh); lh->lh_port = port; lh->lh_type = 0; @@ -44,7 +46,7 @@ */ ipc_labelh_t labelh_new () { - ipc_labelh_t lh = (ipc_labelh_t) kalloc(sizeof(struct ipc_labelh)); + ipc_labelh_t lh = (ipc_labelh_t) zalloc(ipc_labelh_zone); io_lock_init(lh); lh->lh_port = ipc_port_alloc_kernel(); lh->lh_type = 0; @@ -58,7 +60,7 @@ ipc_labelh_t labelh_duplicate (ipc_labelh_t old) { - ipc_labelh_t lh = (ipc_labelh_t) kalloc(sizeof(struct ipc_labelh)); + ipc_labelh_t lh = (ipc_labelh_t) zalloc(ipc_labelh_zone); io_lock_init(lh); lh->lh_port = ipc_port_alloc_kernel(); lh->lh_type = 0; @@ -93,7 +95,7 @@ return lh; } -void labelh_release (ipc_labelh_t lh) +void labelh_release(ipc_labelh_t lh) { lh_lock(lh); lh_release(lh); @@ -102,6 +104,7 @@ void lh_free (ipc_labelh_t lh) { - ipc_object_release(lh->lh_port); + ipc_object_release(&lh->lh_port->ip_object); mac_destroy_port_label (&lh->lh_label); + zfree(ipc_labelh_zone, (vm_offset_t)lh); } ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.h#3 (text+ko) ==== @@ -32,6 +32,8 @@ (lh)->lh_references--; \ MACRO_END +extern zone_t ipc_labelh_zone; + #define lh_lock io_lock #define lh_unlock io_unlock ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_object.c#3 (text+ko) ==== @@ -995,6 +995,11 @@ * that takes a security label as a parameter. In this case, we want * to use the label stored in the label handle and not the label on its * port. + * + * The port should be locked for this call. The lock protecting + * label handle contents should not be necessary, as they can only + * be modified when a label handle with one reference is a task label. + * User allocated label handles can never be modified. */ struct label *io_getlabel (ipc_object_t objp) ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_object.h#3 (text+ko) ==== @@ -226,42 +226,15 @@ (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); - } -} +/* + * Retrieve a label for use in a kernel call that takes a security + * label as a parameter. If necessary, io_getlabel acquires internal + * (not io_lock) locks, and io_unlocklabel releases them. + */ -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); +#define io_unlocklabel(obj) /* * Exported interfaces ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/mach_port.c#3 (text+ko) ==== @@ -1792,6 +1792,7 @@ mac_externalize_port_label (l, policies, outlabel, 512, 0); + io_unlocklabel(entry->ie_object); io_unlock (entry->ie_object); return 0; } ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/ipc_kobject.c#2 (text+ko) ==== @@ -88,6 +88,7 @@ #include #include #include +#include #include @@ -515,6 +516,10 @@ host_notify_port_destroy(port); break; + case IKOT_LABELH: + labelh_release(port->ip_kobject); + break; + default: break; } ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/task.c#3 (text+ko) ==== @@ -1756,6 +1756,31 @@ return (current_task_fast()); } +/* + * Protect 2 task labels against modification by adding a reference on + * both label handles. The locks do not actually have to be held while + * using the labels as only labels with one reference can be modified + * in place. + */ + +void +tasklabel_lock2( + task_t a, + task_t b) +{ + labelh_reference(a->label); + labelh_reference(b->label); +} + +void +tasklabel_unlock2( + task_t a, + task_t b) +{ + labelh_release(a->label); + labelh_release(b->label); +} + void mac_update_task_label (struct label *pl, struct task *t) { tasklabel_lock (t); @@ -1776,160 +1801,3 @@ tasklabel_unlock (pt); } -kern_return_t -mach_get_task_label_text( - task_t t, - labelstr_t policies, - labelstr_t outl) -{ - tasklabel_lock (t); - mac_externalize_task_label (&t->maclabel, policies, outl, 512, 0); - tasklabel_unlock (t); - - return KERN_SUCCESS; -} - -int mac_check_task_service_access (task_t self, task_t obj, const char * perm) -{ - tasklabel_lock2 (self, obj); - - int rc = mac_check_service_access (&self->maclabel, &obj->maclabel, - "mach_task", perm); - - tasklabel_unlock2 (self, obj); - - return rc; -} - -kern_return_t -mac_check_named_access (ipc_space_t space, labelstr_t subj, labelstr_t obj, - labelstr_t serv, labelstr_t perm) -{ - struct label subjl, objl; - - mac_init_task_label (&subjl); - int rc = mac_internalize_port_label (&subjl, subj); - if (rc) - { - mac_destroy_task_label (&subjl); - return KERN_INVALID_ARGUMENT; - } - mac_init_task_label (&objl); - rc = mac_internalize_port_label (&objl, obj); - if (rc) - { - mac_destroy_task_label (&subjl); - mac_destroy_task_label (&objl); - return KERN_INVALID_ARGUMENT; - } - - rc = mac_check_service_access (&subjl, &objl, serv, perm); - mac_destroy_task_label (&subjl); - mac_destroy_task_label (&objl); - if (rc == /*EINVAL*/ 22) - return KERN_INVALID_ARGUMENT; - else if (rc != 0) - return KERN_NO_ACCESS; - else - return 0; -} - -kern_return_t -mac_check_name_port_access (ipc_space_t space, labelstr_t subj, mach_port_name_t obj, - labelstr_t serv, labelstr_t perm) -{ - struct label subjl; - ipc_entry_t entry; - ipc_object_t objp; - kern_return_t kr; - struct label *objl; - - if (space == IS_NULL || space->is_task == NULL) - return KERN_INVALID_TASK; - - if (!MACH_PORT_VALID(obj)) - return KERN_INVALID_NAME; - - mac_init_task_label (&subjl); - int rc = mac_internalize_port_label (&subjl, subj); - if (rc) - { - mac_destroy_task_label (&subjl); - return KERN_INVALID_ARGUMENT; - } - - kr = ipc_right_lookup_write(space, obj, &entry); - if (kr != KERN_SUCCESS) - { - mac_destroy_task_label (&subjl); - return kr; - } - - 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, - labelstr_t serv, labelstr_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; - - objp = obji->ie_object; - subp = subi->ie_object; - is_write_unlock (space); - - 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/sedarwin7/src/darwin/xnu/osfmk/kern/task.h#3 (text+ko) ==== @@ -245,8 +245,8 @@ #define tasklabel_lock(task) io_lock((task)->label) #define tasklabel_unlock(task) io_unlock((task)->label) -#define tasklabel_lock2(a,b) /*io_lock2 ((a)->label, (b)->label)*/ -#define tasklabel_unlock2(a,b) /*io_unlock2 ((a)->label, (b)->label)*/ +extern void tasklabel_lock2(task_t a, task_t b); +extern void tasklabel_unlock2(task_t a, task_t b); #endif ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/mach/security.defs#2 (text+ko) ==== @@ -23,6 +23,12 @@ policies : labelstr_t; out label : labelstr_t); +/* + * Relabel a port. This does not alter the user label data in a label + * handle, but changes the label that is used for access control on the + * port itself. That label cannot be retrieved (with the current interfaces). + */ + routine mach_set_port_label(task : ipc_space_t; name : mach_port_name_t; label : labelstr_t);