From owner-trustedbsd-cvs@FreeBSD.ORG Tue Mar 7 16:47:10 2006 Return-Path: X-Original-To: trustedbsd-cvs@freebsd.org Delivered-To: trustedbsd-cvs@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 135F316A420 for ; Tue, 7 Mar 2006 16:47:10 +0000 (GMT) (envelope-from owner-perforce@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [209.31.154.42]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2516B43D46 for ; Tue, 7 Mar 2006 16:47:09 +0000 (GMT) (envelope-from owner-perforce@freebsd.org) Received: from mx2.freebsd.org (mx2.freebsd.org [216.136.204.119]) by cyrus.watson.org (Postfix) with ESMTP id ACE6446B16 for ; Tue, 7 Mar 2006 11:46:47 -0500 (EST) Received: from hub.freebsd.org (hub.freebsd.org [216.136.204.18]) by mx2.freebsd.org (Postfix) with ESMTP id 1ECD856861; Tue, 7 Mar 2006 16:47:08 +0000 (GMT) (envelope-from owner-perforce@freebsd.org) Received: by hub.freebsd.org (Postfix, from userid 32767) id 0F1DD16A423; Tue, 7 Mar 2006 16:47:08 +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 DDF5216A420 for ; Tue, 7 Mar 2006 16:47:07 +0000 (GMT) (envelope-from millert@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id A0D5143D46 for ; Tue, 7 Mar 2006 16:47:07 +0000 (GMT) (envelope-from millert@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id k27Gl7Hn009181 for ; Tue, 7 Mar 2006 16:47:07 GMT (envelope-from millert@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id k27Gl7Kp009054 for perforce@freebsd.org; Tue, 7 Mar 2006 16:47:07 GMT (envelope-from millert@freebsd.org) Date: Tue, 7 Mar 2006 16:47:07 GMT Message-Id: <200603071647.k27Gl7Kp009054@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to millert@freebsd.org using -f From: Todd Miller To: Perforce Change Reviews Cc: Subject: PERFORCE change 92921 for review X-BeenThere: trustedbsd-cvs@FreeBSD.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: TrustedBSD CVS and Perforce commit message list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Mar 2006 16:47:10 -0000 http://perforce.freebsd.org/chv.cgi?CH=92921 Change 92921 by millert@millert_ibook on 2006/03/07 16:46:29 Change how label handles are freed when their reference count reaches zero. We no longer free label handle storage when the ref count == 0. For kernel-allocated label handles, just deallocate the associated port. The actual label handle storage is deallocated by labelh_destroy() which is called by ipc_kobject_destroy() after all port references are gone. This fixes a race between a user program requesting (and accessing) the label of a labeled kernel object and the destruction of that object (task, port, etc). Affected files ... .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.c#8 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.h#9 edit .. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/ipc_kobject.c#4 edit Differences ... ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.c#8 (text+ko) ==== @@ -47,7 +47,7 @@ if (space == IS_NULL || space->is_task == NULL) return (KERN_INVALID_TASK); - /* XXX - perform entrypoint check here */ + /* XXX - perform entrypoint check here? */ /* * Note: the calling task will have a receive right for the port. @@ -75,7 +75,7 @@ lh->lh_port = port; lh->lh_label = *inl; lh->lh_type = LABELH_TYPE_USER; - lh->lh_references = 1; + lh->lh_references = 1; /* unused for LABELH_TYPE_USER */ /* Must call ipc_kobject_set() with port unlocked. */ ip_unlock(lh->lh_port); @@ -154,6 +154,11 @@ { ipc_labelh_t lh; + /* + * A label handle may only have a single reference. + * If there are no other references this is a no-op. + * Otherwise, make a copy we can write to and return it. + */ if (old->lh_references == 1) return (old); lh = labelh_duplicate(old); @@ -175,6 +180,9 @@ return (lh); } +/* + * Release a reference on an (unlocked) label handle. + */ void labelh_release(ipc_labelh_t lh) { @@ -183,10 +191,18 @@ lh_check_unlock(lh); } +/* + * Deallocate space associated with the label handle backed by the + * specified port. For kernel-allocated label handles the + * label handle reference count should be 0. For user-allocated + * handles the ref count is not used (it was initialized to 1). + */ void -lh_free(ipc_labelh_t lh) +labelh_destroy(ipc_port_t port) { - ipc_object_release(&lh->lh_port->ip_object); + ipc_labelh_t lh = (ipc_labelh_t) port->ip_kobject; + + ip_release(lh->lh_port); 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#9 (text+ko) ==== @@ -47,19 +47,19 @@ #define LABELH_TYPE_KERN 0 #define LABELH_TYPE_USER 1 +void labelh_destroy(ipc_port_t port); ipc_labelh_t labelh_duplicate(ipc_labelh_t old); ipc_labelh_t labelh_modify(ipc_labelh_t old); ipc_labelh_t labelh_new(void); kern_return_t labelh_new_user(ipc_space_t, struct label *, mach_port_name_t *); void labelh_release(ipc_labelh_t lh); ipc_labelh_t labelh_reference(ipc_labelh_t lh); -void lh_free(ipc_labelh_t lh); #define lh_reference(lh) ((lh)->lh_references++) -#define lh_release(lh) \ -MACRO_BEGIN \ - assert((lh)->lh_references > 0); \ - (lh)->lh_references--; \ +#define lh_release(lh) \ +MACRO_BEGIN \ + assert((lh)->lh_references > 0); \ + (lh)->lh_references--; \ MACRO_END extern zone_t ipc_labelh_zone; @@ -67,13 +67,21 @@ #define lh_lock io_lock #define lh_unlock io_unlock -#define lh_check_unlock(lh) \ -MACRO_BEGIN \ +/* + * Check the number of references the label handle a left. + * If there are 0 references and this is a kernel-allocated + * label handle, deallocate the associated port. The + * storage space for the label handle will be deallocated + * as part of the port destruction. User-allocated label + * handles are destroyed along with their ports. + */ +#define lh_check_unlock(lh) \ +MACRO_BEGIN \ _VOLATILE_ natural_t _refs = (lh)->lh_references; \ - \ - lh_unlock(lh); \ - if (_refs == 0) \ - lh_free(lh); \ + \ + lh_unlock(lh); \ + if (_refs == 0 && (lh)->lh_type == LABELH_TYPE_KERN) \ + ipc_port_dealloc_kernel((lh)->lh_port); \ MACRO_END #endif ==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/ipc_kobject.c#4 (text+ko) ==== @@ -514,7 +514,7 @@ break; case IKOT_LABELH: - labelh_release(port->ip_kobject); + labelh_destroy(port); break; default: