沙盒AppDomain中的SecurityException [英] SecurityException in Sandboxed AppDomain
问题描述
我正在尝试使用 CSharpCodeProvider (使用VS2010和.NET 4.0)将C#用作脚本语言.我希望脚本以最小的权限在受限制的AppDomain中运行.当前,在尝试实例化AppDomain中的类时出现异常(对 CreateInstanceAndUnwrap()的调用).这是一些简化的代码,可以重现异常:
I'm attempting to use C# as a scripting language using CSharpCodeProvider (using VS2010 and .NET 4.0). I want the scripts to be run in a restricted AppDomain with minimal permissions. Currently, I'm getting an exception while trying to instantiate a class in the AppDomain (The call to CreateInstanceAndUnwrap()). Here is some simplified code that reproduces the exception:
using System;
using System.Collections.Generic;
using Microsoft.CSharp;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Security;
using System.Security.Policy;
using System.Security.Permissions;
using System.Reflection;
using System.Runtime.Remoting;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
// set permissions
PermissionSet permissions = new PermissionSet(PermissionState.None);
permissions.AddPermission(new SecurityPermission( SecurityPermissionFlag.Execution));
AppDomainSetup adSetup = new AppDomainSetup();
adSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
//Create a list of fully trusted assemblies
Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
List<StrongName> sns = new List<StrongName>();
for (int x = 0; x < asms.Length; x++)
{
StrongName sn = asms[x].Evidence.GetHostEvidence<StrongName>();
if (sn != null && sns.Contains(sn) == false)
sns.Add(sn);
}
//this includes: "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
AppDomain domain = AppDomain.CreateDomain("NewAppDomain", AppDomain.CurrentDomain.Evidence, adSetup, permissions);//, sns);//, sn4, sn, sn2, sn3);
try
{
String asmName = Assembly.GetExecutingAssembly().FullName;
String typeName = typeof(ConsoleApp.ScriptRunner).FullName;
//Throws exception here
ScriptRunner scriptRunner = domain.CreateInstanceAndUnwrap(asmName, typeName) as ScriptRunner;
}
catch (SecurityException se)
{
System.Diagnostics.Debug.WriteLine(se.Message);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
}
public class ScriptRunner : MarshalByRefObject
{
public ScriptRunner()
{
//A breakpoint placed here is never reached.
CompilerParameters param;
param = new CompilerParameters();
param.CompilerOptions = "";
param.GenerateExecutable = false;
param.GenerateInMemory = true;
param.IncludeDebugInformation = false;
// C# compiler
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
CompilerResults results = codeProvider.CompileAssemblyFromFile(param, "Danger.cs");
}
}
}
该异常是从mscorlib引发的,它是一个 System.Reflection.TargetInvocationException ,它具有一个内部 System.Security.SecurityException .例外:
The exception is being thrown from mscorlib and it is a System.Reflection.TargetInvocationException that has an inner System.Security.SecurityException. Here is the exception:
System.Reflection.TargetInvocationException was unhandled
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache)
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(String assemblyName, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(String assemblyName, String typeName)
at System.AppDomain.CreateInstance(String assemblyName, String typeName)
at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)
at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)
at ConsoleApp.Program.Main(String[] args) in C:\Documents and Settings\NaultyCS\my documents\visual studio 2010\Projects\ConsoleApplication4\ConsoleApplication4\Program.cs:line 46
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.Security.SecurityException
Message=Request failed.
Source=ConsoleApplication4
GrantedSet=<PermissionSet class="System.Security.PermissionSet"
version="1">
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Flags="Execution"/>
</PermissionSet>
PermissionState=<PermissionSet class="System.Security.PermissionSet"
version="1"
Unrestricted="true"/>
RefusedSet=""
Url=file:///C:/Documents and Settings/NaultyCS/my documents/visual studio 2010/Projects/ConsoleApplication4/ConsoleApplication4/bin/Debug/ConsoleApplication4.EXE
StackTrace:
at ConsoleApp.ScriptRunner..ctor()
InnerException:
所以在我看来,mscorlib要求完全信任.我已将其添加为完全受信任的程序集,但没有任何效果.如果将权限设置为不受限制,则上面的代码有效:
So it appears to me that mscorlib is demanding full trust. I've added it as a fully trusted assembly, but it has no effect. The above code works if I set the permissions to unrestricted:
PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted);
但是我想限制AppDomain.我在这里做什么错了?
But I want to restrict the AppDomain. What am I doing wrong here?
推荐答案
抱歉,后期编辑.尝试以下方法.我安装了它,并使用测试应用程序在Visual Studio中运行.附带说明一下,我个人不喜欢构造函数中的逻辑",因为真正的错误倾向于被隐藏.下面的步骤将Compile逻辑从构造函数移到了新方法.
Sorry for the late edit. Try the following. I got it up and running in Visual Studio with a test app. On a side note, I personally do not like "logic" in constructors because the true error tends to get a little hidden. The steps below have the Compile logic moved from the constructor to a new method.
- 确保您的控制台应用程序具有强名称"/已签名".
-
包括sns变量作为调用AppDomain.CreateDomain的最后一个参数. LinkDemand权限要求您的ConsoleApp受到完全信任.
- Ensure your Console App has a StrongName / Signed.
Include the sns variable as the last parameter to call AppDomain.CreateDomain. The LinkDemand Permission requires your ConsoleApp to be fully trusted.
AppDomain domain = AppDomain.CreateDomain("NewAppDomain", AppDomain.CurrentDomain.Evidence, adSetup, permissions, sns.ToArray());
更改asmName以使用程序集的完整文件路径.
Change the asmName to use the Full File Path to your assembly.
String asmName = Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName;
将CreateInstanceAndUnwrap调用删除为以下两行代码
Delete the CreateInstanceAndUnwrap call to the following 2 lines of code
var handle = Activator.CreateInstanceFrom(domain, asmName, typeName);
var scriptRunner = (ScriptRunner)handle.Unwrap();
将所有代码从构造方法中移至新方法,例如开始".
Move all your code from the Constructor to a new method such as "Start".
添加一行以调用Start方法.
Add the line to call the Start method.
scriptRunner.Start();
添加FileIOPermission来读取您的Danger.cs文件.
Add the FileIOPermission to read your Danger.cs file.
permissions.AddPermission(new FileIOPermission(PermissionState.None) { AllFiles = FileIOPermissionAccess.Read });
这篇关于沙盒AppDomain中的SecurityException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!