VYPR
Unrated severityNVD Advisory· Published Apr 13, 2011· Updated Apr 29, 2026

CVE-2011-0991

CVE-2011-0991

Description

Use-after-free vulnerability in Mono, when Moonlight 2.x before 2.4.1 or 3.x before 3.99.3 is used, allows remote attackers to cause a denial of service or possibly have unspecified other impact via vectors related to finalizing and then resurrecting a DynamicMethod instance.

Affected products

7
  • cpe:2.3:a:mono:mono:*:*:*:*:*:*:*:*
  • Novell/Moonlight6 versions
    cpe:2.3:a:novell:moonlight:2.0:*:*:*:*:*:*:*+ 5 more
    • cpe:2.3:a:novell:moonlight:2.0:*:*:*:*:*:*:*
    • cpe:2.3:a:novell:moonlight:2.3.0:*:*:*:*:*:*:*
    • cpe:2.3:a:novell:moonlight:2.31:*:*:*:*:*:*:*
    • cpe:2.3:a:novell:moonlight:2.4:*:*:*:*:*:*:*
    • cpe:2.3:a:novell:moonlight:3.0:*:*:*:*:*:*:*
    • cpe:2.3:a:novell:moonlight:3.99:*:*:*:*:*:*:*

Patches

3
3f8ee42b8c86

Don't use finalization to cleanup dynamic methods.

