"cas" parameter.
.PP
The following modes are supported:
-.TP
-.I cas
-This allows mono to support declarative security attributes,
-e.g. execution of Code Access Security (CAS) or non-CAS demands.
.TP
.I core-clr
Enables the core-clr security system, typically used for
int thunks_size;
} MonoThunkJitInfo;
-typedef struct {
- gboolean cas_inited:1;
- gboolean cas_class_assert:1;
- gboolean cas_class_deny:1;
- gboolean cas_class_permitonly:1;
- gboolean cas_method_assert:1;
- gboolean cas_method_deny:1;
- gboolean cas_method_permitonly:1;
-} MonoMethodCasInfo;
-
typedef enum {
JIT_INFO_NONE = 0,
- JIT_INFO_HAS_CAS_INFO = (1 << 0),
- JIT_INFO_HAS_GENERIC_JIT_INFO = (1 << 1),
- JIT_INFO_HAS_TRY_BLOCK_HOLES = (1 << 2),
- JIT_INFO_HAS_ARCH_EH_INFO = (1 << 3),
- JIT_INFO_HAS_THUNK_INFO = (1 << 4)
+ JIT_INFO_HAS_GENERIC_JIT_INFO = (1 << 0),
+ JIT_INFO_HAS_TRY_BLOCK_HOLES = (1 << 1),
+ JIT_INFO_HAS_ARCH_EH_INFO = (1 << 2),
+ JIT_INFO_HAS_THUNK_INFO = (1 << 3)
} MonoJitInfoFlags;
struct _MonoJitInfo {
guint32 num_clauses:15;
/* Whenever the code is domain neutral or 'shared' */
gboolean domain_neutral:1;
- gboolean has_cas_info:1;
gboolean has_generic_jit_info:1;
gboolean has_try_block_holes:1;
gboolean has_arch_eh_info:1;
MonoThunkJitInfo*
mono_jit_info_get_thunk_info (MonoJitInfo *ji);
-MonoMethodCasInfo*
-mono_jit_info_get_cas_info (MonoJitInfo *ji);
-
/*
* Installs a new function which is used to return a MonoJitInfo for a method inside
* an AOT module.
int size = MONO_SIZEOF_JIT_INFO;
size += num_clauses * sizeof (MonoJitExceptionInfo);
- if (flags & JIT_INFO_HAS_CAS_INFO)
- size += sizeof (MonoMethodCasInfo);
if (flags & JIT_INFO_HAS_GENERIC_JIT_INFO)
size += sizeof (MonoGenericJitInfo);
if (flags & JIT_INFO_HAS_TRY_BLOCK_HOLES)
ji->code_start = code;
ji->code_size = code_size;
ji->num_clauses = num_clauses;
- if (flags & JIT_INFO_HAS_CAS_INFO)
- ji->has_cas_info = 1;
if (flags & JIT_INFO_HAS_GENERIC_JIT_INFO)
ji->has_generic_jit_info = 1;
if (flags & JIT_INFO_HAS_TRY_BLOCK_HOLES)
return NULL;
}
}
-
-MonoMethodCasInfo*
-mono_jit_info_get_cas_info (MonoJitInfo *ji)
-{
- if (ji->has_cas_info) {
- char *ptr = (char*)&ji->clauses [ji->num_clauses];
- if (ji->has_generic_jit_info)
- ptr += sizeof (MonoGenericJitInfo);
- if (ji->has_try_block_holes)
- ptr += try_block_hole_table_size (ji);
- if (ji->has_arch_eh_info)
- ptr += sizeof (MonoArchEHJitInfo);
- return (MonoMethodCasInfo*)ptr;
- } else {
- return NULL;
- }
-}
typedef enum {
MONO_SECURITY_MODE_NONE,
MONO_SECURITY_MODE_CORE_CLR,
- MONO_SECURITY_MODE_CAS,
- MONO_SECURITY_MODE_SMCS_HACK
} MonoSecurityMode;
/* Structures */
#ifndef DISABLE_SECURITY
#define mono_security_enabled() (mono_is_security_manager_active ())
-#define mono_security_cas_enabled() (mono_security_get_mode () == MONO_SECURITY_MODE_CAS)
#define mono_security_core_clr_enabled() (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
-#define mono_security_smcs_hack_enabled() (mono_security_get_mode () == MONO_SECURITY_MODE_SMCS_HACK)
#else
#define mono_security_enabled() (FALSE)
-#define mono_security_cas_enabled() (FALSE)
#define mono_security_core_clr_enabled() (FALSE)
-#define mono_security_smcs_hack_enabled() (FALSE)
#endif
#endif /* _MONO_METADATA_SECURITY_MANAGER_H_ */
mini-codegen.c \
mini-exceptions.c \
mini-trampolines.c \
- declsec.c \
- declsec.h \
branch-opts.c \
mini-generic-sharing.c \
regalloc2.c \
if (image_is_dynamic (assembly->image) || assembly->ref_only)
return;
- if (mono_security_cas_enabled ())
- return;
-
mono_aot_lock ();
if (static_aot_modules)
info = g_hash_table_lookup (static_aot_modules, assembly->aname.name);
+++ /dev/null
-/*
- * declsec.c: Declarative Security support
- *
- * Author:
- * Sebastien Pouliot <sebastien@ximian.com>
- *
- * Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
- */
-#include <config.h>
-
-#include "declsec.h"
-#include "mini.h"
-
-#ifndef DISABLE_SECURITY
-
-/*
- * Does the methods (or it's class) as any declarative security attribute ?
- * Is so are they applicable ? (e.g. static class constructor)
- */
-MonoBoolean
-mono_method_has_declsec (MonoMethod *method)
-{
- InterlockedIncrement (&mono_jit_stats.cas_declsec_check);
-
- if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
- method = mono_marshal_method_from_wrapper (method);
- if (!method)
- return FALSE;
- } else if (method->wrapper_type != MONO_WRAPPER_NONE)
- return FALSE;
-
- if ((method->klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) || (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
- /* ignore static constructors */
- if (strcmp (method->name, ".cctor"))
- return TRUE;
- }
- return FALSE;
-}
-
-
-/*
- * Fill actions for the specific index (which may either be an encoded class token or
- * an encoded method token) from the metadata image.
- * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
- */
-void
-mono_declsec_cache_stack_modifiers (MonoJitInfo *jinfo)
-{
- MonoMethodCasInfo *info = mono_jit_info_get_cas_info (jinfo);
- MonoMethod *method;
- guint32 flags;
-
- if (!info)
- return;
-
- method = jinfo_get_method (jinfo);
- /* first find the stack modifiers applied to the method */
- flags = mono_declsec_flags_from_method (method);
- info->cas_method_assert = (flags & MONO_DECLSEC_FLAG_ASSERT) != 0;
- info->cas_method_deny = (flags & MONO_DECLSEC_FLAG_DENY) != 0;
- info->cas_method_permitonly = (flags & MONO_DECLSEC_FLAG_PERMITONLY) != 0;
-
- /* then find the stack modifiers applied to the class */
- flags = mono_declsec_flags_from_class (method->klass);
- info->cas_class_assert = (flags & MONO_DECLSEC_FLAG_ASSERT) != 0;
- info->cas_class_deny = (flags & MONO_DECLSEC_FLAG_DENY) != 0;
- info->cas_class_permitonly = (flags & MONO_DECLSEC_FLAG_PERMITONLY) != 0;
-}
-
-
-MonoSecurityFrame*
-mono_declsec_create_frame (MonoDomain *domain, MonoJitInfo *jinfo)
-{
- MonoSecurityFrame *frame = (MonoSecurityFrame*) mono_object_new (domain, mono_defaults.runtimesecurityframe_class);
- MonoMethodCasInfo *info;
- MonoMethod *method;
-
- method = jinfo_get_method (jinfo);
- info = mono_jit_info_get_cas_info (jinfo);
- if (info && !info->cas_inited) {
- if (mono_method_has_declsec (method)) {
- /* Cache the stack modifiers into the MonoJitInfo structure to speed up future stack walks */
- mono_declsec_cache_stack_modifiers (jinfo);
- }
- info->cas_inited = TRUE;
- }
-
- MONO_OBJECT_SETREF (frame, method, mono_method_get_object (domain, method, NULL));
- MONO_OBJECT_SETREF (frame, domain, domain->domain);
-
- /* stack modifiers on methods have priority on (i.e. replaces) modifiers on class */
-
- if (info && info->cas_method_assert) {
- mono_declsec_get_method_action (method, SECURITY_ACTION_ASSERT, &frame->assert);
- } else if (info && info->cas_class_assert) {
- mono_declsec_get_class_action (method->klass, SECURITY_ACTION_ASSERT, &frame->assert);
- }
-
- if (info && info->cas_method_deny) {
- mono_declsec_get_method_action (method, SECURITY_ACTION_DENY, &frame->deny);
- } else if (info && info->cas_class_deny) {
- mono_declsec_get_class_action (method->klass, SECURITY_ACTION_DENY, &frame->deny);
- }
-
- if (info && info->cas_method_permitonly) {
- mono_declsec_get_method_action (method, SECURITY_ACTION_PERMITONLY, &frame->permitonly);
- } else if (info && info->cas_class_permitonly) {
- mono_declsec_get_class_action (method->klass, SECURITY_ACTION_PERMITONLY, &frame->permitonly);
- }
-
- /* g_warning ("FRAME %s A(%p,%d) D(%p,%d) PO(%p,%d)",
- method->name, frame->assert.blob, frame->assert.size, frame->deny.blob, frame->deny.size, frame->permitonly.blob,frame->permitonly.size); */
-
- return frame;
-}
-
-
-/*
- * Execute any LinkDemand, NonCasLinkDemand, LinkDemandChoice declarative
- * security attribute present on the called method or it's class.
- *
- * @domain The current application domain
- * @caller The method calling
- * @callee The called method.
- * return value: TRUE if a security violation is detection, FALSE otherwise.
- *
- * Note: The execution is done in managed code in SecurityManager.LinkDemand
- */
-static gboolean
-mono_declsec_linkdemand_standard (MonoDomain *domain, MonoMethod *caller, MonoMethod *callee)
-{
- MonoDeclSecurityActions linkclass, linkmethod;
-
- InterlockedIncrement (&mono_jit_stats.cas_linkdemand);
-
- if (mono_declsec_get_linkdemands (callee, &linkclass, &linkmethod)) {
- MonoAssembly *assembly = mono_image_get_assembly (caller->klass->image);
- MonoReflectionAssembly *refass = (MonoReflectionAssembly*) mono_assembly_get_object (domain, assembly);
- MonoSecurityManager *secman = mono_security_manager_get_methods ();
- MonoObject *res;
- gpointer args [3];
-
- args [0] = refass;
- args [1] = &linkclass;
- args [2] = &linkmethod;
-
- res = mono_runtime_invoke (secman->linkdemand, NULL, args, NULL);
- return !(*(MonoBoolean *) mono_object_unbox(res));
- }
- return FALSE;
-}
-
-/*
- * Ensure that the restrictions for partially trusted code are satisfied.
- *
- * @domain The current application domain
- * @assembly The assembly to query
- * return value: TRUE if the assembly is runnning at FullTrust, FALSE otherwise.
- */
-static gboolean
-mono_declsec_is_assembly_fulltrust (MonoDomain *domain, MonoAssembly *assembly)
-{
- if (!MONO_SECMAN_FLAG_INIT (assembly->fulltrust)) {
- MonoReflectionAssembly *refass = (MonoReflectionAssembly*) mono_assembly_get_object (domain, assembly);
- MonoSecurityManager *secman = mono_security_manager_get_methods ();
-
- if (secman && refass) {
- MonoObject *res;
- gpointer args [1];
- args [0] = refass;
-
- res = mono_runtime_invoke (secman->linkdemandfulltrust, NULL, args, NULL);
- if (*(MonoBoolean *) mono_object_unbox(res)) {
- /* keep this value cached as it will be used very often */
- MONO_SECMAN_FLAG_SET_VALUE (assembly->fulltrust, TRUE);
- return TRUE;
- }
- }
-
- MONO_SECMAN_FLAG_SET_VALUE (assembly->fulltrust, FALSE);
- return FALSE;
- }
-
- return MONO_SECMAN_FLAG_GET_VALUE (assembly->fulltrust);
-}
-
-/*
- * Ensure that the restrictions for partially trusted code are satisfied.
- *
- * @domain The current application domain
- * @caller The method calling
- * @callee The called method
- * return value: TRUE if a security violation is detected, FALSE otherwise.
- *
- * If callee's assembly is strongnamed and doesn't have an
- * [AllowPartiallyTrustedCallers] attribute then we must enforce a LinkDemand
- * for FullTrust on all public/protected methods on public class.
- *
- * Note: APTC is only effective on stongnamed assemblies.
- */
-static gboolean
-mono_declsec_linkdemand_aptc (MonoDomain *domain, MonoMethod *caller, MonoMethod *callee)
-{
- MonoSecurityManager* secman = NULL;
- MonoAssembly *assembly;
- guint32 size = 0;
-
- InterlockedIncrement (&mono_jit_stats.cas_linkdemand_aptc);
-
- /* A - Applicable only if we're calling into *another* assembly */
- if (caller->klass->image == callee->klass->image)
- return FALSE;
-
- /* B - Applicable if we're calling a public/protected method from a public class */
- if (!(callee->klass->flags & TYPE_ATTRIBUTE_PUBLIC) || !(callee->flags & FIELD_ATTRIBUTE_PUBLIC))
- return FALSE;
-
- /* C - Applicable if the callee's assembly is strongnamed */
- if ((mono_image_get_public_key (callee->klass->image, &size) == NULL) || (size < MONO_ECMA_KEY_LENGTH))
- return FALSE;
-
- /* D - the callee's assembly must have [AllowPartiallyTrustedCallers] */
- assembly = mono_image_get_assembly (callee->klass->image);
- if (!MONO_SECMAN_FLAG_INIT (assembly->aptc)) {
- MonoCustomAttrInfo* cinfo = mono_custom_attrs_from_assembly (assembly);
- gboolean result = FALSE;
- secman = mono_security_manager_get_methods ();
- if (secman && cinfo) {
- /* look for AllowPartiallyTrustedCallersAttribute */
- result = mono_custom_attrs_has_attr (cinfo, secman->allowpartiallytrustedcallers);
- }
- if (cinfo)
- mono_custom_attrs_free (cinfo);
- MONO_SECMAN_FLAG_SET_VALUE (assembly->aptc, result);
- }
-
- if (MONO_SECMAN_FLAG_GET_VALUE (assembly->aptc))
- return FALSE;
-
- /* E - the caller's assembly must have full trust permissions */
- assembly = mono_image_get_assembly (caller->klass->image);
- if (mono_declsec_is_assembly_fulltrust (domain, assembly))
- return FALSE;
-
- /* g_warning ("FAILURE *** JIT LinkDemand APTC check *** %s.%s calls into %s.%s",
- caller->klass->name, caller->name, callee->klass->name, callee->name); */
-
- return TRUE; /* i.e. throw new SecurityException(); */
-}
-
-/*
- * Ensure that the restrictions for calling native code are satisfied.
- *
- * @domain The current application domain
- * @caller The method calling
- * @native The native method called
- * return value: TRUE if a security violation is detected, FALSE otherwise.
- *
- * Executing Platform Invokes (P/Invoke) is a is a restricted operation.
- * The security policy must allow (SecurityPermissionFlag.UnmanagedCode)
- * an assembly to do this.
- *
- * This LinkDemand case is special because it only needs to call managed
- * code once per assembly. Further calls on this assembly will use a cached
- * flag for better performance. This is not done before the first call (e.g.
- * when loading the assembly) because that would break the lazy policy
- * evaluation that Mono use (another time saving optimization).
- *
- * Note: P/Invoke checks are ALWAYS (1) done at JIT time (as a LinkDemand).
- * They are also checked at runtime, using a Demand (stack walk), unless the
- * method or it's class has a [SuppressUnmanagedCodeSecurity] attribute.
- *
- * (1) well as long as the security manager is active (i.e. --security)
- */
-static gboolean
-mono_declsec_linkdemand_pinvoke (MonoDomain *domain, MonoMethod *caller, MonoMethod *native)
-{
- MonoAssembly *assembly = mono_image_get_assembly (caller->klass->image);
-
- InterlockedIncrement (&mono_jit_stats.cas_linkdemand_pinvoke);
-
- /* Check for P/Invoke flag for the assembly */
- if (!MONO_SECMAN_FLAG_INIT (assembly->unmanaged)) {
- /* Check if we know (and have) or FullTrust status */
- if (MONO_SECMAN_FLAG_INIT (assembly->fulltrust) && MONO_SECMAN_FLAG_GET_VALUE (assembly->fulltrust)) {
- /* FullTrust includes UnmanagedCode permission */
- MONO_SECMAN_FLAG_SET_VALUE (assembly->unmanaged, TRUE);
- return FALSE;
- } else {
- MonoReflectionAssembly *refass = (MonoReflectionAssembly*) mono_assembly_get_object (domain, assembly);
- MonoSecurityManager* secman = mono_security_manager_get_methods ();
- if (secman && refass) {
- MonoObject *res;
- gpointer args [1];
- args [0] = refass;
-
- res = mono_runtime_invoke (secman->linkdemandunmanaged, NULL, args, NULL);
- if (*(MonoBoolean *) mono_object_unbox(res)) {
- MONO_SECMAN_FLAG_SET_VALUE (assembly->unmanaged, TRUE);
- return FALSE;
- }
- }
- }
-
- MONO_SECMAN_FLAG_SET_VALUE (assembly->unmanaged, FALSE);
- }
-
- if (MONO_SECMAN_FLAG_GET_VALUE (assembly->unmanaged))
- return FALSE;
-
- /* g_warning ("FAILURE *** JIT LinkDemand P/Invoke check *** %s.%s calls into %s.%s",
- caller->klass->name, caller->name, native->klass->name, native->name); */
-
- return TRUE; /* i.e. throw new SecurityException(); */
-}
-
-/*
- * Ensure that the restrictions for calling internal calls are satisfied.
- *
- * @domain The current application domain
- * @caller The method calling
- * @icall The internal call method
- * return value: TRUE if a security violation is detected, FALSE otherwise.
- *
- * We can't trust the icall flags/iflags as it comes from the assembly
- * that we may want to restrict and we do not have the public/restricted
- * information about icalls in the runtime. Actually it is not so bad
- * as the CLR 2.0 doesn't enforce that restriction anymore.
- *
- * So we'll limit the icalls to originate from ECMA signed assemblies
- * (as this is required for partial trust scenarios) - or - assemblies that
- * have FullTrust.
- */
-static gboolean
-mono_declsec_linkdemand_icall (MonoDomain *domain, MonoMethod *caller, MonoMethod *icall)
-{
- MonoAssembly *assembly;
-
- InterlockedIncrement (&mono_jit_stats.cas_linkdemand_icall);
-
- /* check if the _icall_ is defined inside an ECMA signed assembly */
- assembly = mono_image_get_assembly (icall->klass->image);
- if (!MONO_SECMAN_FLAG_INIT (assembly->ecma)) {
- guint32 size = 0;
- const char *pk = mono_image_get_public_key (icall->klass->image, &size);
- MONO_SECMAN_FLAG_SET_VALUE (assembly->ecma, mono_is_ecma_key (pk, size));
- }
-
- if (MONO_SECMAN_FLAG_GET_VALUE (assembly->ecma))
- return FALSE;
-
- /* else check if the _calling_ assembly is running at FullTrust */
- assembly = mono_image_get_assembly (caller->klass->image);
- return !mono_declsec_is_assembly_fulltrust (domain, assembly);
-}
-
-
-/*
- * Before the JIT can link (call) into a method the following security checks
- * must be done:
- *
- * We check that the code has the permission to link when:
- * 1. the code try to call an internal call;
- * 2. the code try to p/invoke to unmanaged code;
- * 3. the code try to call trusted code without being trusted itself -
- * or without the trusted code permission (APTC);
- * 4. the code try to call managed code protected by a LinkDemand security
- * attribute
- *
- * Failures result in a SecurityException being thrown (later in mini code).
- *
- * Note: Some checks are duplicated in managed code to deal when reflection is
- * used to call the methods.
- */
-guint32
-mono_declsec_linkdemand (MonoDomain *domain, MonoMethod *caller, MonoMethod *callee)
-{
- guint32 violation = MONO_JIT_SECURITY_OK;
-
- /* short-circuit corlib as it is fully trusted (within itself)
- * and because this cause major recursion headaches */
- if ((caller->klass->image == mono_defaults.corlib) && (callee->klass->image == mono_defaults.corlib))
- return violation;
-
- /* next, the special (implied) linkdemand */
-
- if (callee->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
- /* restrict internal calls into the runtime */
- if (mono_declsec_linkdemand_icall (domain, caller, callee))
- violation = MONO_JIT_LINKDEMAND_ECMA;
- } else if (callee->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
- /* CAS can restrict p/invoke calls with the assembly granted permissions */
- if (mono_declsec_linkdemand_pinvoke (domain, caller, callee))
- violation = MONO_JIT_LINKDEMAND_PINVOKE;
- }
-
- if (!violation) {
- /* check if we allow partially trusted callers in trusted (signed) assemblies */
- if (mono_declsec_linkdemand_aptc (domain, caller, callee))
- violation = MONO_JIT_LINKDEMAND_APTC;
- }
-
- /* then the "normal" LinkDemand (only when called method has declarative security) */
- if (!violation && mono_method_has_declsec (callee)) {
- /* LinkDemand are ignored for static constructors (ensured by calling mono_method_has_declsec) */
- if (mono_declsec_linkdemand_standard (domain, caller, callee))
- violation = MONO_JIT_LINKDEMAND_PERMISSION;
- }
-
- /* if (violation) g_warning ("mono_declsec_linkdemand violation reported %d", violation); */
- return violation;
-}
-
-#else /* DISABLE_SECURITY */
-
-void
-mono_declsec_cache_stack_modifiers (MonoJitInfo *jinfo)
-{
-}
-
-MonoSecurityFrame*
-mono_declsec_create_frame (MonoDomain *domain, MonoJitInfo *jinfo)
-{
- return NULL;
-}
-
-guint32
-mono_declsec_linkdemand (MonoDomain *domain, MonoMethod *caller, MonoMethod *callee)
-{
- return MONO_JIT_SECURITY_OK;
-}
-
-MonoBoolean
-mono_method_has_declsec (MonoMethod *method)
-{
- return FALSE;
-}
-
-#endif
+++ /dev/null
-/*
- * declsec.h: Declarative Security support
- *
- * Author:
- * Sebastien Pouliot <sebastien@ximian.com>
- *
- * (C) 2004-2005 Novell (http://www.novell.com)
- */
-
-#ifndef _MONO_MINI_DECLSEC_H_
-#define _MONO_MINI_DECLSEC_H_
-
-#include <string.h>
-
-#include "mono/metadata/class-internals.h"
-#include "mono/metadata/domain-internals.h"
-#include "mono/metadata/object.h"
-#include "mono/metadata/tabledefs.h"
-#include "mono/metadata/marshal.h"
-#include "mono/metadata/security-manager.h"
-#include "mono/metadata/exception.h"
-#include "mono/utils/mono-compiler.h"
-
-
-/* Definitions */
-
-#define MONO_CAS_INITIAL_STACK_SIZE 6
-
-
-/* keep in synch with RuntimeSecurityFrame in /mcs/class/corlib/System.Security/SecurityFrame.cs */
-typedef struct {
- MonoObject obj;
- MonoAppDomain *domain;
- MonoReflectionMethod *method;
- MonoDeclSecurityEntry assert;
- MonoDeclSecurityEntry deny;
- MonoDeclSecurityEntry permitonly;
-} MonoSecurityFrame;
-
-
-/* limited flags used in MonoJitInfo for stack modifiers */
-enum {
- MONO_JITINFO_STACKMOD_ASSERT = 0x01,
- MONO_JITINFO_STACKMOD_DENY = 0x02,
- MONO_JITINFO_STACKMOD_PERMITONLY = 0x04
-};
-
-enum {
- MONO_JIT_SECURITY_OK = 0x00,
- MONO_JIT_LINKDEMAND_PERMISSION = 0x01,
- MONO_JIT_LINKDEMAND_APTC = 0x02,
- MONO_JIT_LINKDEMAND_ECMA = 0x04,
- MONO_JIT_LINKDEMAND_PINVOKE = 0x08
-};
-
-/* Prototypes */
-MonoBoolean mono_method_has_declsec (MonoMethod *method);
-void mono_declsec_cache_stack_modifiers (MonoJitInfo *jinfo);
-MonoSecurityFrame* mono_declsec_create_frame (MonoDomain *domain, MonoJitInfo *jinfo);
-
-guint32 mono_declsec_linkdemand (MonoDomain *domain, MonoMethod *caller, MonoMethod *callee);
-
-#ifndef DISABLE_SECURITY
-#define mono_security_method_has_declsec(method) (mono_method_has_declsec(method))
-#else
-#define mono_security_method_has_declsec(method) (FALSE)
-#endif
-
-#endif /* _MONO_MINI_DECLSEC_H_ */
} else if (strcmp (argv [i], "--security") == 0) {
#ifndef DISABLE_SECURITY
mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE);
- mono_security_set_mode (MONO_SECURITY_MODE_CAS);
- mono_activate_security_manager ();
#else
fprintf (stderr, "error: --security: not compiled with security manager support");
return 1;
#endif
} else if (strncmp (argv [i], "--security=", 11) == 0) {
- /* Note: temporary-smcs-hack, validil, and verifiable need to be
+ /* Note: validil, and verifiable need to be
accepted even if DISABLE_SECURITY is defined. */
- if (strcmp (argv [i] + 11, "temporary-smcs-hack") == 0) {
- mono_security_set_mode (MONO_SECURITY_MODE_SMCS_HACK);
- } else if (strcmp (argv [i] + 11, "core-clr") == 0) {
+ if (strcmp (argv [i] + 11, "core-clr") == 0) {
#ifndef DISABLE_SECURITY
mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE);
mono_security_set_mode (MONO_SECURITY_MODE_CORE_CLR);
#endif
} else if (strcmp (argv [i] + 11, "cas") == 0) {
#ifndef DISABLE_SECURITY
- mono_verifier_set_mode (MONO_VERIFIER_MODE_VERIFIABLE);
- mono_security_set_mode (MONO_SECURITY_MODE_CAS);
- mono_activate_security_manager ();
+ fprintf (stderr, "warning: --security=cas not supported.");
#else
fprintf (stderr, "error: --security: not compiled with CAS support");
return 1;
return FALSE;
}
- /*
- * CAS - do not inline methods with declarative security
- * Note: this has to be before any possible return TRUE;
- */
- if (mono_security_method_has_declsec (method))
- return FALSE;
-
#ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
if (mono_arch_is_soft_float ()) {
/* FIXME: */
return fsig;
}
-/*
- * Returns TRUE if the JIT should abort inlining because "callee"
- * is influenced by security attributes.
- */
-static
-gboolean check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *callee)
-{
- guint32 result;
-
- if ((cfg->method != caller) && mono_security_method_has_declsec (callee)) {
- return TRUE;
- }
-
- result = mono_declsec_linkdemand (cfg->domain, caller, callee);
- if (result == MONO_JIT_SECURITY_OK)
- return FALSE;
-
- if (result == MONO_JIT_LINKDEMAND_ECMA) {
- /* Generate code to throw a SecurityException before the actual call/link */
- MonoSecurityManager *secman = mono_security_manager_get_methods ();
- MonoInst *args [2];
-
- NEW_ICONST (cfg, args [0], 4);
- NEW_METHODCONST (cfg, args [1], caller);
- mono_emit_method_call (cfg, secman->linkdemandsecurityexception, args, NULL);
- } else if (cfg->exception_type == MONO_EXCEPTION_NONE) {
- /* don't hide previous results */
- mono_cfg_set_exception (cfg, MONO_EXCEPTION_SECURITY_LINKDEMAND);
- cfg->exception_data = result;
- return TRUE;
- }
-
- return FALSE;
-}
-
static MonoMethod*
throw_exception (void)
{
int num_calls = 0, inline_costs = 0;
int breakpoint_id = 0;
guint num_args;
- MonoBoolean security, pinvoke;
- MonoSecurityManager* secman = NULL;
- MonoDeclSecurityActions actions;
GSList *class_inits = NULL;
gboolean dont_verify, dont_verify_stloc, readonly = FALSE;
int context_used;
dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP;
dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP_INVOKE;
- dont_verify |= mono_security_smcs_hack_enabled ();
-
/* still some type unsafety issues in marshal wrappers... (unknown is PtrToStructure) */
dont_verify_stloc = method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE;
dont_verify_stloc |= method->wrapper_type == MONO_WRAPPER_UNKNOWN;
}
}
- if (mono_security_cas_enabled ())
- secman = mono_security_manager_get_methods ();
-
- security = (secman && mono_security_method_has_declsec (method));
- /* at this point having security doesn't mean we have any code to generate */
- if (security && (cfg->method == method)) {
- /* Only Demand, NonCasDemand and DemandChoice requires code generation.
- * And we do not want to enter the next section (with allocation) if we
- * have nothing to generate */
- security = mono_declsec_get_demands (method, &actions);
- }
-
- /* we must Demand SecurityPermission.Unmanaged before P/Invoking */
- pinvoke = (secman && (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE));
- if (pinvoke) {
- MonoMethod *wrapped = mono_marshal_method_from_wrapper (method);
- if (wrapped && (wrapped->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
- MonoCustomAttrInfo* custom = mono_custom_attrs_from_method (wrapped);
-
- /* unless the method or it's class has the [SuppressUnmanagedCodeSecurity] attribute */
- if (custom && mono_custom_attrs_has_attr (custom, secman->suppressunmanagedcodesecurity)) {
- pinvoke = FALSE;
- }
- if (custom)
- mono_custom_attrs_free (custom);
-
- if (pinvoke) {
- custom = mono_custom_attrs_from_class (wrapped->klass);
- if (custom && mono_custom_attrs_has_attr (custom, secman->suppressunmanagedcodesecurity)) {
- pinvoke = FALSE;
- }
- if (custom)
- mono_custom_attrs_free (custom);
- }
- } else {
- /* not a P/Invoke after all */
- pinvoke = FALSE;
- }
- }
-
/* we use a separate basic block for the initialization code */
NEW_BBLOCK (cfg, init_localsbb);
cfg->bb_init = init_localsbb;
*/
}
- /* at this point we know, if security is TRUE, that some code needs to be generated */
- if (security && (cfg->method == method)) {
- MonoInst *args [2];
-
- cfg->stat_cas_demand_generation++;
-
- if (actions.demand.blob) {
- /* Add code for SecurityAction.Demand */
- EMIT_NEW_DECLSECCONST (cfg, args[0], image, actions.demand);
- EMIT_NEW_ICONST (cfg, args [1], actions.demand.size);
- /* Calls static void SecurityManager.InternalDemand (byte* permissions, int size); */
- mono_emit_method_call (cfg, secman->demand, args, NULL);
- }
- if (actions.noncasdemand.blob) {
- /* CLR 1.x uses a .noncasdemand (but 2.x doesn't) */
- /* For Mono we re-route non-CAS Demand to Demand (as the managed code must deal with it anyway) */
- EMIT_NEW_DECLSECCONST (cfg, args[0], image, actions.noncasdemand);
- EMIT_NEW_ICONST (cfg, args [1], actions.noncasdemand.size);
- /* Calls static void SecurityManager.InternalDemand (byte* permissions, int size); */
- mono_emit_method_call (cfg, secman->demand, args, NULL);
- }
- if (actions.demandchoice.blob) {
- /* New in 2.0, Demand must succeed for one of the permissions (i.e. not all) */
- EMIT_NEW_DECLSECCONST (cfg, args[0], image, actions.demandchoice);
- EMIT_NEW_ICONST (cfg, args [1], actions.demandchoice.size);
- /* Calls static void SecurityManager.InternalDemandChoice (byte* permissions, int size); */
- mono_emit_method_call (cfg, secman->demandchoice, args, NULL);
- }
- }
-
- /* we must Demand SecurityPermission.Unmanaged before p/invoking */
- if (pinvoke) {
- mono_emit_method_call (cfg, secman->demandunmanaged, NULL, NULL);
- }
-
if (mono_security_core_clr_enabled ()) {
/* check if this is native code, e.g. an icall or a p/invoke */
if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod))
GENERIC_SHARING_FAILURE (CEE_JMP);
- if (mono_security_cas_enabled ())
- CHECK_CFG_EXCEPTION;
-
emit_instrumentation_call (cfg, mono_profiler_method_leave);
if (ARCH_HAVE_OP_TAIL_CALL) {
}
*/
- if (mono_security_cas_enabled ()) {
- if (check_linkdemand (cfg, method, cmethod))
- INLINE_FAILURE ("linkdemand");
- CHECK_CFG_EXCEPTION;
- }
-
if (cmethod->string_ctor && method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE)
g_assert_not_reached ();
context_used = mini_method_check_context_used (cfg, cmethod);
- if (mono_security_cas_enabled ()) {
- if (check_linkdemand (cfg, method, cmethod))
- INLINE_FAILURE ("linkdemand");
- CHECK_CFG_EXCEPTION;
- } else if (mono_security_core_clr_enabled ()) {
+ if (mono_security_core_clr_enabled ())
ensure_method_is_allowed_to_call_method (cfg, method, cmethod, bblock, ip);
- }
if (cfg->generic_sharing_context && cmethod && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
emit_generic_class_init (cfg, cmethod->klass);
if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod))
METHOD_ACCESS_FAILURE (method, cil_method);
- if (mono_security_cas_enabled ()) {
- if (check_linkdemand (cfg, method, cmethod))
- INLINE_FAILURE ("linkdemand");
- CHECK_CFG_EXCEPTION;
- } else if (mono_security_core_clr_enabled ()) {
+ if (mono_security_core_clr_enabled ())
ensure_method_is_allowed_to_call_method (cfg, method, cmethod, bblock, ip);
- }
/*
* Optimize the common case of ldftn+delegate creation
context_used = mini_method_check_context_used (cfg, cmethod);
- if (mono_security_cas_enabled ()) {
- if (check_linkdemand (cfg, method, cmethod))
- INLINE_FAILURE ("linkdemand");
- CHECK_CFG_EXCEPTION;
- } else if (mono_security_core_clr_enabled ()) {
+ if (mono_security_core_clr_enabled ())
ensure_method_is_allowed_to_call_method (cfg, method, cmethod, bblock, ip);
- }
/*
* Optimize the common case of ldvirtftn+delegate creation
return TRUE;
}
-typedef struct {
- guint32 skips;
- MonoSecurityFrame *frame;
-} MonoFrameSecurityInfo;
-
-static gboolean
-callback_get_first_frame_security_info (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
-{
- MonoFrameSecurityInfo *si = (MonoFrameSecurityInfo*) data;
- MonoJitInfo *ji = frame->ji;
- MonoMethod *method;
-
- if (!ji)
- return FALSE;
-
- /* FIXME: skip all wrappers ?? probably not - case by case testing is required */
- method = jinfo_get_method (ji);
- if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
- method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
- method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
- method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
- method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) {
- return FALSE;
- }
-
- if (si->skips > 0) {
- si->skips--;
- return FALSE;
- }
-
- si->frame = mono_declsec_create_frame (frame->domain, ji);
-
- /* Stop - we only want the first frame (e.g. LinkDemand and InheritanceDemand) */
- return TRUE;
-}
-
-/**
- * ves_icall_System_Security_SecurityFrame_GetSecurityFrame:
- * @skip: the number of stack frames to skip
- *
- * This function returns a the security informations of a single stack frame
- * (after the skipped ones). This is required for [NonCas]LinkDemand[Choice]
- * and [NonCas]InheritanceDemand[Choice] as only the caller security is
- * evaluated.
- */
-MonoSecurityFrame*
+/* Obsolete */
+MonoObject*
ves_icall_System_Security_SecurityFrame_GetSecurityFrame (gint32 skip)
{
- MonoFrameSecurityInfo si;
-
- si.skips = skip;
- si.frame = NULL;
-
- mono_walk_stack (callback_get_first_frame_security_info, MONO_UNWIND_DEFAULT, &si);
-
- return (si.skips == 0) ? si.frame : NULL;
-}
-
-
-typedef struct {
- guint32 skips;
- MonoArray *stack;
- guint32 count;
- guint32 maximum;
-} MonoSecurityStack;
-
-static void
-grow_array (MonoSecurityStack *stack)
-{
- MonoDomain *domain = mono_domain_get ();
- guint32 newsize = (stack->maximum << 1);
- MonoArray *newstack = mono_array_new (domain, mono_defaults.runtimesecurityframe_class, newsize);
- int i;
- for (i=0; i < stack->maximum; i++) {
- gpointer frame = mono_array_get (stack->stack, gpointer, i);
- mono_array_setref (newstack, i, frame);
- }
- stack->maximum = newsize;
- stack->stack = newstack;
+ return NULL;
}
-static gboolean
-callback_get_stack_frames_security_info (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
+/* Obsolete */
+MonoArray*
+ves_icall_System_Security_SecurityFrame_GetSecurityStack (gint32 skip)
{
- MonoSecurityStack *ss = (MonoSecurityStack*) data;
- MonoJitInfo *ji = frame->ji;
- MonoMethod *method;
-
- if (!ji)
- return FALSE;
-
- /* FIXME: skip all wrappers ?? probably not - case by case testing is required */
- method = jinfo_get_method (ji);
- if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE ||
- method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE ||
- method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH ||
- method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK ||
- method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE) {
- return FALSE;
- }
-
- if (ss->skips > 0) {
- ss->skips--;
- return FALSE;
- }
-
- if (ss->count == ss->maximum)
- grow_array (ss);
-
- mono_array_setref (ss->stack, ss->count++, mono_declsec_create_frame (frame->domain, ji));
-
- /* continue down the stack */
- return FALSE;
+ return NULL;
}
static MonoArray *
return res;
}
-/**
- * ves_icall_System_Security_SecurityFrame_GetSecurityStack:
- * @skip: the number of stack frames to skip
- *
- * This function returns an managed array of containing the security
- * informations for each frame (after the skipped ones). This is used for
- * [NonCas]Demand[Choice] where the complete evaluation of the stack is
- * required.
- */
-MonoArray*
-ves_icall_System_Security_SecurityFrame_GetSecurityStack (gint32 skip)
-{
- MonoSecurityStack ss;
-
-#if defined(__ia64__) || defined(__s390__) || defined(__s390x__)
- skip--;
-#endif
-
- ss.skips = skip;
- ss.count = 0;
- ss.maximum = MONO_CAS_INITIAL_STACK_SIZE;
- ss.stack = mono_array_new (mono_domain_get (), mono_defaults.runtimesecurityframe_class, ss.maximum);
- mono_walk_stack (callback_get_stack_frames_security_info, MONO_UNWIND_DEFAULT, &ss);
- /* g_warning ("STACK RESULT: %d out of %d", ss.count, ss.maximum); */
- return ss.stack;
-}
-
static MonoClass*
get_exception_catch_class (MonoJitExceptionInfo *ei, MonoJitInfo *ji, MonoContext *ctx)
{
g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
- if (mono_security_cas_enabled ()) {
- g_print ("\nDecl security check : %ld\n", mono_jit_stats.cas_declsec_check);
- g_print ("LinkDemand (user) : %ld\n", mono_jit_stats.cas_linkdemand);
- g_print ("LinkDemand (icall) : %ld\n", mono_jit_stats.cas_linkdemand_icall);
- g_print ("LinkDemand (pinvoke) : %ld\n", mono_jit_stats.cas_linkdemand_pinvoke);
- g_print ("LinkDemand (aptc) : %ld\n", mono_jit_stats.cas_linkdemand_aptc);
- g_print ("Demand (code gen) : %ld\n", mono_jit_stats.cas_demand_generation);
- }
-
g_free (mono_jit_stats.max_ratio_method);
mono_jit_stats.max_ratio_method = NULL;
g_free (mono_jit_stats.biggest_method);
printf ("Number of try block holes %d\n", num_holes);
}
- if (mono_security_method_has_declsec (cfg->method_to_register))
- flags |= JIT_INFO_HAS_ARCH_EH_INFO;
-
if (COMPILE_LLVM (cfg))
num_clauses = cfg->llvm_ex_info_len;
else
mono_jit_stats.regvars += cfg->stat_n_regvars;
mono_jit_stats.inlineable_methods += cfg->stat_inlineable_methods;
mono_jit_stats.inlined_methods += cfg->stat_inlined_methods;
- mono_jit_stats.cas_demand_generation += cfg->stat_cas_demand_generation;
mono_jit_stats.code_reallocs += cfg->stat_code_reallocs;
mono_destroy_compile (cfg);
#include "mini-arch.h"
#include "regalloc.h"
-#include "declsec.h"
#include "mini-unwind.h"
#include "jit.h"
+#include "mono/metadata/class-internals.h"
+#include "mono/metadata/domain-internals.h"
+#include "mono/metadata/object.h"
+#include "mono/metadata/tabledefs.h"
+#include "mono/metadata/marshal.h"
+#include "mono/metadata/security-manager.h"
+#include "mono/metadata/exception.h"
+#include "mono/utils/mono-compiler.h"
+
#ifdef __native_client_codegen__
#include <nacl/nacl_dyncode.h>
#endif
int stat_n_regvars;
int stat_inlineable_methods;
int stat_inlined_methods;
- int stat_cas_demand_generation;
int stat_code_reallocs;
} MonoCompile;
gint32 max_basic_blocks;
gint32 locals_stack_size;
gint32 regvars;
- gint32 cas_declsec_check;
- gint32 cas_linkdemand_icall;
- gint32 cas_linkdemand_pinvoke;
- gint32 cas_linkdemand_aptc;
- gint32 cas_linkdemand;
- gint32 cas_demand_generation;
gint32 generic_virtual_invocations;
gint32 alias_found;
gint32 alias_removed;
mono_local_alias_analysis (MonoCompile *cfg);
/* CAS - stack walk */
-MonoSecurityFrame* ves_icall_System_Security_SecurityFrame_GetSecurityFrame (gint32 skip);
+MonoObject* ves_icall_System_Security_SecurityFrame_GetSecurityFrame (gint32 skip);
MonoArray* ves_icall_System_Security_SecurityFrame_GetSecurityStack (gint32 skip);
/* Generic sharing */