Build/Test Issues

Unit testing with classes from Roslyn.Services namespace results in a SecurityException

Started by distilled on 30,019 views

When the following test is run with NCrunch I receive a SecurityException:


[Fact]
public void Create_solution()
{
    ProjectId projectId;
    DocumentId documentId;

    const string Title = "Untitled";

    var solution =
        Solution.Create(SolutionId.CreateNewId())
                .AddCSharpProject(Title, Title, out projectId)

                .UpdateCompilationOptions(projectId, new CompilationOptions(OutputKind.DynamicallyLinkedLibrary))

                .AddMetadataReference(projectId, MetadataReference.Create("mscorlib"))
                .AddMetadataReference(projectId, MetadataReference.Create("Microsoft.CSharp"))
                .AddMetadataReference(projectId, MetadataReference.Create("System"))
                .AddMetadataReference(projectId, MetadataReference.Create("System.Core"))

                .AddDocument(projectId, "MyFile.cs", string.Empty, out documentId);

    Assert.NotNull(solution);
}


This test runs fine when executed via the Visual Studio unit test runner, or the ReSharper unit test runner.

The exception details are:


*** Failures ***

Exception
System.Security.SecurityException: System.Security.SecurityException : Type System.Runtime.Remoting.ObjRef and the types derived from it (such as System.Runtime.Remoting.ObjRef) are not permitted to be deserialized at this security level.

Server stack trace: 
   at System.Runtime.Serialization.FormatterServices.CheckTypeSecurity(Type t, TypeFilterLevel securityLevel)
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ParseObject(ParseRecord pr)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, IMethodCallMessage methodCallMessage)
   at System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryRequestMessage(String objectUri, Stream inputStream, Boolean bStrictBinding, TypeFilterLevel securityLevel)
   at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at Roslyn.Utilities.RemoteServices.Initialize(Int32 clientProcessId)
   at Roslyn.Utilities.RemoteServices.StartRemoteServicesProcess()
   at Roslyn.Utilities.RemoteServices.get_Instance()
   at Roslyn.Utilities.RemoteServices.CreateInstance[T]()
   at Roslyn.Services.Host.TemporaryStorageServiceFactory.CreateService(IWorkspaceServiceProvider workspaceServices)
   at Roslyn.Services.Host.WorkspaceServiceProviderFactory.Provider.<>c__DisplayClass7.<.ctor>b__4()
   at Roslyn.Utilities.NonReentrantLazy`1.get_Value()
   at Roslyn.Services.Host.WorkspaceServiceProviderFactory.Provider.GetService[TWorkspaceService]()
   at Roslyn.Services.SolutionServices..ctor(IWorkspaceServiceProvider workspaceServices, ILanguageServiceProviderFactory languageServicesFactory)
   at Roslyn.Services.Solution..ctor(SolutionId id, String filePath, VersionStamp version, VersionStamp latestProjectVersion, ILanguageServiceProviderFactory languageServiceProviderFactory, IWorkspaceServiceProvider workspaceServices)
   at Roslyn.Services.Solution.Create(SolutionId id)
   at Core.Tests.Models.PostTests.Create_solution() in E:\Projects\Compilify\Tests\Core.Tests\Models\ProjectTests.cs:line 20#0
System.Security.SecurityException: System.Security.SecurityException : Type System.Runtime.Remoting.ObjRef and the types derived from it (such as System.Runtime.Remoting.ObjRef) are not permitted to be deserialized at this security level.

Server stack trace: 
   at System.Runtime.Serialization.FormatterServices.CheckTypeSecurity(Type t, TypeFilterLevel securityLevel)
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ParseObject(ParseRecord pr)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, IMethodCallMessage methodCallMessage)
   at System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryRequestMessage(String objectUri, Stream inputStream, Boolean bStrictBinding, TypeFilterLevel securityLevel)
   at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at Roslyn.Utilities.RemoteServices.Initialize(Int32 clientProcessId)
   at Roslyn.Utilities.RemoteServices.StartRemoteServicesProcess()
   at Roslyn.Utilities.RemoteServices.get_Instance()
   at Roslyn.Utilities.RemoteServices.CreateInstance[T]()
   at Roslyn.Services.Host.TemporaryStorageServiceFactory.CreateService(IWorkspaceServiceProvider workspaceServices)
   at Roslyn.Services.Host.WorkspaceServiceProviderFactory.Provider.<>c__DisplayClass7.<.ctor>b__4()
   at Roslyn.Utilities.NonReentrantLazy`1.get_Value()
   at Roslyn.Services.Host.WorkspaceServiceProviderFactory.Provider.GetService[TWorkspaceService]()
   at Roslyn.Services.SolutionServices..ctor(IWorkspaceServiceProvider workspaceServices, ILanguageServiceProviderFactory languageServicesFactory)
   at Roslyn.Services.Solution..ctor(SolutionId id, String filePath, VersionStamp version, VersionStamp latestProjectVersion, ILanguageServiceProviderFactory languageServiceProviderFactory, IWorkspaceServiceProvider workspaceServices)
   at Roslyn.Services.Solution.Create(SolutionId id)
   at Create_solution() in Tests.cs:line 20#1


