none
CORSEC_E_NO_EXEC_PERM with host assembly store RRS feed

  • Question

  • Hi.  I'm developing an application that hosts the CLR (2.0) to provide scripting capabilities.  The scripting is not for end users, and the app will ultimately want to store assemblies encrypted in its proprietary resource system, not as disk files.  As such, it provides the CLR an assembly store.  Getting the CLR hosted was a breeze, but getting the CLR to use my assembly store has been nothing but headaches.

    Right now in (relatively) simple tests I am getting CORSEC_E_NO_EXEC_PERM when loading a simple script EXE (made with C#) via the assembly store.  However, if I disable the assembly store and let CLR resolve assemblies from disk in the usual fashion, everything works fine.  This is under XP Pro, IA32, .NET 3.5 (but the app asks for v2.0.50727).

    The overall sequence of events leading to the error is as follows:

    1. The native app sets up the CLR.  The domain manager type is set to a type in a strong named C++/CLI assembly, presently called Inter.dll.  This is not in the GAC but is in the same directory as the app.

    2. The native app calls ICLRRuntimeHost::Start.

    3. CLR calls my GetNonHostStoreAssemblies, which returns my ICLRAssemblyReferenceList (which happens to be the same object; all the host interfaces are implemented in the same object except IStream).

    4. CLR calls my IsAssemblyReferenceInList for Inter, msvcm90d, and several framework assemblies.  I return true for these.

    5. Inter loads and my CHostControl::SetAppDomainManager gets called for the default app domain.

    6. SetAppDomainManager in native code obtains a pointer to a COM exported interface on the managed AppDomainManager implemented in Inter, and calls a bootstrap method on this.

    7. The bootstrap method does some internal work and then this:

    AppDomain::CurrentDomain->ExecuteAssemblyByName( "script, Version=1.0.0.0, Culture=neutral, PublicKeyToken=blablabla, processorarchitecture=msil" );

    Note the processorarchitecture has to be supplied or else I run into another problem: CLR asks for the x86 first, and if I return the MSIL, it refuses to load script.exe because it's MSIL and not x86.  However, if when asked for the x86 I either fail the call to IHostAssemblyStore::ProvideAssembly with ERROR_FILE_NOT_FOUND, or succeed but set the stream pointers to NULL (MSDN wasn't clear on which of these to do), then I do not get called again for the MSIL version, as I had understood I'm supposed to be - it just fails the load (with an exception).  But that's another horror story.

    8. My IsAssemblyReferenceInList gets called for "script", and I return false (meaning I want to provide this assembly).  Note script.exe is not in the GAC but is strong named.

    9. My IHostAssemblyStore::ProvideAssembly is called with the following info:

    Referenced identity: script, version=1.0.0.0, culture=neutral, publickeytoken=blablabla, processorarchitecture=msil
    Post policy identity: script, version=1.0.0.0, culture=neutral, publickeytoken=blablabla, processorarchitecture=msil
    App domain id: 1
    Policy level: 0x0

    10. I obtain the assembly in memory (presently by reading it from script.exe on disk but this is subject to change), and set up an IStream for it.

    11. I set the PDB's stream pointer to NULL (for now), the host context to 1, and the assembly ID to 1 (which is not used anywhere else), then return from IHostAssemblyStore::ProvideAssembly.

    12. CLR stats my IStream, virtual allocs a committed block big enough, reads my IStream in one chunk into it, then releases the IStream.  I've confirmed that this is all happening properly.

    Lucky 13. CLR throws this exception:

    System.IO.FileLoadException: Could not load file or assembly 'script, Version=1.0.0.0, Culture=neutral, PublicKeyToken=blablabla' or one of its dependencies. Failed to grant permission to execute. (Exception from HRESULT: 0x80131418)
    File name: 'script, Version=1.0.0.0, Culture=neutral, PublicKeyToken=blablabla' ---> System.Security.Policy.PolicyException: Execution permission cannot be acquired.
       at System.Security.SecurityManager.ResolvePolicy(Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, PermissionSet& denied, Boolean checkExecutionPermission)
       at System.Security.SecurityManager.ResolvePolicy(Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, PermissionSet& denied, Int32& securitySpecialFlags, Boolean checkExecutionPermission)
       at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
       at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
       at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
       at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
       at System.Reflection.Assembly.Load(String assemblyString, Evidence assemblySecurity)
       at System.AppDomain.ExecuteAssemblyByName(String assemblyName, Evidence assemblySecurity, String[] args)
       at System.AppDomain.ExecuteAssemblyByName(String assemblyName)

    That HRESULT is CORSEC_E_NO_EXEC_PERM.  The Fusion log has nothing to say because the binding itself succeeded - I just can't run the code.

    All I have to do to get it to work is add "script" to the non-host-store assemblies list, bypassing everything from step 8; when CLR loads the assembly on its own, it has no complaints running it.  I'm having a lot of trouble understanding why the same assembly that isn't a security problem when CLR loads it, is a security problem when I load it.

    I might also add that I get strange problems when I have assemblies of version 0.0.0.0, but I changed them all to 1.0.0.0, bringing me to the current problem as given above.

    Any help will be greatly appreciated.

    Regards,
    Kevin
    Monday, July 20, 2009 10:00 AM

Answers

  • Hi Hans, thanks for the tip.

    Indeed the immediate problem was fixed by overriding get HostSecurityManager and implementing HostSecurityManager::ResolvePolicy.  I did end up having to remove STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN from the CorBindToRuntimeEx call in order to avoid COR_E_CANNOT_SET_POLICY, which is kind of annoying.

    I didn't find any answer to the problem of not being asked for the MSIL after refusing to provide the x86; I'm still explicitly asking for an MSIL assembly as a workaround.

    I've subsequently run into a larger problem which I'll start another thread for.

    Thanks,
    Kevin
    • Marked as answer by Love4Brandy Tuesday, July 21, 2009 1:04 PM
    Tuesday, July 21, 2009 1:03 PM

All replies

  • Check this thread.   Check this blog post for your other issues.

    Hans Passant.
    Monday, July 20, 2009 1:01 PM
    Moderator
  • Hi Hans, thanks for the tip.

    Indeed the immediate problem was fixed by overriding get HostSecurityManager and implementing HostSecurityManager::ResolvePolicy.  I did end up having to remove STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN from the CorBindToRuntimeEx call in order to avoid COR_E_CANNOT_SET_POLICY, which is kind of annoying.

    I didn't find any answer to the problem of not being asked for the MSIL after refusing to provide the x86; I'm still explicitly asking for an MSIL assembly as a workaround.

    I've subsequently run into a larger problem which I'll start another thread for.

    Thanks,
    Kevin
    • Marked as answer by Love4Brandy Tuesday, July 21, 2009 1:04 PM
    Tuesday, July 21, 2009 1:03 PM