PERFORCE change 78531 for review

Andrew Reisse areisse at FreeBSD.org
Tue Jun 14 15:30:21 GMT 2005


http://perforce.freebsd.org/chv.cgi?CH=78531

Change 78531 by areisse at areisse_ibook on 2005/06/14 15:29:49

	Convert mach label handles to be real kernel ports, instead of just
	sharing the namespace. This will allow the interface to some of the
	security related calls to be simplified in the future, as well as
	removing the uglyness of IOT_LABELH from the system. Label handles
	should also be able to be passed among processes if desired.
	
	This submit doesn't change the policy-kernel interface, or the
	kernel-user interface.
	
	Some locking and memory issues remain (mostly because there were
	locking problems with label handles before).

Affected files ...

.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_init.c#2 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_kmsg.c#2 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_kmsg.h#2 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.c#2 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.h#2 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_object.c#2 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_object.h#2 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_right.c#3 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/mach_msg.c#4 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/mach_port.c#2 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/ipc_kobject.h#2 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/task.c#2 edit
.. //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/task.h#2 edit

Differences ...

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_init.c#2 (text+ko) ====

@@ -165,12 +165,6 @@
 	/* 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/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_kmsg.c#2 (text+ko) ====

@@ -239,15 +239,10 @@
 	mach_msg_size_t size = kmsg->ikm_size;
 	ipc_port_t port;
 
-	if (kmsg->ikm_sender != IO_NULL && io_otype (&kmsg->ikm_sender->lh_object) == 
-	    IOT_LABELH) {
-	  ipc_object_release (&kmsg->ikm_sender->lh_object);
-	  kmsg->ikm_sender = IO_NULL;
+	if (kmsg->ikm_sender != NULL) {
+	  labelh_release (kmsg->ikm_sender);
+	  kmsg->ikm_sender = NULL;
 	}
-	else if (kmsg->ikm_sender != IO_NULL && io_otype (&kmsg->ikm_sender->lh_object)
-		 != IOT_LABELH)
-	  printf ("strange otype in message label: %d\n", io_otype (&kmsg->ikm_sender->lh_object));
-
 
 	/*
 	 * Check to see if the message is bound to the port.  If so,
@@ -614,15 +609,10 @@
 		ipc_kmsg_clean_body(kmsg, body->msgh_descriptor_count);
 	}
 
-	if (kmsg->ikm_sender != IO_NULL && io_otype (&kmsg->ikm_sender->lh_object) == 
-	    IOT_LABELH) {
-	  ipc_object_release (&kmsg->ikm_sender->lh_object);
-	  kmsg->ikm_sender = IO_NULL;
+	if (kmsg->ikm_sender != NULL) {
+	  labelh_release (kmsg->ikm_sender);
+	  kmsg->ikm_sender = NULL;
 	}
-	else if (kmsg->ikm_sender != IO_NULL && io_otype (&kmsg->ikm_sender->lh_object)
-		 != IOT_LABELH)
-	  printf ("strange otype in message label: %d\n", io_otype (&kmsg->ikm_sender->lh_object));
-
 }
 
 /*
@@ -729,9 +719,7 @@
 	task_t cur = current_thread()->top_act->task;
 	if (cur)
 	  {
-	    ipc_object_reference (&cur->label->lh_object);
-	    /*trailer->msgh_labels.sender = (mach_port_name_t)cur->label;*/
-
+	    labelh_reference (cur->label);
 	    kmsg->ikm_sender = cur->label;
 	  }
 	else
@@ -823,7 +811,7 @@
 
 	trailer->msgh_labels.sender = 0;
 
-	kmsg->ikm_sender = (ipc_labelh_t)IO_NULL;
+	kmsg->ikm_sender = (ipc_labelh_t)NULL;
 
 	*kmsgp = kmsg;
 	return MACH_MSG_SUCCESS;

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_kmsg.h#2 (text+ko) ====

@@ -78,7 +78,6 @@
 #include <kern/macro_help.h>
 #include <kern/kalloc.h>
 #include <ipc/ipc_object.h>
-#include <ipc/ipc_labelh.h>
 
 /*
  *	This structure is only the header for a kmsg buffer;
@@ -92,13 +91,14 @@
  *	of the message.
  */
 
+struct ipc_labelh;
 
 typedef struct ipc_kmsg {
 	struct ipc_kmsg *ikm_next;
 	struct ipc_kmsg *ikm_prev;
 	ipc_port_t ikm_prealloc;	/* port we were preallocated from */
 	mach_msg_size_t ikm_size;
-        ipc_labelh_t ikm_sender;
+        struct ipc_labelh *ikm_sender;
 	mach_msg_header_t ikm_header;
 } *ipc_kmsg_t;
 

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.c#2 (text+ko) ====