Hi Distilled,

Thanks for posting!

I suspect this may be due to a difference in the serialization security level between the NCrunch test runner and the other test runners you're using.

There is a way you can control this security level via the .config file used for your test environment. I've found an article that explains how to do this, although it does assume that you have some level of knowledge or control over the channel used for serialization. Are there any other components involved in the solution you're working in, or is it just the simple interaction with Roslyn?
Thanks for the quick reply, Remco! I've been able to reproduce the issue on two workstations with the xUnit test posted above. The test is solely dependent on Roslyn -- I removed any dependencies it had on my code just to be sure I wasn't responsible.
Thanks. I'll note this down to look into and fix in a future revision. Did you have any luck with adding the security configuration into the .config file?
Changing the .config file didn't fix the problem, unfortunately.
Something else that may work is to add the following attribute to your AssemblyInfo.cs file:

[assembly: AllowPartiallyTrustedCallers]

Does this do the trick?
I have reproduced same issue with nCrunch 1.45.0.12 for VS2012 and Roslyn CTP September 2012 1.2.20906.2. And [assembly: AllowPartiallyTrustedCallers] does not help.

ps: ReSharper test runner works fine
Hi Akim -

I believe this is related to the same issue described in this troubleshooting page (the security verification exception). Do the suggestions on this page solve the problem?

Edited

Remco wrote:Hi Akim -

I believe this is related to the same issue described in this troubleshooting page (the security verification exception). Do the suggestions on this page solve the problem?


I have tried to 'Specify a .NET 2.0 compatible security ruleset' without any results

#if NCRUNCH
[assembly: SecurityRules(SecurityRuleSet.Level1)]
#endif


I have no any security attributes to disable ('Disable .NET security attributes for NCrunch builds '), but I also try to add app.config with following content

<configuration>
  <runtime>
    <!-- enables legacy CAS policy for this process -->
    <NetFx40_LegacySecurityPolicy enabled="true" />
  </runtime>
</configuration>


also without any results.

Source code is at github, in case if you need to check something yourself

I also tried to turn off options 'instrument output assembly' and 'analyze line execution times' without any success
Thanks Akim. I've had a good go at trying to resolve and work around this problem using the sample solution you provided. I'm wondering if you can share some more information on the context in which you are working - is this for a critical application where NCrunch simply must work, or for a test project to learn more about Roslyn?

The reason I ask is that with considerable effort I still haven't yet found a way to solve or work around this problem. My suspicion is that there is something complex happening within the .NET security model that is specific to the way that Roslyn is transferring data between domains, although more research and experimentation is required to find exactly what is happening. If possible, I'd prefer to put this issue on the backlog to be addressed as part of a maintenance release. Would this work for you?

Cheers,

Remco
Hi Remco,

