* Sebastien Pouliot <sebastien@ximian.com>
*
* Copyright 2007-2010 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#include <mono/metadata/class-internals.h>
#include <mono/metadata/object.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/debug-helpers.h>
-#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-logger-internals.h>
#include "security-core-clr.h"
#ifndef DISABLE_SECURITY
+/* Class lazy loading functions */
+static GENERATE_GET_CLASS_WITH_CACHE (security_critical, System.Security, SecurityCriticalAttribute)
+static GENERATE_GET_CLASS_WITH_CACHE (security_safe_critical, System.Security, SecuritySafeCriticalAttribute)
+
static MonoClass*
security_critical_attribute (void)
{
- static MonoClass *class = NULL;
-
- if (!class) {
- class = mono_class_from_name (mono_defaults.corlib, "System.Security",
- "SecurityCriticalAttribute");
- }
- g_assert (class);
- return class;
+ return mono_class_get_security_critical_class ();
}
static MonoClass*
security_safe_critical_attribute (void)
{
- static MonoClass *class = NULL;
+ return mono_class_get_security_safe_critical_class ();
- if (!class) {
- class = mono_class_from_name (mono_defaults.corlib, "System.Security",
- "SecuritySafeCriticalAttribute");
- }
- g_assert (class);
- return class;
}
/* sometime we get a NULL (not found) caller (e.g. get_reflection_caller) */
* debugging purposes.
*/
static void
-set_type_load_exception_type (const char *format, MonoClass *class)
+set_type_load_exception_type (const char *format, MonoClass *klass)
{
- char *type_name = mono_type_get_full_name (class);
- char *parent_name = mono_type_get_full_name (class->parent);
+ char *type_name = mono_type_get_full_name (klass);
+ char *parent_name = mono_type_get_full_name (klass->parent);
char *message = g_strdup_printf (format, type_name, parent_name);
g_free (parent_name);
g_free (type_name);
mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_SECURITY, message);
- mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, message);
+ mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, message);
// note: do not free string given to mono_class_set_failure
}
* Reference: fxcop CA2132 rule
*/
void
-mono_security_core_clr_check_inheritance (MonoClass *class)
+mono_security_core_clr_check_inheritance (MonoClass *klass)
{
MonoSecurityCoreCLRLevel class_level, parent_level;
- MonoClass *parent = class->parent;
+ MonoClass *parent = klass->parent;
if (!parent)
return;
- class_level = mono_security_core_clr_class_level (class);
+ class_level = mono_security_core_clr_class_level (klass);
parent_level = mono_security_core_clr_class_level (parent);
if (class_level < parent_level) {
set_type_load_exception_type (
"Inheritance failure for type %s. Parent class %s is more restricted.",
- class);
+ klass);
} else {
MonoMethod *parent_ctor = get_default_ctor (parent);
if (parent_ctor && ((parent_ctor->flags & METHOD_ATTRIBUTE_PUBLIC) != 0)) {
- class_level = mono_security_core_clr_method_level (get_default_ctor (class), FALSE);
+ class_level = mono_security_core_clr_method_level (get_default_ctor (klass), FALSE);
parent_level = mono_security_core_clr_method_level (parent_ctor, FALSE);
if (class_level < parent_level) {
set_type_load_exception_type (
"Inheritance failure for type %s. Default constructor security mismatch with %s.",
- class);
+ klass);
}
}
}
* Reference: http://msdn.microsoft.com/en-us/magazine/cc765416.aspx#id0190030
*/
void
-mono_security_core_clr_check_override (MonoClass *class, MonoMethod *override, MonoMethod *base)
+mono_security_core_clr_check_override (MonoClass *klass, MonoMethod *override, MonoMethod *base)
{
MonoSecurityCoreCLRLevel base_level = mono_security_core_clr_method_level (base, FALSE);
MonoSecurityCoreCLRLevel override_level = mono_security_core_clr_method_level (override, FALSE);
static gboolean
get_caller_no_reflection_related (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
{
- MonoMethod **dest = data;
+ MonoMethod **dest = (MonoMethod **)data;
const char *ns;
/* skip unmanaged frames */
static gboolean
get_caller_of_elevated_trust_code (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
{
- ElevatedTrustCookie *cookie = data;
+ ElevatedTrustCookie *cookie = (ElevatedTrustCookie *)data;
/* skip unmanaged frames and wrappers */
if (!managed || (m->wrapper_type != MONO_WRAPPER_NONE))
* Transparent code cannot access to Critical fields and can only use
* them if they are visible from it's point of view.
*
- * A FieldAccessException is thrown if the field is cannot be accessed.
+ * Returns TRUE if acess is allowed. Otherwise returns FALSE and sets @error to a FieldAccessException if the field is cannot be accessed.
*/
-void
-mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field)
+gboolean
+mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field, MonoError *error)
{
+ mono_error_init (error);
MonoMethod *caller = get_reflection_caller ();
/* CoreCLR restrictions applies to Transparent code/caller */
if (mono_security_core_clr_method_level (caller, TRUE) != MONO_SECURITY_CORE_CLR_TRANSPARENT)
- return;
+ return TRUE;
if (mono_security_core_clr_get_options () & MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_REFLECTION) {
if (!mono_security_core_clr_is_platform_image (mono_field_get_parent(field)->image))
- return;
+ return TRUE;
}
/* Transparent code cannot [get|set]value on Critical fields */
if (mono_security_core_clr_class_level (mono_field_get_parent (field)) == MONO_SECURITY_CORE_CLR_CRITICAL) {
- mono_raise_exception (get_field_access_exception (
+ mono_error_set_exception_instance (error, get_field_access_exception (
"Transparent method %s cannot get or set Critical field %s.",
caller, field));
+ return FALSE;
}
/* also it cannot access a fields that is not visible from it's (caller) point of view */
if (!check_field_access (caller, field)) {
- mono_raise_exception (get_field_access_exception (
+ mono_error_set_exception_instance (error, get_field_access_exception (
"Transparent method %s cannot get or set private/internal field %s.",
caller, field));
+ return FALSE;
}
+ return TRUE;
}
/*
* Transparent code cannot call Critical methods and can only call them
* if they are visible from it's point of view.
*
- * A MethodAccessException is thrown if the field is cannot be accessed.
+ * If access is allowed returns TRUE. Returns FALSE and sets @error to a MethodAccessException if the field is cannot be accessed.
*/
-void
-mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method)
+gboolean
+mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method, MonoError *error)
{
+ mono_error_init (error);
MonoMethod *caller = get_reflection_caller ();
/* CoreCLR restrictions applies to Transparent code/caller */
if (mono_security_core_clr_method_level (caller, TRUE) != MONO_SECURITY_CORE_CLR_TRANSPARENT)
- return;
+ return TRUE;
if (mono_security_core_clr_get_options () & MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_REFLECTION) {
if (!mono_security_core_clr_is_platform_image (method->klass->image))
- return;
+ return TRUE;
}
/* Transparent code cannot invoke, even using reflection, Critical code */
if (mono_security_core_clr_method_level (method, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL) {
- mono_raise_exception (get_method_access_exception (
+ mono_error_set_exception_instance (error, get_method_access_exception (
"Transparent method %s cannot invoke Critical method %s.",
caller, method));
+ return FALSE;
}
/* also it cannot invoke a method that is not visible from it's (caller) point of view */
if (!check_method_access (caller, method)) {
- mono_raise_exception (get_method_access_exception (
+ mono_error_set_exception_instance (error, get_method_access_exception (
"Transparent method %s cannot invoke private/internal method %s.",
caller, method));
+ return FALSE;
}
+ return TRUE;
}
/*
/*
* mono_security_core_clr_ensure_delegate_creation:
*
- * Return TRUE if a delegate can be created on the specified method.
- * CoreCLR also affect the binding, so throwOnBindFailure must be
- * FALSE to let this function return (FALSE) normally, otherwise (if
- * throwOnBindFailure is TRUE) it will throw an ArgumentException.
+ * Return TRUE if a delegate can be created on the specified
+ * method. CoreCLR can also affect the binding, this function may
+ * return (FALSE) and set @error to an ArgumentException.
*
- * A MethodAccessException is thrown if the specified method is not
+ * @error is set to a MethodAccessException if the specified method is not
* visible from the caller point of view.
*/
gboolean
-mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, gboolean throwOnBindFailure)
+mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, MonoError *error)
{
MonoMethod *caller;
+ mono_error_init (error);
+
/* note: mscorlib creates delegates to avoid reflection (optimization), we ignore those cases */
if (can_avoid_corlib_reflection_delegate_optimization (method))
return TRUE;
/* otherwise it (as a Transparent caller) cannot create a delegate on a Critical method... */
if (mono_security_core_clr_method_level (method, TRUE) == MONO_SECURITY_CORE_CLR_CRITICAL) {
- /* but this throws only if 'throwOnBindFailure' is TRUE */
- if (!throwOnBindFailure)
- return FALSE;
-
- mono_raise_exception (get_argument_exception (
+ mono_error_set_exception_instance (error, get_argument_exception (
"Transparent method %s cannot create a delegate on Critical method %s.",
caller, method));
+ return FALSE;
}
if (mono_security_core_clr_get_options () & MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_DELEGATE) {
/* also it cannot create the delegate on a method that is not visible from it's (caller) point of view */
if (!check_method_access (caller, method)) {
- mono_raise_exception (get_method_access_exception (
+ mono_error_set_exception_instance (error, get_method_access_exception (
"Transparent method %s cannot create a delegate on private/internal method %s.",
caller, method));
+ return FALSE;
}
return TRUE;
if (cinfo && mono_custom_attrs_has_attr (cinfo, security_critical_attribute ()))
level = MONO_SECURITY_CORE_CLR_CRITICAL;
- return level;
+ return (MonoSecurityCoreCLRLevel)level;
}
/*
* - a check for the class and outer class(es) ...
*/
static MonoSecurityCoreCLRLevel
-mono_security_core_clr_class_level_no_platform_check (MonoClass *class)
+mono_security_core_clr_class_level_no_platform_check (MonoClass *klass)
{
MonoSecurityCoreCLRLevel level = MONO_SECURITY_CORE_CLR_TRANSPARENT;
- MonoCustomAttrInfo *cinfo = mono_custom_attrs_from_class (class);
+ MonoCustomAttrInfo *cinfo = mono_custom_attrs_from_class (klass);
if (cinfo) {
- level = mono_security_core_clr_level_from_cinfo (cinfo, class->image);
+ level = mono_security_core_clr_level_from_cinfo (cinfo, klass->image);
mono_custom_attrs_free (cinfo);
}
- if (level == MONO_SECURITY_CORE_CLR_TRANSPARENT && class->nested_in)
- level = mono_security_core_clr_class_level_no_platform_check (class->nested_in);
+ if (level == MONO_SECURITY_CORE_CLR_TRANSPARENT && klass->nested_in)
+ level = mono_security_core_clr_class_level_no_platform_check (klass->nested_in);
return level;
}
* Return the MonoSecurityCoreCLRLevel for the specified class.
*/
MonoSecurityCoreCLRLevel
-mono_security_core_clr_class_level (MonoClass *class)
+mono_security_core_clr_class_level (MonoClass *klass)
{
/* non-platform code is always Transparent - whatever the attributes says */
- if (!mono_security_core_clr_test && !mono_security_core_clr_is_platform_image (class->image))
+ if (!mono_security_core_clr_test && !mono_security_core_clr_is_platform_image (klass->image))
return MONO_SECURITY_CORE_CLR_TRANSPARENT;
- return mono_security_core_clr_class_level_no_platform_check (class);
+ return mono_security_core_clr_class_level_no_platform_check (klass);
}
/*
#else
void
-mono_security_core_clr_check_inheritance (MonoClass *class)
+mono_security_core_clr_check_inheritance (MonoClass *klass)
{
}
void
-mono_security_core_clr_check_override (MonoClass *class, MonoMethod *override, MonoMethod *base)
+mono_security_core_clr_check_override (MonoClass *klass, MonoMethod *override, MonoMethod *base)
{
}
return FALSE;
}
-void
-mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field)
+gboolean
+mono_security_core_clr_ensure_reflection_access_field (MonoClassField *field, MonoError *error)
{
+ mono_error_init (error);
+ return TRUE;
}
void
-mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method)
+mono_security_core_clr_ensure_reflection_access_method (MonoMethod *method, MonoError *error)
{
+ mono_error_init (error);
+ return TRUE;
}
gboolean
-mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, gboolean throwOnBindFailure)
+mono_security_core_clr_ensure_delegate_creation (MonoMethod *method, MonoError *error)
{
+ mono_error_init (error);
return TRUE;
}
}
MonoSecurityCoreCLRLevel
-mono_security_core_clr_class_level (MonoClass *class)
+mono_security_core_clr_class_level (MonoClass *klass)
{
return MONO_SECURITY_CORE_CLR_TRANSPARENT;
}