【发布时间】:2013-03-25 02:23:44
【问题描述】:
以下代码存在于企业库的日志记录应用程序块中的 LogEntry.cs 中:
private bool UnmanagedCodePermissionAvailable
{
get
{
if (!unmanagedCodePermissionAvailableInitialized)
{
// check whether the unmanaged code permission is available to avoid three potential stack walks
bool internalUnmanagedCodePermissionAvailable = false;
SecurityPermission unmanagedCodePermission =
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
// avoid a stack walk by checking for the permission on the current assembly. this is safe because there are no
// stack walk modifiers before the call.
if (SecurityManager.IsGranted(unmanagedCodePermission))
{
try
{
unmanagedCodePermission.Demand();
internalUnmanagedCodePermissionAvailable = true;
}
catch (SecurityException)
{ }
}
this.UnmanagedCodePermissionAvailable =
internalUnmanagedCodePermissionAvailable;
}
return this.unmanagedCodePermissionAvailable;
}
set
{
this.unmanagedCodePermissionAvailable = value;
unmanagedCodePermissionAvailableInitialized = true;
}
}
在进行多次 P/Invoke 调用之前调用该函数以检索各种信息以帮助填写 LogEntry 结构。如果“UnmanagedCodePermission”不可用,则将相应的 LogEntry 属性设置为指示这种情况的字符串(“XXX 不可用”)。
例如,LogEntry 想要获取 Win32 线程 ID,它使用 P/Invoke 调用的 Win32 函数 GetCurrentThreadId 来获取它。在调用 GetCurrentThreadId 之前,它会检查“未管理的代码权限”是否可用。如果是,它会调用,如果不是,它不会。像这样的:
private void InitializeWin32ThreadId()
{
if (this.UnmanagedCodePermissionAvailable)
{
try
{
this.Win32ThreadId = LogEntryContext.GetCurrentThreadId();
}
catch (Exception e)
{
this.Win32ThreadId = string.Format(
CultureInfo.CurrentCulture,
Properties.Resources.IntrinsicPropertyError,
e.Message);
}
}
else
{
this.Win32ThreadId = string.Format(CultureInfo.CurrentCulture,
Properties.Resources.IntrinsicPropertyError,
Properties.Resources.
LogEntryIntrinsicPropertyNoUnmanagedCodePermissionError);
}
}
据我了解,诚然,这并不多,由于安全/权限/信任,调用非托管代码(例如 P/Invoke)并不总是可能的。通过检查是否可以进行非托管代码调用,可以以统一的方式保护所有非托管调用。
当我编译这段代码时,我在这一行收到警告:
if (SecurityManager.IsGranted(unmanagedCodePermission))
这里是警告:
System.Security.SecurityManager.IsGranted(System.Security.IPermission)' 已过时:'IsGranted 已过时,将在 .NET Framework 的未来版本中删除。请改用 AppDomain 或 Assembly 的 PermissionSet 属性。
(请注意,我是在 .Net 4.0 上使用 VS2010 构建的)。
所以,看起来 IsGranted 已经过时了。我查看了 AppDomain 和 Assembly 的 PermissionSet 属性,并不清楚如何进行相同的检查。
在 LogEntry 的情况下,该信息看起来并不重要,因此如果非托管权限不可用,则不会将其视为严重故障。从相同的角度考虑以下问题。也就是说,如果非托管代码权限不可用,也不是什么大不了的事,没有信息我也可以活下去。
最后,有几个问题:
尝试保护对非托管代码(例如 P/Invoke)的调用是否是个好主意?有时,总是,从不?
如果保护这些调用是个好主意,那么这样做是否合理?有没有更好的办法?
在 .Net 4.0 中进行等效检查的正确(即不过时)方法是什么?
【问题讨论】:
标签: c# .net security pinvoke unmanaged