I'm wondering if you can share some more information on the context in which you are working - is this for a critical application where NCrunch simply must work, or for a test project to learn more about Roslyn?


For now this is my pet project, where I analyzing source code using Roslyn CTP, but when Microsoft will release Roslyn as bootstrapping compiler for .Net, I believe, it will be "critical application where NCrunch simply must work".

I had tried to create new AppDomain and provide it with FullTrust from within unittest, but same error appeared.

Also I have noticed that NCrunch AppDomain itself has AppDomain with
currentDomain.IsFullyTrusted == true; //for both NCrunch and ReSharper
, so remoting deserialization should not be forbidden according to Automatic Deserialization in .NET Framework Remoting

I also compared AppDomain settings for NCrucnh and ReSharper, and found that they are slightly different (json and other inputs are at gist.github.com)


  • NCrunch Evidence contains only:

    • System.Security.Policy.Zone "MyComputer" and System.Security.Policy.Url with "nCrunch.TaskRunner.DLL"

  • ReSharper Evidence contains:
  • System.Security.Policy.Zone "MyComputer" and System.Security.Policy.Url with "JetBrains.ReSharper.TaskRunner.CLR4.MSIL.exe"
    • And System.Security.Policy.Hash
    • And StrongName for "JetBrains.ReSharper.TaskRunner.CLR4.MSIL.exe"


Additional evidences for ReSharper:

...
<<System.Security.Policy.Hash version="2">
	<hash algorithm="SHA1"
		value="46E80C23AD02A4378F9B4606EB6D5C3BB35D080A"/>
	<hash algorithm="SHA256"
		value="ED8650569B27F8BDDD6F8301AF7A8DC4E31A919A5C5D5769B2F63631794454E8"/>
	<hash algorithm="MD5"
		value="5A4D962AB80A472E8A88698B644D5E33"/>
</System.Security.Policy.Hash>
>,

<<StrongName version="1"
	Key="002400000480000094000000060200000024000052534131000400000100010087F63BA6A789C30E210E7EC987234AD9FE33BAF7367993BAB1B312D6F72CA296B91ED5C658964FFB9E7570EB184A527C68C6BDBA41CFE67D8CFD3F888234206BF39205A3652D3AF3445BB6F715FDAC532E289FEA41229BAC37762B67EB16F58FEE717D2465FCA9EE17F08ED16772A1FC52C1C17022E1F0D9BDD004524A663ACA"
	Name="JetBrains.ReSharper.TaskRunner.CLR4.MSIL"
	Version="7.1.3000.2254"/>
>,
...


Also ReSharper AppDomain has `ShadowCopyFiles == true`, but it should no affect remoting

So, I'm still looking for a solution. Do you have any sample of creation of new AppDomain for nCrunch from scratch for testing interaction between AppDomains? My sample based upon stackoverflow sandbox sample, but it has no permissions for deserialization while I'm creating it from NCrunch.
[h]Same exception appears while using `nunit-console-x86.exe`[/h], but not `nunit-console.exe`! Looks this is not only NCrunch related issue
It looks as though this exception is actually an x64/x86 exception in disguise.

After setting the 'Use CPU Architecture' NCrunch project-level configuration option to 'x64' for all the projects in the solution, the problem went away.

NCrunch normally defaults to x86 when projects are built for AnyCPU. I believe Resharper defaults to x64 for AnyCPU test environments on an x64 processor, so this would explain the difference in behaviour. Most likely Roslyn is following the same behaviour as Resharper in building a test process or domain in which to do its work.

Thanks for sharing the tip about the NUnit behaviour differences ... This saved me many hours of frustratingly digging through CLR security settings.

Edited

Thx Remco!

It is enough for my unittest assembly to has "64bits" as Platform Target and also update NCrunch configuration to run on 64bits to work fine with Roslyn CTP Workspaces :)
ps: btw, I had same issue with SQLite (x86/x64) 1.0.81+ fron NuGet platforms configuration

Post a reply

Log in to reply.