I am getting the following error when I trying to enable code access security in a sandboxed app domain.
Inheritance security rules violated by type: 'XXX'. Derived types must either match the security accessibility of the base type or be less accessible.
Here is what I have: Plugin assembly has a class which implements an interface defined in a sdk assembly. Plugin assembly is not signed. Also, the plugin assembly has [assembly: SecurityTransparent] in AssemblyInfo.cs Example:
public Class Bar : AbstractBase
{
// This class implements an abstract method defined in the base class
}
AbstractBase is defined in the SDK binary and it is signed. Also, when I create a domain in the executing assembly, it is marked as Trusted.
[SecuritySafeCritical] public abstract class AbstractBase : MarshalByRefObject, IDisposable { public abstract void BaseMethod();
[SecurityCritical]
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.Infrastructure)]
public override object InitializeLifetimeService()
{
var lease = (ILease)base.InitializeLifetimeService();
if (lease != null && lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.FromHours(1);
lease.SponsorshipTimeout = TimeSpan.FromHours(1);
lease.RenewOnCallTime = TimeSpan.FromHours(1);
}
return lease;
}
protected void MethodFoo()
{
...
}
public virtual Foo FooItIs{get;set;} // Foo is a class which is a MarshallByRefObject and is implemented in the executing assembly
}
Here is what I have tried in AssemblyInfo.cs of SDK binary.
[assembly: AllowPartiallyTrustedCallers]
[assembly: SecurityRules(SecurityRuleSet.Level2, SkipVerificationInFullTrust = true)]
//[assembly: SecurityRules(SecurityRuleSet.Level1)]
Finally, there is the executing assembly which creates a domain and applies security restriction. I get the exception when I call CreateInstanceAndUnWrap.
private void CreateAppDomain()
{
AppDomainSetup domainSetup = new AppDomainSetup();
domainSetup.ApplicationName = "Plugins";
domainSetup.ApplicationBase = Section.Instance.BaseDirectory;
domainSetup.ConfigurationFile = domainSetup.ApplicationName + ".config";
PermissionSet domainPermissions = new PermissionSet(PermissionState.None);
domainPermissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
domainPermissions.AddPermission(new IsolatedStorageFilePermission(PermissionState.Unrestricted));
domainPermissions.AddPermission(new FileIOPermission(PermissionState.Unrestricted));
domainPermissions.AddPermission(new System.Net.WebPermission(PermissionState.Unrestricted));
domainPermissions.AddPermission(new System.Net.Mail.SmtpPermission(PermissionState.Unrestricted));
domainPermissions.AddPermission(new System.Configuration.ConfigurationPermission(PermissionState.Unrestricted));
domainPermissions.AddPermission(new System.Data.SqlClient.SqlClientPermission(PermissionState.Unrestricted));
StrongName plugins = typeof(AbstractBase).Assembly.Evidence.GetHostEvidence<StrongName>();
this.appDomain = AppDomain.CreateDomain(domainSetup.ApplicationName, null,
domainSetup, domainPermissions,
plugins);
}
And here is how I create an instance:
action =
this.appDomain.CreateInstanceFromAndUnwrap(
Path.Combine(pluginProperties.AssemblyBaseDirectory, pluginProperties.AssemblyName),
className) as
AbstractBase;
I am not sure what it is I am missing or is my architecture wrong in some way for code access security? Any help is appreciated!
Edit: Here is the stack trace. My UT does the exact same thing described above
at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type) at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase) at System.Activator.CreateInstanceFromInternal(String assemblyFile, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo) at System.AppDomain.CreateInstanceFrom(String assemblyFile, String typeName) at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String typeName) at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String typeName) at Microsoft.Windows.Infrastructure.MissionControl.Eventing.Agent.Tests.ActionProcessorTests.TestActionExecuted() in ActionProcessorTests.cs: line 196
Well, this is an old post, but I stumbled across it while trying to solve the same problem. The problem is that you've marked the entire AbstractBase class with the SecuritySafeCritical
, but the Bar class, because it is unsigned, must be SecurityTransparent
. Deriving a SecurityTransparent
class from a SecuritySafeCritical
class is not allowed.
The solution is to remove the [SecuritySafeCritical]
attribute from the AbstractBase class. Because you've marked the antire assembly as AllowPartiallyTrustedCallers
, the AbstractBase class will default to SecurityTransparent
, and both AbstractBase and Bar will be Transparent.
Then, when you need access to SecuritySafeCritical
or SecurityCritical
functions, you would mark the individual function inside of AbstractBase as SecuritySafeCritical
. This will allow those methods to access more restricted classes.