+/* Routine io_registry_entry_get_property */
+kern_return_t is_io_registry_entry_get_property(
+ io_object_t registry_entry,
+ io_name_t property_name,
+ io_buf_ptr_t *properties,
+ mach_msg_type_number_t *propertiesCnt )
+{
+ kern_return_t err;
+ vm_size_t len;
+ OSObject * obj;
+
+ CHECK( IORegistryEntry, registry_entry, entry );
+
+#if CONFIG_MACF
+ if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name))
+ return kIOReturnNotPermitted;
+#endif
+
+ obj = entry->copyProperty(property_name);
+ if( !obj)
+ return( kIOReturnNotFound );
+
+ OSSerialize * s = OSSerialize::withCapacity(4096);
+ if( !s) {
+ obj->release();
+ return( kIOReturnNoMemory );
+ }
+
+ if( obj->serialize( s )) {
+ len = s->getLength();
+ *propertiesCnt = len;
+ err = copyoutkdata( s->text(), len, properties );
+
+ } else
+ err = kIOReturnUnsupported;
+
+ s->release();
+ obj->release();
+
+ return( err );
+}
+
+/* Routine io_registry_entry_get_property_recursively */
+kern_return_t is_io_registry_entry_get_property_recursively(
+ io_object_t registry_entry,
+ io_name_t plane,
+ io_name_t property_name,
+ uint32_t options,
+ io_buf_ptr_t *properties,
+ mach_msg_type_number_t *propertiesCnt )
+{
+ kern_return_t err;
+ vm_size_t len;
+ OSObject * obj;
+
+ CHECK( IORegistryEntry, registry_entry, entry );
+
+#if CONFIG_MACF
+ if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name))
+ return kIOReturnNotPermitted;
+#endif
+
+ obj = entry->copyProperty( property_name,
+ IORegistryEntry::getPlane( plane ), options );
+ if( !obj)
+ return( kIOReturnNotFound );
+
+ OSSerialize * s = OSSerialize::withCapacity(4096);
+ if( !s) {
+ obj->release();
+ return( kIOReturnNoMemory );
+ }
+
+ if( obj->serialize( s )) {
+ len = s->getLength();
+ *propertiesCnt = len;
+ err = copyoutkdata( s->text(), len, properties );
+
+ } else
+ err = kIOReturnUnsupported;
+
+ s->release();
+ obj->release();
+
+ return( err );
+}
+
+/* Routine io_registry_entry_get_properties */
+kern_return_t is_io_registry_entry_get_properties(
+ io_object_t registry_entry,
+ io_buf_ptr_t *properties,
+ mach_msg_type_number_t *propertiesCnt )
+{
+ return (kIOReturnUnsupported);
+}
+
+#if CONFIG_MACF
+
+struct GetPropertiesEditorRef
+{
+ kauth_cred_t cred;
+ IORegistryEntry * entry;
+ OSCollection * root;
+};
+
+static const OSMetaClassBase *
+GetPropertiesEditor(void * reference,
+ OSSerialize * s,
+ OSCollection * container,
+ const OSSymbol * name,
+ const OSMetaClassBase * value)
+{
+ GetPropertiesEditorRef * ref = (typeof(ref)) reference;
+
+ if (!ref->root) ref->root = container;
+ if (ref->root == container)
+ {
+ if (0 != mac_iokit_check_get_property(ref->cred, ref->entry, name->getCStringNoCopy()))
+ {
+ value = 0;
+ }
+ }
+ if (value) value->retain();
+ return (value);
+}
+
+#endif /* CONFIG_MACF */
+
+/* Routine io_registry_entry_get_properties */
+kern_return_t is_io_registry_entry_get_properties_bin(
+ io_object_t registry_entry,
+ io_buf_ptr_t *properties,
+ mach_msg_type_number_t *propertiesCnt)
+{
+ kern_return_t err = kIOReturnSuccess;
+ vm_size_t len;
+ OSSerialize * s;
+ OSSerialize::Editor editor = 0;
+ void * editRef = 0;
+
+ CHECK(IORegistryEntry, registry_entry, entry);
+
+#if CONFIG_MACF
+ GetPropertiesEditorRef ref;
+ if (mac_iokit_check_filter_properties(kauth_cred_get(), entry))
+ {
+ editor = &GetPropertiesEditor;
+ editRef = &ref;
+ ref.cred = kauth_cred_get();
+ ref.entry = entry;
+ ref.root = 0;
+ }
+#endif
+
+ s = OSSerialize::binaryWithCapacity(4096, editor, editRef);
+ if (!s) return (kIOReturnNoMemory);
+
+ if (!entry->serializeProperties(s)) err = kIOReturnUnsupported;
+
+ if (kIOReturnSuccess == err)
+ {
+ len = s->getLength();
+ *propertiesCnt = len;
+ err = copyoutkdata(s->text(), len, properties);
+ }
+ s->release();
+
+ return (err);
+}
+
+/* Routine io_registry_entry_get_property_bin */
+kern_return_t is_io_registry_entry_get_property_bin(
+ io_object_t registry_entry,
+ io_name_t plane,
+ io_name_t property_name,
+ uint32_t options,
+ io_buf_ptr_t *properties,
+ mach_msg_type_number_t *propertiesCnt )
+{
+ kern_return_t err;
+ vm_size_t len;
+ OSObject * obj;
+ const OSSymbol * sym;
+
+ CHECK( IORegistryEntry, registry_entry, entry );
+
+#if CONFIG_MACF
+ if (0 != mac_iokit_check_get_property(kauth_cred_get(), entry, property_name))
+ return kIOReturnNotPermitted;
+#endif
+
+ sym = OSSymbol::withCString(property_name);
+ if (!sym) return (kIOReturnNoMemory);
+
+ if (gIORegistryEntryPropertyKeysKey == sym)
+ {
+ obj = entry->copyPropertyKeys();
+ }
+ else
+ {
+ if ((kIORegistryIterateRecursively & options) && plane[0])
+ {
+ obj = entry->copyProperty(property_name,
+ IORegistryEntry::getPlane(plane), options );
+ }
+ else
+ {
+ obj = entry->copyProperty(property_name);
+ }
+ if (obj && gIORemoveOnReadProperties->containsObject(sym)) entry->removeProperty(sym);
+ }
+
+ sym->release();
+ if (!obj) return (kIOReturnNotFound);
+
+ OSSerialize * s = OSSerialize::binaryWithCapacity(4096);
+ if( !s) {
+ obj->release();
+ return( kIOReturnNoMemory );
+ }
+
+ if( obj->serialize( s )) {
+ len = s->getLength();
+ *propertiesCnt = len;
+ err = copyoutkdata( s->text(), len, properties );
+
+ } else err = kIOReturnUnsupported;
+
+ s->release();
+ obj->release();
+
+ return( err );
+}
+
+
+/* Routine io_registry_entry_set_properties */
+kern_return_t is_io_registry_entry_set_properties
+(
+ io_object_t registry_entry,
+ io_buf_ptr_t properties,
+ mach_msg_type_number_t propertiesCnt,
+ kern_return_t * result)
+{
+ OSObject * obj;
+ kern_return_t err;
+ IOReturn res;
+ vm_offset_t data;
+ vm_map_offset_t map_data;
+
+ CHECK( IORegistryEntry, registry_entry, entry );
+
+ if( propertiesCnt > sizeof(io_struct_inband_t) * 1024)
+ return( kIOReturnMessageTooLarge);
+
+ err = vm_map_copyout( kernel_map, &map_data, (vm_map_copy_t) properties );
+ data = CAST_DOWN(vm_offset_t, map_data);
+
+ if( KERN_SUCCESS == err) {
+
+ FAKE_STACK_FRAME(entry->getMetaClass());
+
+ // must return success after vm_map_copyout() succeeds
+ obj = OSUnserializeXML( (const char *) data, propertiesCnt );
+ vm_deallocate( kernel_map, data, propertiesCnt );
+
+ if (!obj)
+ res = kIOReturnBadArgument;
+#if CONFIG_MACF
+ else if (0 != mac_iokit_check_set_properties(kauth_cred_get(),
+ registry_entry, obj))
+ {
+ res = kIOReturnNotPermitted;
+ }
+#endif
+ else
+ {
+ res = entry->setProperties( obj );
+ }
+
+ if (obj)
+ obj->release();
+
+ FAKE_STACK_FRAME_END();
+
+ } else
+ res = err;
+
+ *result = res;
+ return( err );
+}
+