X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/fe8ab488e9161c46dd9885d58fc52996dc0249ff..e8c3f78193f1895ea514044358b93b1add9322f3:/osfmk/ipc/ipc_entry.c

diff --git a/osfmk/ipc/ipc_entry.c b/osfmk/ipc/ipc_entry.c
index aabb15ada..facaf2af0 100644
--- a/osfmk/ipc/ipc_entry.c
+++ b/osfmk/ipc/ipc_entry.c
@@ -79,6 +79,7 @@
 #include <ipc/ipc_table.h>
 #include <ipc/ipc_port.h>
 #include <string.h>
+#include <sys/kdebug.h>
 
 /*
  *	Routine:	ipc_entry_lookup
@@ -103,8 +104,9 @@ ipc_entry_lookup(
 	if (index <  space->is_table_size) {
                 entry = &space->is_table[index];
 		if (IE_BITS_GEN(entry->ie_bits) != MACH_PORT_GEN(name) ||
-		    IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
+		    IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) {
 			entry = IE_NULL;		
+		}
 	}
 	else {
 		entry = IE_NULL;
@@ -189,10 +191,14 @@ ipc_entry_claim(
 	assert(table->ie_next < space->is_table_size);
 
 	/*
-	 *	Initialize the new entry.  We need only
-	 *	increment the generation number and clear ie_request.
+	 *	Initialize the new entry: increment gencount and reset
+	 *	rollover point if it rolled over, and clear ie_request.
 	 */
-	gen = IE_BITS_NEW_GEN(entry->ie_bits);
+	gen = ipc_entry_new_gen(entry->ie_bits);
+	if (__improbable(ipc_entry_gen_rolled(entry->ie_bits, gen))) {
+		ipc_entry_bits_t roll = ipc_space_get_rollpoint(space);
+		gen = ipc_entry_new_rollpoint(roll);
+	}
 	entry->ie_bits = gen;
 	entry->ie_request = IE_REQ_NONE;
 
@@ -302,6 +308,9 @@ ipc_entry_alloc_name(
 	mach_port_index_t index = MACH_PORT_INDEX(name);
 	mach_port_gen_t gen = MACH_PORT_GEN(name);
 
+	if (index > ipc_table_max_entries())
+		return KERN_NO_SPACE;
+
 	assert(MACH_PORT_VALID(name));
 
 
@@ -431,7 +440,7 @@ ipc_entry_dealloc(
 
 	if ((index < size) && (entry == &table[index])) {
 		assert(IE_BITS_GEN(entry->ie_bits) == MACH_PORT_GEN(name));
-		entry->ie_bits &= IE_BITS_GEN_MASK;
+		entry->ie_bits &= (IE_BITS_GEN_MASK | IE_BITS_ROLL_MASK);
 		entry->ie_next = table->ie_next;
 		table->ie_next = index;
 		space->is_table_free++;
@@ -481,6 +490,14 @@ ipc_entry_modified(
 		space->is_low_mod = index;
 	if (index > space->is_high_mod)
 		space->is_high_mod = index;
+
+	KERNEL_DEBUG_CONSTANT(
+		MACHDBG_CODE(DBG_MACH_IPC,MACH_IPC_PORT_ENTRY_MODIFY) | DBG_FUNC_NONE,
+		space->is_task ? task_pid(space->is_task) : 0,
+		name,
+		entry->ie_bits,
+		0,
+		0);
 }
 
 #define IPC_ENTRY_GROW_STATS 1
@@ -608,14 +625,7 @@ ipc_entry_grow_table(
 		return KERN_RESOURCE_SHORTAGE;
 	}
 
-	/* initialize new entries (free chain in backwards order) */
-	for (i = osize; i < size; i++) {
-		table[i].ie_object = IO_NULL;
-		table[i].ie_bits = IE_BITS_GEN_MASK;
-		table[i].ie_index = 0;
-		table[i].ie_next = i + 1;
-	}
-	table[size-1].ie_next = 0;
+	ipc_space_rand_freelist(space, table, osize, size);
 
 	/* clear out old entries in new table */
 	memset((void *)table, 0, osize * sizeof(*table));
@@ -749,3 +759,29 @@ ipc_entry_grow_table(
 
 	return KERN_SUCCESS;
 }
+
+
+/*
+ *	Routine:	ipc_entry_name_mask
+ *	Purpose:
+ *		Ensure a mach port name has the default ipc entry
+ *		generation bits set. This can be used to ensure that
+ *		a name passed in by user space matches names generated
+ *		by the kernel.
+ *	Conditions:
+ *		None.
+ *	Returns:
+ *		'name' input with default generation bits masked or added
+ *		as appropriate.
+ */
+mach_port_name_t
+ipc_entry_name_mask(mach_port_name_t name)
+{
+#ifndef NO_PORT_GEN
+	static mach_port_name_t null_name = MACH_PORT_MAKE(0, IE_BITS_GEN_MASK + IE_BITS_GEN_ONE);
+	return name | null_name;
+#else
+	static mach_port_name_t null_name = MACH_PORT_MAKE(0, ~(IE_BITS_GEN_MASK + IE_BITS_GEN_ONE));
+	return name & ~null_name;
+#endif
+}