@@ -1,13 +1,16 @@
 
 #include <ipc/ipc_space.h>
-#include <ipc/ipc_object.h>
+#include <ipc/ipc_port.h>
 #include <ipc/ipc_labelh.h>
+#include <kern/ipc_kobject.h>
 
 kern_return_t mac_label_new (ipc_space_t task, mach_port_name_t *name,
 			     vm_offset_t labelstr)
 {
   ipc_labelh_t lh;
   struct label inl;
+  ipc_port_t   port, sport;
+  kern_return_t kr;
 
   if (task == IS_NULL)
     return (KERN_INVALID_TASK);
@@ -16,35 +19,54 @@
   if (mac_internalize_port_label (&inl, labelstr))
     return KERN_INVALID_ARGUMENT;
 
-  int kr = ipc_object_alloc (task, IOT_LABELH, MACH_PORT_TYPE_LABELH, 1, name, &lh);
-  if (kr)
-    return kr;
+  port = ipc_port_alloc_kernel();
 
+  lh = kalloc(sizeof(struct ipc_labelh));
+  io_lock_init(lh);
+  lh->lh_port = port;
+  lh->lh_type = 0;
+  lh->lh_references = 1;
   lh->lh_label = inl;
-  io_unlock (&lh->lh_object);
+  ipc_kobject_set(port, (ipc_kobject_t)lh, IKOT_LABELH);
+
+  sport = ipc_port_make_send_locked(port);
+  ip_release(port);
+  ip_unlock(port);
+  *name = ipc_port_copyout_send (port,task);
   return 0;
 }
 
+/* This function should be used to allocate label handles
+   that are stored in other kernel objects, such as tasks.
+   They must be released along with that object.
+   The caller gets one reference, which can be applied to either the
+   port or the ipc_label_t structure itself.
+*/
 ipc_labelh_t labelh_new ()
 {
-  ipc_labelh_t lh = (ipc_labelh_t) io_alloc (IOT_LABELH);
-  io_lock_init (&(lh->lh_object));
-  lh->lh_object.io_references = 1;
-  lh->lh_object.io_bits = io_makebits (TRUE, IOT_LABELH, 0);
+  ipc_labelh_t lh = (ipc_labelh_t) kalloc(sizeof(struct ipc_labelh));
+  io_lock_init(lh);
+  lh->lh_port = ipc_port_alloc_kernel();
+  lh->lh_type = 0;
+  lh->lh_references = 1;
+  ipc_kobject_set(lh->lh_port, (ipc_kobject_t)lh, IKOT_LABELH);
+  ip_unlock(lh->lh_port);
   return lh;
 }
 
-/* call with old locked */
+/* call with old locked; returned object is unlocked */
 
 ipc_labelh_t labelh_duplicate (ipc_labelh_t old)
 {
-  ipc_labelh_t lh = (ipc_labelh_t) io_alloc (IOT_LABELH);
-  io_lock_init (&(lh->lh_object));
-  lh->lh_object.io_references = 1;
-  lh->lh_object.io_bits = io_makebits (TRUE, IOT_LABELH, 0);
-
+  ipc_labelh_t lh = (ipc_labelh_t) kalloc(sizeof(struct ipc_labelh));
+  io_lock_init(lh);
+  lh->lh_port = ipc_port_alloc_kernel();
+  lh->lh_type = 0;
+  lh->lh_references = 1;
+  ipc_kobject_set(lh->lh_port, (ipc_kobject_t)lh, IKOT_LABELH);
   mac_init_port_label (&lh->lh_label);
   mac_copy_port_label (&old->lh_label, &lh->lh_label);
+  ip_unlock(lh->lh_port);
   return lh;
 }
 
@@ -52,11 +74,34 @@
 
 ipc_labelh_t labelh_modify (ipc_labelh_t old)
 {
-  if (old->lh_object.io_references == 1)
+  if (old->lh_references == 1)
     return old;
   ipc_labelh_t lh = labelh_duplicate (old);
-  io_release (&old->lh_object);
-  io_unlock (&old->lh_object);
-  io_lock (&lh->lh_object);
+  lh_release(old);
+  lh_check_unlock (old);
+  lh_lock (lh);
+  return lh;
+}
+
+/* add or drop a reference on a label handle; not locked */
+
+ipc_labelh_t labelh_reference (ipc_labelh_t lh)
+{
+  lh_lock(lh);
+  lh_reference(lh);
+  lh_unlock(lh);
   return lh;
 }
