在部分信任环境 (SecurityPermission) 中调用 Marshal.GetHRForException
我有一些 IO 代码可以读取 try..catch 中的流。 它捕获 IOException 并调用 System.Runtime.InteropServices .Marshal.GetHRForException() 在 catch 内,尝试根据 HResult 采取不同的操作。 像这样的东西:
try
{
stream.Read(...);
}
catch (IOException ioexc1)
{
uint hr = (uint) Marshal.GetHRForException(ioexc1);
if (hr == ...)
do_one_thing();
else
do_another();
}
程序集已签名并标记为 AllowPartiallyTrustedCallersAttribute。
但是在 ASP.NET 中使用 trust="medium" 运行此代码时,出现此异常: 有
Request for the permission of type 'System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
几个问题:
- 我认为发生异常是因为 GetHRForException 调用非托管代码,而这在中等信任中是不允许的。 正确的?
- 此异常不是在执行 GetHRForException 时抛出,而是在对该方法进行 JIT 编译时抛出 - 正确吗? (堆栈跟踪显示了我的方法,但我 99% 确定没有发生 IO 异常)
- 如果是这样,有没有办法让我在部分信任环境中改变行为,这样我就不会调用 GetHRForException (非托管代码)哪里不允许? 换句话说,如何让 JIT 在编译时成功,同时在运行时评估代码是否应该调用 GetHRForException()? 像这样的事情:
catch (IOException ioexc1)
{
if (!OkToCallUnmanaged())
throw ioexc1;
uint hr = (uint) Marshal.GetHRForException(ioexc1);
if (hr == ...)
do_one_thing();
else
do_another();
}
我认为有一个运行时机制可以测试权限是否可用,但一直找不到它。
应用于我的代码,MethodA() 可能是调用 Read 的代码,然后在 catch 中尝试调用 GetHRForException()。 GetHRForException 是 MethodB()。 当 MethodA() 是 JIT 时,将评估 LinkDemand。 (此 LinkDemand 在我的中等信任 ASP.NET 场景中失败)。 如果我将 GetHRForException 移至新方法 MethodC() 中,并仅在命令式权限成功后有条件地调用 MethodC(),理论上我应该能够在 JIT 时避免 SecurityException,因为 MethodC() 将仅在 Permission.Demain() 成功后进行 JIT。
I have some IO code that reads a stream within a try..catch. It catches IOException and calls System.Runtime.InteropServices.Marshal.GetHRForException()
within the catch, in an attempt to take different actions based on the HResult. Something like this:
try
{
stream.Read(...);
}
catch (IOException ioexc1)
{
uint hr = (uint) Marshal.GetHRForException(ioexc1);
if (hr == ...)
do_one_thing();
else
do_another();
}
The assembly is signed and marked with AllowPartiallyTrustedCallersAttribute.
But running this code within ASP.NET with trust="medium", I get this exception:
Request for the permission of type 'System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
A couple questions:
- I think the exception is occurring because GetHRForException calls into unmanaged code, which is not permitted in medium trust. Correct?
- This exception is being thrown, not at the time of execution of GetHRForException, but at the time the method is being JIT'ed - Correct? (The stacktrace shows my method, but I am 99% certain that an IO exception has not occurred)
- If so, is there a way for me to vary the behavior in a partial trust environment, so that I don't call the GetHRForException (unmanaged code) where it is not permitted? In other words, how can I allow the JIT to succeed at compile time, while also evaluating at runtime whether the code should call GetHRForException()? Something like this:
catch (IOException ioexc1)
{
if (!OkToCallUnmanaged())
throw ioexc1;
uint hr = (uint) Marshal.GetHRForException(ioexc1);
if (hr == ...)
do_one_thing();
else
do_another();
}
I think there is a runtime mechanism for testing if permissions are available, but haven't been able to find it.
EDIT: Is this blog article the answer? ShawnFa of Microsoft says that you cannot do a try ... catch(SecurityException) around a method protected by a LinkDemand. If MethodA() calls MethodB(), and MethodB() is marked with LinkDemand for full trust, then the LinkDemand is checked with MethodA is Jit'ed. Therefore to avoid the SecurityException, I need to extract Marshal.GetHRForException into a separate method. Is that correct?
Applied to my code, MethodA() might be the code that calls Read, and then in the catch tries to call GetHRForException(). GetHRForException is MethodB(). The LinkDemand is evaluated when MethodA() is JIT'd. (This LinkDemand fails in my medium-trust ASP.NET scenario). If I move the GetHRForException into a new method, MethodC(), and conditionally call MethodC() only after an imperative permission.Demand() succeeds, theoretically I should be able to avoid the SecurityException at JIT time, because MethodC() will be JIT'd only after the permission.Demain() succeeds.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
所需的方法是 SecurityPermission.IsUnrestricted()< /a>. 它返回 true 或 false 指示是否允许该权限。 它不像 SecurityPermission.Demand()。 我将 IsUnresticted 与 SecurityPermissionFlag.UnmanagedCode 结合使用来查看是否允许程序集调用非托管代码,然后仅在允许的情况下调用非托管代码。
还有一个额外的转折。 JIT 编译器在编译方法时,会检查调用要编译的方法的任何方法上的 CodeAccessPermission LinkDemands。 Marshal.GetHRForException() 标有 LinkDemand。 因此,当在受限环境(如具有中等信任度的 ASP.NET)中运行时,我调用 Marshal.GetHRForException() 的方法将在 JIT 编译时抛出无法捕获的 SecurityException。 因此,在这种情况下,我们绝不能 JIT 调用 Marshal.GetHRForException() 的方法,这意味着我需要将 Marshal.GetHRForException() 分解为我的代码中的一个单独的方法,仅当 UnmanagedCode 为不受限制。
这是一些示例代码:
The method required is SecurityPermission.IsUnrestricted(). It returns a true or false indicating whether the permission is allowed or not. It does not demand a permission, as does SecurityPermission.Demand(). I use IsUnresticted with SecurityPermissionFlag.UnmanagedCode to see if the assembly is allowed to call unmanaged code, and then call the unmanaged code only if allowed.
There is one additional twist. The JIT compiler, when compiling a method, checks for CodeAccessPermission LinkDemands on any method called my the method to be compiled. Marshal.GetHRForException() is marked with a LinkDemand. Hence, my method that calls Marshal.GetHRForException() will throw an uncatchable SecurityException at the time of JIT compile, when run in a restricted environment, like ASP.NET with medium trust. Therefore, we must never JIT the method that calls Marshal.GetHRForException() in that case, which means I need to break out Marshal.GetHRForException() into a separate method in my code that is called (and thus JITted) only when UnmanagedCode is unrestricted.
Here's some example code:
提出 CAS 需求的代码如下所示
The code to make a CAS demand looks like this
是否 System.Runtime.InteropServices.Marshal.GetHRForException () 得到你通过检查异常类型得不到的东西吗? 看起来它使用了静态映射。
Does System.Runtime.InteropServices.Marshal.GetHRForException() get you anything you can't get by checking the type of exception? It looks like it uses a static mapping.