从Windows Vista开始,具有较低完整性级别(IL)的进程似乎无法向具有更高完整性级别的进程发送消息.从安全角度来看,这是有道理的,但它打破了我们的一些进程间通信.
我们有遗留应用程序(进程A),不幸的是必须以提升的"管理员"权限运行(通过将其快捷方式设置为始终以管理员身份运行来完成).有时它需要实例化一个单独的应用程序(进程B).因此,进程B继承了与进程A相同的提升权限(和IL).这就是问题所在.可能还有其他独立的进程B实例没有提升权限,并且所有这些进程B实例都需要能够相互发送消息.如果进程B的一个实例被提升而另一个实例没有提升,这显然会失败.
我知道我们可以使用ChangeWindowMessageFilterAPI方法在UIPI消息过滤器中打开漏洞,但这似乎不是理想的解决方案.相反,我宁愿让进程A生成具有降低权限的进程B,特别是它可以与其他进程B实例进行通信.我认为默认情况下其他进程B实例运行在"中"IL,因此我希望进程A使用相同的IL生成进程B实例.
我的搜索引导我使用CreateProcessAsUser和CreateRestrictedTokenAPI方法,但是尽管有这些文档,令牌和安全描述符的所有各个方面对我来说仍然非常混乱.
我也接触过一些线程这里(运行使用尽可能低的权限的进程中WINAPI和Windows上用C删除权限++),但我无法找到任何代码很好的例子.
任何人都可以为我提供一些简单但"正确"的代码,这将帮助我使用适当的Windows IL生成子进程吗?具体来说,我想要一个如何获取现有Process A令牌并将其转换为具有降低权限的示例(我很确定我可以弄清楚其余的).在修改进程'令牌之前,我真的不清楚是否需要复制进程'令牌.
我在C#中编写了一个小实用程序,以确保指定的文件夹及其所有内容都具有适当的访问权限(我希望为该Authenticated Users组提供完全访问权限).以下代码似乎可以正常用于更新顶级文件夹的ACL(访问控制列表):
SecurityIdentifier allUsers = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
InheritanceFlags iFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
FileSystemAccessRule newRule = new FileSystemAccessRule(allUsers,
FileSystemRights.FullControl, iFlags,
PropagationFlags.None, AccessControlType.Allow);
DirectoryInfo info = new DirectoryInfo(folderPath);
DirectorySecurity security = info.GetAccessControl();
security.AddAccessRule(newRule);
info.SetAccessControl(security);
Run Code Online (Sandbox Code Playgroud)
但是,我注意到,此新访问规则不会传播到其安全属性中未选中"包含可继承权限..."选项的子文件夹.这才有意义.所以,我想要做的是为任何这样的子文件夹重新打开安全权限继承.
我挖掘的ObjectSecurity.SetAccessRuleProtection方法应该是我需要的一半.但是,对于已经继承父级DACL的对象盲目使用上述方法似乎很草率.因此,我想确定哪些对象的权限继承被关闭,但我似乎无法找到返回此信息的相应方法或属性.有吗?我在这里错过了什么吗?
我已经阅读了很多关于这个主题的帖子,我想我终于明白了这个volatile关键词在C#中是如何运作的.我仍然想在这里问一下,以确保我理解正确的概念.请考虑以下代码:
class ThreadWrapper
{
public bool Enabled { get; set; }
private void ThreadMethod()
{
while (Enabled) { // ... Do work }
}
}
Run Code Online (Sandbox Code Playgroud)
根据我的理解,如果要设置另一个线程Enabled=false,原始线程可能不会立即(或者可能永远?)看到此更改.为了确保编译器不优化对Enabled属性的访问并依赖缓存值,更改代码如下所示应该解决问题.
public bool Enabled { get {return mEnabled;} set {mEnabled=value;} }
private volatile bool mEnabled;
Run Code Online (Sandbox Code Playgroud)
现在,只要读取Enabled值,就可以保证获得最新值,对吗?如果是这样,我应该能够将它用作简单的信号或标志(就像我上面的那样).
作为另一个例子,请考虑以下事项:
class C
{
private volatile int i;
private volatile bool enabledA;
private volatile bool enabledB;
void ThreadA()
{
i = 0; // Reset counter
while (enabledA)
{
// .. Do some other repeated work …Run Code Online (Sandbox Code Playgroud) 如果这个问题有点过于开放,请提前原谅我,但我在这里看过类似的语言讨论帖,所以我想我会冒险尝试.
无论如何,我已经阅读了几个关于正确实现IDisposable类的MSDN帮助页面和其他各种博客.我觉得我很了解事情,但我不得不怀疑建议的类结构是否存在缺陷:
public class DisposableBase : IDisposable
{
private bool mDisposed;
~DisposableBase()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!mDisposed)
{
if (disposing)
{
// Dispose managed resources
mManagedObject.Dispose();
}
// Dispose unmanaged resources
CloseHandle(mUnmanagedHandle);
mUnmanagedHandle = IntPtr.Zero;
mDisposed = true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
无论何时上述应该作为基类,您依赖子类的实现者在必要时正确覆盖Dispose(bool)方法.简而言之,派生类必须确保它们在其重写版本中调用基本Dispose(bool)方法.如果没有,基类的非托管资源可能永远不会被释放,从而破坏了IDisposable接口的主要目的.
我们都知道虚拟方法的好处,但似乎在这种情况下它们的设计不足.事实上,我认为虚拟方法的这个特殊缺点在尝试设计可视组件和类似的基础/派生类结构时经常表现出来.
使用受保护事件而不是受保护的虚拟方法,请考虑以下更改:
public class DisposeEventArgs : EventArgs
{
public bool Disposing { get; protected set; }
public DisposeEventArgs(bool disposing)
{
Disposing = disposing; …Run Code Online (Sandbox Code Playgroud) 我有一个用C#编写的实用程序来与我们的USB设备来回通信.我们使用通用HID驱动程序并将句柄包装到FileStream对象中的设备.我使用它BeginRead和BeginWrite方法读/写数据,不是因为我需要异步IO,而是因为我可以在设备进入非通信状态(有意或无意)时超时.所有读/写都在我自己的专用IO线程中完成.
我担心我做得不好,因为我已经看到了一些我怀疑是线程死锁的情况.这是我的相关Read方法的精简版(似乎工作得很好).
if (_readResult == null)
{
_readResult = _deviceStream.BeginRead(_readBuffer, 0, _readBuffer.Length, null, null);
}
if (_readResult.AsyncWaitHandle.WaitOne(IOTimeout, true))
{
int bytesRead = _deviceStream.EndRead(_readResult);
_readResult.AsyncWaitHandle.Close();
_readResult= null;
// … Copy bytes to another buffer
}
else
{
// … Timeout, so retry again in a bit
}
Run Code Online (Sandbox Code Playgroud)
我的主要问题是如果我需要终止我的IO线程并且我的设备不再通信,如何正确停止未完成BeginRead或BeginWrite调用.我不能只是打电话,EndRead因为它会坐在那里永远阻止.Filestream.Close在读/写操作处于挂起状态时调用是否安全?
我还要问,同时运行挂起的读写操作是否安全?例如,如果我的读取方法超时,我还能继续尝试写一些东西吗?
很难重现我目前的死锁问题,但真正奇怪的是它似乎是在IO线程被我的read方法"卡住"时开始的.我不确定除非我的代码按照我认为的方式工作,否则会发生这种情况.
假设我有一个Thread对象的引用,例如:
System.Threading.Thread thread;
Run Code Online (Sandbox Code Playgroud)
如果我想确定当前线程是否由此对象表示,是否应使用以下代码?
bool currentThread = (thread.ManagedThreadId == Thread.CurrentThread.ManagedThreadId);
Run Code Online (Sandbox Code Playgroud)
我很确定这样可以正常工作,但似乎很奇怪,没有更直接的方法来检查它.有吗?
想象一下一个表(名为Example),它有一个主键字段(KeyID)和一个外键字段(ForeignID).此外键用于将表中的行链接到单独表中的外部行/项,从而建立多对一关系.但是,对于我们的许多行,不存在这样的关系,因此我们的外键字段NULL位于这些行中.
现在,如果给出一个KeyID(例如123),获取包含具有匹配的ForeignID值的所有行的结果集的首选SQL是什么?
我天真地开始使用以下SQL:
SELECT E1.*
FROM Example E1
JOIN Example E2
ON E2.KeyID = 123
AND E2.ForeignID = E1.ForeignID
Run Code Online (Sandbox Code Playgroud)
当我们的匹配键行在ForeignID中具有正常值时,这非常有用.但是,如果出现了ForeignID,它将失败(不返回任何内容)NULL.做一些初步搜索后,我现在明白为什么(后读这样的问题这一个),但我还没有找到如何解决此限制的任何好的解决方案.
授予SQL Server的ANSI_NULLS设置我可以更改,但这似乎是一个肮脏的,可能有问题的黑客.
或者,我总是可以组成我自己的伪空值(如0)并将其粘贴在ForeignID列中而不是NULL,但这会破坏我为此列建立的外键约束.
那么如何最好地实现我想要的呢?
.net ×5
c# ×5
windows ×3
c++ ×1
filesystems ×1
idisposable ×1
io ×1
null ×1
permissions ×1
security ×1
sql ×1
sql-server ×1
usb ×1
winapi ×1