+
+void labelh_release (ipc_labelh_t lh)
+{
+  lh_lock(lh);
+  lh_release(lh);
+  lh_check_unlock(lh);
+}
+
+void lh_free (ipc_labelh_t lh)
+{
+    ipc_object_release(lh->lh_port);
+    mac_destroy_port_label (&lh->lh_label);
+}

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_labelh.h#2 (text+ko) ====

@@ -3,17 +3,45 @@
 #define _IPC_LABELH_H_
 
 #include <kern/lock.h>
-#include <ipc/ipc_object.h>
+#include <ipc/ipc_port.h>
 #include <mach/_label.h>
 
 typedef struct ipc_labelh
 {
-  struct ipc_object lh_object;
-  struct label      lh_label;
+	int               lh_references;
+	int               lh_type;
+	struct label      lh_label;
+	ipc_port_t        lh_port;
+#if NCPUS == 1
+	usimple_lock_data_t	io_lock_data;
+#else
+	decl_mutex_data(,	io_lock_data)
+#endif
 } *ipc_labelh_t;
 
-
 ipc_labelh_t labelh_duplicate (ipc_labelh_t old);
 ipc_labelh_t labelh_modify (ipc_labelh_t old);
+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--;				\
+MACRO_END
+
+#define lh_lock io_lock
+#define lh_unlock io_unlock
+
+#define lh_check_unlock(lh) 		       			\
+MACRO_BEGIN				       			\
+	_VOLATILE_ natural_t _refs = (lh)->lh_references;	\
+					       			\
+	lh_unlock(lh);			       			\
+	if (_refs == 0)			       			\
+		lh_free(lh);		      			\
+MACRO_END
 
 #endif

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_object.c#2 (text+ko) ====

@@ -990,17 +990,23 @@
 	return kr;
 }
 
+/*
+ * Get a label out of a port, to be used by a kernel call
+ * 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.
+ */
+
 struct label *io_getlabel (ipc_object_t objp)
 {
-  switch (io_otype (objp))
-    {
-    case IOT_PORT:
-      return &((ipc_port_t) objp)->ip_label;
+	assert(io_otype(objp) == IOT_PORT);
+
+	ipc_port_t port = (ipc_port_t) objp;
 
-    case IOT_LABELH:
-      return &((ipc_labelh_t) objp)->lh_label;
-    }
-  return NULL;
+	if (ip_kotype(port) == IKOT_LABELH)
+		return &((ipc_labelh_t) port->ip_kobject)->lh_label;
+	else
+		return &port->ip_label;
 }
 
 /*
@@ -1025,10 +1031,6 @@
 		   and calling it now causes problems. */
 
 		mac_destroy_port_label (&port->ip_label);
-	}
-	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);
@@ -1080,6 +1082,7 @@
 	"(IOKIT_CONNECT)    ",
 	"(IOKIT_OBJECT)     ",	/* 30 */
 	"(UPL)              ",
+	"(LABELH)           ",
 						/* << new entries here	*/
 	"(UNKNOWN)          "	/* magic catchall	*/
 };

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_object.h#2 (text+ko) ====

@@ -142,8 +142,7 @@
  */
 #define	IOT_PORT		0
 #define IOT_PORT_SET		1
-#define IOT_LABELH              2 /* a label handle */
-#define IOT_NUMBER		3 /* number of types used */
+#define IOT_NUMBER		2 /* number of types used */
 
 extern zone_t ipc_object_zones[IOT_NUMBER];
 
