Loading...
libkern/c++/OSSerialize.cpp xnu-6153.41.3 xnu-8792.61.2
--- xnu/xnu-6153.41.3/libkern/c++/OSSerialize.cpp
+++ xnu/xnu-8792.61.2/libkern/c++/OSSerialize.cpp
@@ -27,15 +27,16 @@
  */
 /* OSSerialize.cpp created by rsulack on Wen 25-Nov-1998 */
 
+#define IOKIT_ENABLE_SHARED_PTR
+
 #include <sys/cdefs.h>
-
-__BEGIN_DECLS
 #include <vm/vm_kern.h>
-__END_DECLS
+#include <os/hash.h>
 
 #include <libkern/c++/OSContainers.h>
 #include <libkern/c++/OSLib.h>
 #include <libkern/c++/OSDictionary.h>
+#include <libkern/c++/OSSharedPtr.h>
 #include <libkern/OSSerializeBinary.h>
 #include <libkern/Block.h>
 #include <IOKit/IOLib.h>
@@ -52,6 +53,16 @@
 OSMetaClassDefineReservedUnused(OSSerialize, 6);
 OSMetaClassDefineReservedUnused(OSSerialize, 7);
 
+static inline kmem_guard_t
+OSSerialize_guard()
+{
+	kmem_guard_t guard = {
+		.kmg_tag     = IOMemoryTag(kernel_map),
+	};
+
+	return guard;
+}
+
 
 char *
 OSSerialize::text() const
@@ -189,6 +200,8 @@
 bool
 OSSerialize::initWithCapacity(unsigned int inCapacity)
 {
+	kmem_return_t kmr;
+
 	if (!super::init()) {
 		return false;
 	}
@@ -203,39 +216,37 @@
 	if (!inCapacity) {
 		inCapacity = 1;
 	}
-	if (round_page_overflow(inCapacity, &capacity)) {
-		tags->release();
-		tags = NULL;
-		return false;
-	}
-
-	capacityIncrement = capacity;
+	if (round_page_overflow(inCapacity, &inCapacity)) {
+		tags.reset();
+		return false;
+	}
+
+	capacityIncrement = inCapacity;
 
 	// allocate from the kernel map so that we can safely map this data
 	// into user space (the primary use of the OSSerialize object)
 
-	kern_return_t rc = kmem_alloc(kernel_map, (vm_offset_t *)&data, capacity, IOMemoryTag(kernel_map));
-	if (rc) {
-		tags->release();
-		tags = NULL;
-		return false;
-	}
-	bzero((void *)data, capacity);
-
-
-	OSCONTAINER_ACCUMSIZE(capacity);
-
-	return true;
-}
-
-OSSerialize *
+	kmr = kmem_alloc_guard(kernel_map, inCapacity, /* mask */ 0,
+	    (kma_flags_t)(KMA_ZERO | KMA_DATA), OSSerialize_guard());
+
+	if (kmr.kmr_return == KERN_SUCCESS) {
+		data = (char *)kmr.kmr_ptr;
+		capacity = inCapacity;
+		OSCONTAINER_ACCUMSIZE(capacity);
+		return true;
+	}
+
+	capacity = 0;
+	return false;
+}
+
+OSSharedPtr<OSSerialize>
 OSSerialize::withCapacity(unsigned int inCapacity)
 {
-	OSSerialize *me = new OSSerialize;
+	OSSharedPtr<OSSerialize> me = OSMakeShared<OSSerialize>();
 
 	if (me && !me->initWithCapacity(inCapacity)) {
-		me->release();
-		return NULL;
+		return nullptr;
 	}
 
 	return me;
@@ -266,7 +277,7 @@
 unsigned int
 OSSerialize::ensureCapacity(unsigned int newCapacity)
 {
-	char *newData;
+	kmem_return_t kmr;
 
 	if (newCapacity <= capacity) {
 		return capacity;
@@ -276,25 +287,18 @@
 		return capacity;
 	}
 
-	kern_return_t rc = kmem_realloc(kernel_map,
-	    (vm_offset_t)data,
-	    capacity,
-	    (vm_offset_t *)&newData,
-	    newCapacity,
-	    VM_KERN_MEMORY_IOKIT);
-	if (!rc) {
-		OSCONTAINER_ACCUMSIZE(newCapacity);
-
-		// kmem realloc does not free the old address range
-		kmem_free(kernel_map, (vm_offset_t)data, capacity);
-		OSCONTAINER_ACCUMSIZE(-((size_t)capacity));
-
-		// kmem realloc does not zero out the new memory
-		// and this could end up going to user land
-		bzero(&newData[capacity], newCapacity - capacity);
-
-		data = newData;
+	kmr = kmem_realloc_guard(kernel_map, (vm_offset_t)data, capacity,
+	    newCapacity, (kmr_flags_t)(KMR_ZERO | KMR_DATA | KMR_FREEOLD),
+	    OSSerialize_guard());
+
+	if (kmr.kmr_return == KERN_SUCCESS) {
+		size_t delta = 0;
+
+		data     = (char *)kmr.kmr_ptr;
+		delta   -= capacity;
 		capacity = newCapacity;
+		delta   += capacity;
+		OSCONTAINER_ACCUMSIZE(delta);
 	}
 
 	return capacity;
@@ -303,12 +307,12 @@
 void
 OSSerialize::free()
 {
-	OSSafeReleaseNULL(tags);
-	OSSafeReleaseNULL(indexData);
-
-	if (data) {
-		kmem_free(kernel_map, (vm_offset_t)data, capacity);
+	if (capacity) {
+		kmem_free_guard(kernel_map, (vm_offset_t)data, capacity,
+		    KMF_NONE, OSSerialize_guard());
 		OSCONTAINER_ACCUMSIZE( -((size_t)capacity));
+		data = nullptr;
+		capacity = 0;
 	}
 	super::free();
 }
@@ -316,15 +320,14 @@
 
 OSDefineMetaClassAndStructors(OSSerializer, OSObject)
 
-OSSerializer * OSSerializer::forTarget( void * target,
+OSSharedPtr<OSSerializer>
+OSSerializer::forTarget( void * target,
     OSSerializerCallback callback, void * ref )
 {
-	OSSerializer * thing;
-
-	thing = new OSSerializer;
+	OSSharedPtr<OSSerializer> thing = OSMakeShared<OSSerializer>();
+
 	if (thing && !thing->init()) {
-		thing->release();
-		thing = NULL;
+		thing.reset();
 	}
 
 	if (thing) {
@@ -342,11 +345,11 @@
 	return ((OSSerializerBlock)ref)(serializer);
 }
 
-OSSerializer *
+OSSharedPtr<OSSerializer>
 OSSerializer::withBlock(
 	OSSerializerBlock callback)
 {
-	OSSerializer * serializer;
+	OSSharedPtr<OSSerializer> serializer;
 	OSSerializerBlock block;
 
 	block = Block_copy(callback);