Unit testing with Roslyn.Services.Workspace results in a SecurityException while working at x86 target
Asked Answered
H

2

7

I'm working on set of constants for my project, and I'd like to use to verify some of them in source code level. To achieve this, I'm loading entire solution using following snippet into AppDomain with IsFullyTrusted == true and IsHomogenous == true, i.e. remoting is enabled with x86 platform target:

// load workspace, i.e. solution from Visual Studio
var workspace = Roslyn.Services.Workspace.LoadSolution(solutionFile);

Test runners for NCrunch and NUnit with x86 platform with Roslyn

But while using either 1.45 or 2.6.2 nunit-console-x86.exe with platform configuration x86 as test runners, I'm constantly getting following 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.CheckSecurity(ParseRecord pr)
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ParseObject(ParseRecord pr)
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Parse(ParseRecord pr)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum)
   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.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.<>c__DisplayClass6.<OnImportsSatisfied>b__1(IWorkspaceServiceProvider wsp)
   at Roslyn.Services.Host.WorkspaceServiceProvider.ConstructService(Type type)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Roslyn.Services.Host.WorkspaceServiceProvider.GetService[TWorkspaceService]()
   at Roslyn.Services.SolutionServices..ctor(IWorkspaceServiceProvider workspaceServices)
   at Roslyn.Services.Solution..ctor(SolutionId id, String filePath, VersionStamp version, VersionStamp latestProjectVersion, IWorkspaceServiceProvider workspaceServices)
   at Roslyn.Services.Host.SolutionFactoryServiceFactory.SolutionFactoryService.CreateSolution(SolutionId id)
   at Roslyn.Services.Host.TrackingWorkspace.CreateNewSolution(ISolutionFactoryService solutionFactory, SolutionId id)
   at Roslyn.Services.Host.TrackingWorkspace..ctor(IWorkspaceServiceProvider workspaceServiceProvider, Boolean enableBackgroundCompilation, Boolean enableInProgressSolutions)
   at Roslyn.Services.Host.HostWorkspace..ctor(IWorkspaceServiceProvider workspaceServiceProvider, Boolean enableBackgroundCompilation, Boolean enableInProgressSolutions, Boolean enableFileTracking)
   at Roslyn.Services.Host.LoadedWorkspace..ctor(IWorkspaceServiceProvider workspaceServiceProvider, IDictionary`2 globalProperties, Boolean enableBackgroundCompilation, Boolean enableFileTracking)
   at Roslyn.Services.Host.LoadedWorkspace.LoadSolution(String solutionFileName, String configuration, String platform, Boolean enableFileTracking)
   at Roslyn.Services.Workspace.LoadSolution(String solutionFileName, String configuration, String platform, Boolean enableFileTracking)

There is a discussion on NCrunch forum, but I have tried all following options without success:

  • Add [assembly: AllowPartiallyTrustedCallers] to AssemblyInfo.cs
  • Add [assembly: SecurityRules(SecurityRuleSet.Level1)] to AssemblyInfo.cs
  • Add <NetFx40_LegacySecurityPolicy enabled="true" /> to app.config
  • Run VS2012 as Administrator
  • Decorate both unittests and implementation with [SecuritySafeCritical]
  • Update: create new AppDomain and provide
    • PermissionState.Unrestricted, SecurityPermissionFlag.AllFlags and DataProtectionPermissionFlags.AllFlags
    • Add Host Evidence: SecurityZone.MyComputer, System.Security.Policy.Hash and System.Security.Policy.StrongName
    • Add all assemblies (both mine and Roslyn CTP) to fullTrustAssemblies while creating of AppDomain

Update #2

This exception happens only while I'm running test under x86 configuration, after I had switched to x64 platform configuration, everything seems to work fine

Question

Are there any other attributes or configuration changes to app.config or AppDomain that could help to enable deserialization in .NET Framework remoting for System.Runtime.Remoting.ObjRef while running under x86 configuration?

Temporary solution

Switch to x64 build configuration only for unittest project(s)

Source code

Additional information

Also I notice...

  1. A lot of instances of Roslyn.Services.dll hang in background, after all tests had been completed.
  2. Lack of Host Evidences for NCrunch: System.Security.Policy.Hash and System.Security.Policy.StrongName with test runner assembly name
  3. MSIL (should be x64 inside) and 2.6.2 nunit-console.exe test runner are working fine, so it looks like Roslyn configuration/remoting/security configuration issue.
Hilton answered 6/5, 2013 at 7:4 Comment(0)
G
4

It looks like is executing the tests in Partial Trust, whereas Resharper is running them in Full Trust.

Roslyn has not been tested in Partial Trust scenarios. There are likely to be accesses to APIs that require Full Trust.

I haven't used ncrunch, but maybe there is a way to configure it to run the tests in Full Trust?

Gibert answered 6/5, 2013 at 15:17 Comment(4)
NCrunch AppDomain has both IsFullyTrusted == true and IsHomogenous == true, so NCrunch has FullTrust permissions, i.e. remoting is enabled. Is it possible that it happens because AppDomain configration: lack of System.Security.Policy.Hash and System.Security.Policy.StrongName at test runner AppDomain or any other configurations?Hilton
Same exception appears while using nunit-console-x86.exe, but not nunit-console.exe! Looks this is not only NCrunch related issueHilton
So, everything seems to work fine after I have switched to "64bit" platform target only for unittest project both at Visual Studio 2012 and NCRunchHilton
Unfortunately it also sounds like you are dealing with some bugs for the nunit-console-x86. I have run into the same thing when I tried going from 64 bit to 32 bit. Is it a large code base you are testing?Gand
M
1

I want to add something!

After upgrading an NUnit instance I manage to run to both 2.6.2 and 2.6.3 of the software, my team ran into similar issues with this exact System.Security exception that Akim was seeing.

We were creating an IpcChannel with some of our custom NUnit logic that wasn't created with the right trust settings, so we had to change something that looked like:

IpcChannel channel = new IpcChannel(string.Format("localhost:{0}", portNum));

To -

BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();

var properties = new System.Collections.Hashtable();
properties["name"] = "ipc";
properties["priority"] = "20";
properties["portName"] = string.Format("localhost:{0}", portNum);

IpcChannel channel = new IpcChannel(properties, clientProvider, serverProvider);

Just a quick fix I noticed that I figured I would forward to anybody seeing something similar that can't just switch their platform settings. To be fair, it took me about four hours to figure out so I didn't want the knowledge to go to waste.

Mobley answered 13/11, 2013 at 15:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.