@@ -152,7 +151,6 @@
 
 /*
  *	Call the routine for io_free so that checking can be performed.
- *      It is also responsible for freeing labels.
  */
 extern void	io_free(
 			unsigned int	otype,

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/ipc_right.c#3 (text+ko) ====

@@ -560,10 +560,6 @@
 		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:
@@ -678,14 +674,6 @@
 		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:
@@ -1020,21 +1008,6 @@
 		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/sedarwin7/src/darwin/xnu/osfmk/ipc/mach_msg.c#4 (text+ko) ====

@@ -276,7 +276,7 @@
 #if 1
 
 		if (option & MACH_RCV_TRAILER_ELEMENTS (MACH_RCV_TRAILER_AV)) {
-		  if (kmsg->ikm_sender != IO_NULL &&
+		  if (kmsg->ikm_sender != NULL &&
 		      IP_VALID(kmsg->ikm_header.msgh_remote_port)) {
 		    mac_check_ipc_methods
 		      (&kmsg->ikm_sender->lh_label,
@@ -288,24 +288,32 @@
 			  memset(trailer->msgh_av.av, 0, sizeof(msg_access_vector_t));
 		}
 
+		/*
+		 * The ipc_kmsg_t holds a reference to the label of a label
+		 * handle, not the port. We must get a reference to the port
+		 * and a send right to copyout to the receiver.
+		 */
 		if (option & MACH_RCV_TRAILER_ELEMENTS (MACH_RCV_TRAILER_LABELS)) {
-		  if (kmsg->ikm_sender != IO_NULL) {
-		    ipc_object_t  lh = &kmsg->ikm_sender->lh_object;
+
+		  if (kmsg->ikm_sender != NULL) {
+		    ipc_labelh_t  lh = kmsg->ikm_sender;
 		    ipc_entry_t   entry;
 		    kern_return_t kr;
 
-		    io_lock (lh);
-		    kr = ipc_entry_alloc (space, &trailer->msgh_labels.sender, &entry);
+		    ip_lock (lh->lh_port);
+		    lh->lh_port->ip_mscount++;
+		    lh->lh_port->ip_srights++;
+		    ip_reference (lh->lh_port);
+		    ip_unlock (lh->lh_port);
+
+		    kr = ipc_object_copyout (space, lh->lh_port, MACH_MSG_TYPE_PORT_SEND, 0,
+					     &trailer->msgh_labels.sender);
 		    if (kr != KERN_SUCCESS) {
+		      ip_lock (lh->lh_port);
+		      ip_release (lh->lh_port);
+		      ip_check_unlock (lh->lh_port);
+
 		      trailer->msgh_labels.sender = 0;
-		      /*ipc_object_release (lh);*/
-		    }
-		    else {
-		      entry->ie_bits |= (1 | MACH_PORT_TYPE_LABELH);
-		      entry->ie_object = lh;
-		      io_reference (lh);
-		      io_unlock (lh);
-		      is_write_unlock (space);
 		    }
 		  }
 		  else {

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/ipc/mach_port.c#2 (text+ko) ====

@@ -1774,6 +1774,7 @@
 {
 	ipc_entry_t entry;
 	kern_return_t kr;
+	struct label *l;
 
 	if (space == IS_NULL || space->is_task == NULL)
 		return KERN_INVALID_TASK;
@@ -1785,32 +1786,14 @@
 	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;
+	io_lock(entry->ie_object);
+	is_write_unlock (space);
+	l = io_getlabel(entry->ie_object);
 
-		ip_lock (port);
-		is_write_unlock (space);
-		mac_externalize_port_label (&port->ip_label, policies, outlabel, 512, 0);
+	mac_externalize_port_label (l, policies, outlabel, 512, 0);
 
-		ip_unlock (port);
-	}
+	io_unlock (entry->ie_object);
 	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, policies, outlabel, 512, 0);
-		io_unlock (&lh->lh_object);
-	}
-	return 0;
-	}
-
-	is_write_unlock (space);
-	return KERN_INVALID_ARGUMENT;
 }
 
 kern_return_t

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/ipc_kobject.h#2 (text+ko) ====

@@ -110,9 +110,10 @@
 #define IKOT_IOKIT_CONNECT		29
 #define IKOT_IOKIT_OBJECT		30
 #define IKOT_UPL				31
+#define IKOT_LABELH			32
 								/* << new entries here	*/
-#define	IKOT_UNKNOWN			32	/* magic catchall	*/
-#define	IKOT_MAX_TYPE			33	/* # of IKOT_ types	*/
+#define	IKOT_UNKNOWN			33	/* magic catchall	*/
+#define	IKOT_MAX_TYPE			34	/* # of IKOT_ types	*/
 
 /* Please keep ipc/ipc_object.c:ikot_print_array up to date	*/
 

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/task.c#2 (text+ko) ====

@@ -518,7 +518,7 @@
 	task_prof_deallocate(task);
 
 #ifdef MAC
-	ipc_object_release (&task->label->lh_object);
+	labelh_release(task->label);
 #endif
 
 	zfree(task_zone, (vm_offset_t) task);

==== //depot/projects/trustedbsd/sedarwin7/src/darwin/xnu/osfmk/kern/task.h#2 (text+ko) ====

@@ -242,11 +242,11 @@
 
 #define maclabel label->lh_label
 
-#define tasklabel_lock(task) io_lock(&(task)->label->lh_object)
-#define tasklabel_unlock(task) io_unlock(&(task)->label->lh_object)
+#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->lh_object, &(b)->label->lh_object)
-#define tasklabel_unlock2(a,b) io_unlock2 (&(a)->label->lh_object, &(b)->label->lh_object)
+#define tasklabel_lock2(a,b) /*io_lock2 ((a)->label, (b)->label)*/
+#define tasklabel_unlock2(a,b) /*io_unlock2 ((a)->label, (b)->label)*/
 
 #endif
 
To Unsubscribe: send mail to majordomo at trustedbsd.org
with "unsubscribe trustedbsd-cvs" in the body of the message



More information about the trustedbsd-cvs mailing list