https://github.com/mono/monoRodrigo KumperaFeb 1, 2011via nvd-ref
4 files changed · +50 20
  • mcs/class/corlib/System.Reflection.Emit/DynamicMethod.cs+0 8 modified
    @@ -130,9 +130,6 @@ public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool
     		[MethodImplAttribute(MethodImplOptions.InternalCall)]
     		private extern void create_dynamic_method (DynamicMethod m);
     
    -		[MethodImplAttribute(MethodImplOptions.InternalCall)]
    -		private extern void destroy_dynamic_method (DynamicMethod m);
    -
     		private void CreateDynMethod () {
     			if (mhandle.Value == IntPtr.Zero) {
     				if (ilgen == null || (ILGenerator.Mono_GetCurrentOffset (ilgen) == 0))
    @@ -161,11 +158,6 @@ private void CreateDynMethod () {
     			}
     		}
     
    -		~DynamicMethod ()
    -		{
    -			destroy_dynamic_method (this);
    -		}
    -
     		[ComVisible (true)]
     		public Delegate CreateDelegate (Type delegateType)
     		{
    
  • mono/metadata/icall-def.h+0 1 modified
    @@ -513,7 +513,6 @@ ICALL(DERIVEDTYPE_1, "create_unmanaged_type", mono_reflection_create_unmanaged_t
     
     ICALL_TYPE(DYNM, "System.Reflection.Emit.DynamicMethod", DYNM_1)
     ICALL(DYNM_1, "create_dynamic_method", mono_reflection_create_dynamic_method)
    -ICALL(DYNM_2, "destroy_dynamic_method", mono_reflection_destroy_dynamic_method)
     
     ICALL_TYPE(ENUMB, "System.Reflection.Emit.EnumBuilder", ENUMB_1)
     ICALL(ENUMB_1, "setup_enum_type", ves_icall_EnumBuilder_setup_enum_type)
    
  • mono/metadata/object-internals.h+3 0 modified
    @@ -1448,6 +1448,9 @@ mono_string_to_utf8_checked (MonoString *s, MonoError *error) MONO_INTERNAL;
     gboolean
     mono_class_is_reflection_method_or_constructor (MonoClass *class) MONO_INTERNAL;
     
    +void
    +mono_reflection_shutdown (void) MONO_INTERNAL;
    +
     #endif /* __MONO_OBJECT_INTERNALS_H__ */
     
     
    
  • mono/metadata/reflection.c+47 11 modified
    @@ -11064,15 +11064,56 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
     	return result;
     }
     
    +typedef struct {
    +	MonoMethod *handle;
    +	MonoDomain *domain;
    +} DynamicMethodReleaseData;
    +	
    +static MonoReferenceQueue *dynamic_method_queue;
    +
    +void
    +mono_reflection_shutdown (void)
    +{
    +	MonoReferenceQueue *queue;
    +	mono_loader_lock ();
    +	queue = dynamic_method_queue;
    +	dynamic_method_queue = NULL;
    +	if (queue)
    +		mono_gc_reference_queue_free (queue);
    +	mono_loader_unlock ();
    +}
    +
    +static void
    +free_dynamic_method (void *dynamic_method)
    +{
    +	DynamicMethodReleaseData *data = dynamic_method;
    +
    +	mono_runtime_free_method (data->domain, data->handle);
    +	g_free (data);
    +}
    +
     void 
     mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
     {
    +	MonoReferenceQueue *queue;
    +	MonoMethod *handle;
    +	DynamicMethodReleaseData *release_data;
     	ReflectionMethodBuilder rmb;
     	MonoMethodSignature *sig;
     	MonoClass *klass;
     	GSList *l;
     	int i;
     
    +	if (mono_runtime_is_shutting_down ())
    +		mono_raise_exception (mono_get_exception_invalid_operation (""));
    +
    +	if (!(queue = dynamic_method_queue)) {
    +		mono_loader_lock ();
    +		if (!(queue = dynamic_method_queue))
    +			queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
    +		mono_loader_unlock ();
    +	}
    +
     	sig = dynamic_method_to_signature (mb);
     
     	reflection_methodbuilder_from_dynamic_method (&rmb, mb);
    @@ -11130,7 +11171,12 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
     
     	klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
     
    -	mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
    +	mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
    +	release_data = g_new (DynamicMethodReleaseData, 1);
    +	release_data->handle = handle;
    +	release_data->domain = mono_object_get_domain ((MonoObject*)mb);
    +	if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
    +		g_free (release_data);
     
     	/* Fix up refs entries pointing at us */
     	for (l = mb->referenced_by; l; l = l->next) {
    @@ -11156,16 +11202,6 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
     
     #endif /* DISABLE_REFLECTION_EMIT */
     
    -void
    -mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
    -{
    -	g_assert (mb);
    -
    -	if (mb->mhandle)
    -		mono_runtime_free_method (
    -			mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
    -}
    -
     /**
      * 
      * mono_reflection_is_valid_dynamic_token:
    
89d1455a80ef

Don't use finalization to cleanup dynamic methods.

https://github.com/mono/monoRodrigo KumperaFeb 1, 2011via nvd-ref
5 files changed · +53 20
  • mcs/class/corlib/System.Reflection.Emit/DynamicMethod.cs+0 8 modified
    @@ -127,9 +127,6 @@ public DynamicMethod (string name, Type returnType, Type[] parameterTypes, bool
     		[MethodImplAttribute(MethodImplOptions.InternalCall)]
     		private extern void create_dynamic_method (DynamicMethod m);
     
    -		[MethodImplAttribute(MethodImplOptions.InternalCall)]
    -		private extern void destroy_dynamic_method (DynamicMethod m);
    -
     		private void CreateDynMethod () {
     			if (mhandle.Value == IntPtr.Zero) {
     				if (ilgen == null || ilgen.ILOffset == 0)
    @@ -158,11 +155,6 @@ private void CreateDynMethod () {
     			}
     		}
     
    -		~DynamicMethod ()
    -		{
    -			destroy_dynamic_method (this);
    -		}
    -
     		[ComVisible (true)]
     		public Delegate CreateDelegate (Type delegateType)
     		{
    
  • mono/metadata/icall-def.h+0 1 modified
    @@ -524,7 +524,6 @@ ICALL(DERIVEDTYPE_1, "create_unmanaged_type", mono_reflection_create_unmanaged_t
     
     ICALL_TYPE(DYNM, "System.Reflection.Emit.DynamicMethod", DYNM_1)
     ICALL(DYNM_1, "create_dynamic_method", mono_reflection_create_dynamic_method)
    -ICALL(DYNM_2, "destroy_dynamic_method", mono_reflection_destroy_dynamic_method)
     
     ICALL_TYPE(ENUMB, "System.Reflection.Emit.EnumBuilder", ENUMB_1)
     ICALL(ENUMB_1, "setup_enum_type", ves_icall_EnumBuilder_setup_enum_type)
    
  • mono/metadata/object-internals.h+3 0 modified
    @@ -1539,6 +1539,9 @@ mono_object_new_pinned (MonoDomain *domain, MonoClass *klass) MONO_INTERNAL;
     void
     mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value) MONO_INTERNAL;
     
    +void
    +mono_reflection_shutdown (void) MONO_INTERNAL;
    +
     #endif /* __MONO_OBJECT_INTERNALS_H__ */
     
     
    
  • mono/metadata/reflection.c+47 11 modified
    @@ -11441,15 +11441,56 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
     	return result;
     }
     
    +typedef struct {
    +	MonoMethod *handle;
    +	MonoDomain *domain;
    +} DynamicMethodReleaseData;
    +	
    +static MonoReferenceQueue *dynamic_method_queue;
    +
    +void
    +mono_reflection_shutdown (void)
    +{
    +	MonoReferenceQueue *queue;
    +	mono_loader_lock ();
    +	queue = dynamic_method_queue;
    +	dynamic_method_queue = NULL;
    +	if (queue)
    +		mono_gc_reference_queue_free (queue);
    +	mono_loader_unlock ();
    +}
    +
    +static void
    +free_dynamic_method (void *dynamic_method)
    +{
    +	DynamicMethodReleaseData *data = dynamic_method;
    +
    +	mono_runtime_free_method (data->domain, data->handle);
    +	g_free (data);
    +}
    +
     void 
     mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
     {
    +	MonoReferenceQueue *queue;
    +	MonoMethod *handle;
    +	DynamicMethodReleaseData *release_data;
     	ReflectionMethodBuilder rmb;
     	MonoMethodSignature *sig;
     	MonoClass *klass;
     	GSList *l;
     	int i;
     
    +	if (mono_runtime_is_shutting_down ())
    +		mono_raise_exception (mono_get_exception_invalid_operation (""));
    +
    +	if (!(queue = dynamic_method_queue)) {
    +		mono_loader_lock ();
    +		if (!(queue = dynamic_method_queue))
    +			queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
    +		mono_loader_unlock ();
    +	}
    +
     	sig = dynamic_method_to_signature (mb);
     
     	reflection_methodbuilder_from_dynamic_method (&rmb, mb);
    @@ -11507,7 +11548,12 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
     
     	klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
     
    -	mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
    +	mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
    +	release_data = g_new (DynamicMethodReleaseData, 1);
    +	release_data->handle = handle;
    +	release_data->domain = mono_object_get_domain ((MonoObject*)mb);
    +	if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
    +		g_free (release_data);
     
     	/* Fix up refs entries pointing at us */
     	for (l = mb->referenced_by; l; l = l->next) {
    @@ -11533,16 +11579,6 @@ mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
     
     #endif /* DISABLE_REFLECTION_EMIT */
     
    -void
    -mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
    -{
    -	g_assert (mb);
    -
    -	if (mb->mhandle)
    -		mono_runtime_free_method (
    -			mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
    -}
    -
     /**
      * 
      * mono_reflection_is_valid_dynamic_token:
    
  • mono/metadata/runtime.c+3 0 modified
    @@ -39,5 +39,8 @@ void
     mono_runtime_shutdown (void)
     {
     	mono_domain_foreach (fire_process_exit_event, NULL);
    +
    +	/*From this point on, no more DM methods can be created. */
    +	mono_reflection_shutdown ();
     }
     
    
8eb1189099e0

Implement a reference queue API.

https://github.com/mono/monoRodrigo KumperaFeb 1, 2011via nvd-ref
2 files changed · +164 0
  • mono/metadata/gc.c+141 0 modified
    @@ -54,6 +54,7 @@ static gboolean finalizing_root_domain = FALSE;
     #define mono_finalizer_lock() EnterCriticalSection (&finalizer_mutex)
     #define mono_finalizer_unlock() LeaveCriticalSection (&finalizer_mutex)
     static CRITICAL_SECTION finalizer_mutex;
    +static CRITICAL_SECTION reference_queue_mutex;
     
     static GSList *domains_to_finalize= NULL;
     static MonoMList *threads_to_finalize = NULL;
    @@ -64,6 +65,7 @@ static void object_register_finalizer (MonoObject *obj, void (*callback)(void *,
     
     static void mono_gchandle_set_target (guint32 gchandle, MonoObject *obj);
     
    +static void reference_queue_proccess_all (void);
     #ifndef HAVE_NULL_GC
     static HANDLE pending_done_event;
     static HANDLE shutdown_event;
    @@ -1065,6 +1067,8 @@ finalizer_thread (gpointer unused)
     		mono_attach_maybe_start ();
     #endif
     
    +		reference_queue_proccess_all ();
    +
     		if (domains_to_finalize) {
     			mono_finalizer_lock ();
     			if (domains_to_finalize) {
    @@ -1083,6 +1087,7 @@ finalizer_thread (gpointer unused)
     		 */
     		mono_gc_invoke_finalizers ();
     
    +
     		SetEvent (pending_done_event);
     	}
     
    @@ -1097,6 +1102,7 @@ mono_gc_init (void)
     	InitializeCriticalSection (&allocator_section);
     
     	InitializeCriticalSection (&finalizer_mutex);
    +	InitializeCriticalSection (&reference_queue_mutex);
     
     	MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_NORMAL].entries);
     	MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_PINNED].entries);
    @@ -1174,6 +1180,7 @@ mono_gc_cleanup (void)
     	DeleteCriticalSection (&handle_section);
     	DeleteCriticalSection (&allocator_section);
     	DeleteCriticalSection (&finalizer_mutex);
    +	DeleteCriticalSection (&reference_queue_mutex);
     }
     
     #else
    @@ -1292,3 +1299,137 @@ mono_gc_alloc_mature (MonoVTable *vtable)
     	return mono_object_new_specific (vtable);
     }
     #endif
    +
    +
    +static MonoReferenceQueue *ref_queues;
    +
    +static void
    +ref_list_remove_element (RefQueueEntry **prev, RefQueueEntry *element)
    +{
    +	do {
    +		/* Guard if head is changed concurrently. */
    +		while (*prev != element)
    +			prev = &(*prev)->next;
    +	} while (prev && InterlockedCompareExchangePointer ((void*)prev, element->next, element) != element);
    +}
    +
    +static void
    +ref_list_push (RefQueueEntry **head, RefQueueEntry *value)
    +{
    +	RefQueueEntry *current;
    +	do {
    +		current = *head;
    +		value->next = current;
    +	} while (InterlockedCompareExchangePointer ((void*)head, value, current) != current);
    +}
    +
    +static void
    +reference_queue_proccess (MonoReferenceQueue *queue)
    +{
    +	RefQueueEntry **iter = &queue->queue;
    +	RefQueueEntry *entry;
    +	while ((entry = *iter)) {
    +		if (queue->should_be_deleted || !mono_gc_weak_link_get (&entry->dis_link)) {
    +			ref_list_remove_element (iter, entry);
    +			mono_gc_weak_link_remove (&entry->dis_link);
    +			queue->callback (entry->user_data);
    +			g_free (entry);
    +		} else {
    +			iter = &entry->next;
    +		}
    +	}
    +}
    +
    +static void
    +reference_queue_proccess_all (void)
    +{
    +	MonoReferenceQueue **iter;
    +	MonoReferenceQueue *queue = ref_queues;
    +	for (; queue; queue = queue->next)
    +		reference_queue_proccess (queue);
    +
    +restart:
    +	EnterCriticalSection (&reference_queue_mutex);
    +	for (iter = &ref_queues; *iter;) {
    +		queue = *iter;
    +		if (!queue->should_be_deleted) {
    +			iter = &queue->next;
    +			continue;
    +		}
    +		if (queue->queue) {
    +			LeaveCriticalSection (&reference_queue_mutex);
    +			reference_queue_proccess (queue);
    +			goto restart;
    +		}
    +		*iter = queue->next;
    +		g_free (queue);
    +	}
    +	LeaveCriticalSection (&reference_queue_mutex);
    +}
    +
    +/**
    + * mono_gc_reference_queue_new:
    + * @callback callback used when processing dead entries.
    + *
    + * Create a new reference queue used to process collected objects.
    + * A reference queue let you queue the pair (managed object, user data).
    + * Once the managed object is collected @callback will be called
    + * in the finalizer thread with 'user data' as argument.
    + *
    + * The callback is called without any locks held.
    + */
    +MonoReferenceQueue*
    +mono_gc_reference_queue_new (mono_reference_queue_callback callback)
    +{
    +	MonoReferenceQueue *res = g_new0 (MonoReferenceQueue, 1);
    +	res->callback = callback;
    +
    +	EnterCriticalSection (&reference_queue_mutex);
    +	res->next = ref_queues;
    +	ref_queues = res;
    +	LeaveCriticalSection (&reference_queue_mutex);
    +
    +	return res;
    +}
    +
    +/**
    + * mono_gc_reference_queue_add:
    + * @queue the queue to add the reference to.
    + * @obj the object to be watched for collection
    + * @user_data parameter to be passed to the queue callback
    + *
    + * Queue an object to be watched for collection.
    + *
    + * @returns false if the queue is scheduled to be freed.
    + */
    +gboolean
    +mono_gc_reference_queue_add (MonoReferenceQueue *queue, MonoObject *obj, void *user_data)
    +{
    +	RefQueueEntry *head;
    +	RefQueueEntry *entry;
    +	if (queue->should_be_deleted)
    +		return FALSE;
    +
    +	entry = g_new0 (RefQueueEntry, 1);
    +	entry->user_data = user_data;
    +	mono_gc_weak_link_add (&entry->dis_link, obj, TRUE);
    +	ref_list_push (&queue->queue, entry);
    +	return TRUE;
    +}
    +
    +/**
    + * mono_gc_reference_queue_free:
    + * @queue the queue that should be deleted.
    + *
    + * This operation signals that @queue should be deleted. This operation is deferred
    + * as it happens on the finalizer thread.
    + *
    + * After this call, no further objects can be queued. It's the responsibility of the
    + * caller to make sure that no further attempt to access queue will be made.
    + */
    +void
    +mono_gc_reference_queue_free (MonoReferenceQueue *queue)
    +{
    +	queue->should_be_deleted = TRUE;
    +}
    +
    
  • mono/metadata/gc-internal.h+23 0 modified
    @@ -335,5 +335,28 @@ gboolean mono_gc_precise_stack_mark_enabled (void) MONO_INTERNAL;
     
     FILE *mono_gc_get_logfile (void) MONO_INTERNAL;
     
    +typedef void (*mono_reference_queue_callback) (void *user_data);
    +
    +typedef struct _MonoReferenceQueue MonoReferenceQueue;
    +typedef struct _RefQueueEntry RefQueueEntry;
    +
    +struct _RefQueueEntry {
    +	void *dis_link;
    +	void *user_data;
    +	RefQueueEntry *next;
    +};
    +
    +struct _MonoReferenceQueue {
    +	RefQueueEntry *queue;
    +	mono_reference_queue_callback callback;
    +	MonoReferenceQueue *next;
    +	gboolean should_be_deleted;
    +};
    +
    +MonoReferenceQueue* mono_gc_reference_queue_new (mono_reference_queue_callback callback) MONO_INTERNAL;
    +void mono_gc_reference_queue_free (MonoReferenceQueue *queue) MONO_INTERNAL;
    +gboolean mono_gc_reference_queue_add (MonoReferenceQueue *queue, MonoObject *obj, void *user_data) MONO_INTERNAL;
    +
    +
     #endif /* __MONO_METADATA_GC_INTERNAL_H__ */
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

13

News mentions

0

No linked articles in our index yet.