【问题标题】:Windows 2008 RenderFarm Service: CreateProcessAsUser "Session 0 Isolation" and OpenGLWindows 2008 RenderFarm 服务:CreateProcessAsUser“会话 0 隔离”和 OpenGL
【发布时间】:2011-01-28 16:22:16
【问题描述】:

我有一个旧的 Windows 服务器服务和(衍生的)应用程序,在 XP-64 和 W2K3 中运行良好,但在 W2K8 中失败。我相信这是因为新的“Session 0 isolation”功能。

因此,我正在寻找代码示例/安全设置 mojo,它可以让您从 Windows 服务为 Windows 2008 Server 创建一个新进程,以便我可以恢复(并可能超越)以前的行为。我需要一个解决方案:

  1. 在非零会话中创建新进程以绕过会话 0 隔离限制(无法从会话 0 访问图形硬件) - 官方 MS 行是:

因为会话 0 不再是用户 会话,正在运行的服务 会话 0 无权访问 视频驱动程序。这意味着任何 服务进行渲染的尝试 图形失败。查询显示 Session 中的分辨率和颜色深度 0 报告正确的结果 系统高达 1920x1200 在 每像素 32 位。

  1. 新进程获得可用于创建 Windows DC 的 Windows 工作站/桌面(例如 winsta0/default)。我在这里找到了一个解决方案(在交互式会话中启动 OK):Starting an Interactive Client Process in C++

  2. Windows DC 在用作OpenGL DescribePixelFormat enumeration 的基础时,能够找到并使用硬件加速格式(在适当配备 OpenGL 硬件的系统上)。请注意,我们当前的解决方案工作正常在 XP-64 和 W2K3 上,除非终端服务会话正在运行(VNC 工作正常。)一个还允许进程工作的解决方案(即,即使终端服务会话打开,也可以使用 OpenGL 硬件加速运行)将是狂热的,虽然不是必需的。

我目前停留在第 1 项,尽管有一些类似的帖子讨论了这个问题(如 thisthis - 它们不是合适的解决方案,因为不能保证记录用户会话已经从“获取”会话 ID,也不是从 LocalSystem 帐户运行(我正在从服务的域帐户运行,我可以在合理范围内调整权限,尽管我更愿意不必升级优先级以包含 SeTcbPrivileges。)

例如 - 这是一个我认为应该可以工作的存根,但在调用 SetTokenInformation 时总是返回错误 1314(即使 AdjustTokenPrivileges 没有返回错误)我也使用了一些涉及“LogonUser”的替代策略(而不是打开现有的进程令牌),但我似乎无法换出会话 ID。

我也怀疑在所有情况下都使用 WTSActiveConsoleSessionId(例如,如果没有交互式用户登录) - 尽管在没有登录会话的情况下运行服务的快速测试似乎返回了合理的会话值(1 )。

为了便于阅读,我删除了错误处理(仍然有点混乱 - 道歉)

    //Also tried using LogonUser(..) here
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
                         | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID
                         | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY
                         | TOKEN_DUPLICATE, &hToken)

GetTokenInformation( hToken, TokenSessionId, &logonSessionId, sizeof(DWORD), &dwTokenLength )

DWORD consoleSessionId = WTSGetActiveConsoleSessionId();

/* Can't use this - requires very elevated privileges (LOCAL only, SeTcbPrivileges as well)   
   if( !WTSQueryUserToken(consoleSessionId, &hToken))
...
   */

DuplicateTokenEx(hToken, (TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE), NULL, SecurityIdentification, TokenPrimary, &hDupToken))


    // Look up the LUID for the TCB Name privilege.
LookupPrivilegeValue(NULL, SE_TCB_NAME, &tp.Privileges[0].Luid))

    // Enable the TCB Name privilege in the token.
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (!AdjustTokenPrivileges(hDupToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, 0))
    {
        DisplayError("AdjustTokenPrivileges");
           ...
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        DEBUG( "Token does not have the necessary privilege.\n");
    } else {
        DEBUG( "No error reported from AdjustTokenPrivileges!\n");
    }                                                                                                                                                                                        // Never errors here

   DEBUG(LM_INFO, "Attempting setting of sessionId to: %d\n", consoleSessionId );

   if (!SetTokenInformation(hDupToken, TokenSessionId, &consoleSessionId, sizeof(DWORD)))
           *** ALWAYS FAILS WITH 1314 HERE ***

在调用 SetTokenInformation 之前,所有调试输出看起来都很好 - 我看到会话 0 是我当前的进程会话,在我的情况下,它正在尝试设置会话 1(WTSGetActiveConsoleSessionId 的结果)。 (请注意,我是通过 VNC 而非 RDC 登录 W2K8 框的)

所以 - 一个问题:

  1. 这种方法是否有效,还是所有服务启动的进程都被有意限制在会话 0 中?
  2. 是否有更好的方法(缺少“登录时启动”和服务器自动登录?)
  3. 此代码是否有问题,或者创建进程令牌的不同方法,我 可以 换出会话 ID 以指示我想在新会话中生成进程?我确实尝试使用 LogonUser 而不是 OpenProcessToken,但这也不起作用。 (此时我不在乎所有衍生进程是否共享相同的非零会话。)

非常感谢任何帮助 - 谢谢!

【问题讨论】:

    标签: opengl windows-services windows-server-2008 createprocessasuser session-0-isolation


    【解决方案1】:

    对于有兴趣解决此问题的任何人:

    我与 LogonSDK 团队的 MS Support 讨论了这个问题。似乎不可能以编程方式完全模拟交互式用户,这样您就可以得到一个物理控制台和相关的 GDI 构造,而且我们基本上“很幸运”它一直工作到现在。他们确实确认会话 0 隔离是回归的根本原因。

    他们的建议是启用自动登录到交互式会话,并重构服务以与交互式会话中的新客户端组件对话。为了解决此问题的安全性缺点,他们建议实施 shell 替换,以便在登录时将服务器置于“Kiosk”模式(例如,没有适当的凭据就无法访问 Explorer 等)

    从好的方面来说,这应该可以解决我们遇到的终端服务会话终止硬件加速的问题。

    我将向 MS 提交请求,考虑在未来版本中为“代理用户会话”支持提供这种“渲染农场”用例,这样服务器就可以生成硬件加速进程,而不会因需要现有要在控制台登录的客户端用户进程。

    【讨论】:

    • 我面临着完全相同的问题。您能告诉我在此期间是否可以得到更好的解决方案吗?谢谢!
    • 我从来没有解决过这个问题,但如果我要再次解决它,我可能会尝试重构应用程序以使用 FBO/RBO 渲染(这不需要初始 Windows hDC。)@ 987654321@有一些背景信息。
    • 不确定您是否还在,但是当 wglCreateContext 需要 DC 时如何创建 OpenGL 上下文?
    • @Robinson - 我在一些关于 WGL_ARB_create_context 上限的 OpenGL 4.x 公告中听说这是可能的,但是经过搜索,似乎只有 Linux(X-Windows)和 OS X“支持”目前创建无窗口上下文 - 甚至这似乎有点棘手 (renderingpipeline.com/2012/05/windowless-opengl)。我也看到很多关于“OpenCL as a service”的投诉。这也解释了为什么这个 wiki 页面添加了“......这实际上可能不起作用”:opengl.org/wiki/…
    • 这里有一个关于这个主题的更直接的 SO 问题:stackoverflow.com/questions/7062804/…
    【解决方案2】:

    我还没有完成培训课程,但是我在 Microsoft-MSDN 站点上找到了“Session 0 隔离解决方法”教程:

    http://msdn.microsoft.com/en-us/windows7trainingcourse_sessionisolation_unit.aspx

    我在计划任务中出现了同样的 session-0-isolation 问题。

    【讨论】:

      【解决方案3】:

      farmComm 将在会话 0 中启动您选择的应用程序,不显示 GUI,但可以访问图形硬件,无论用户是否登录。它还响应任何活动会话中的用户活动(包括会话 0 或“安全桌面”,当那是活动会话时)。它旨在在用户空闲时启动应用程序,并在用户从空闲状态恢复时终止它们,但这些运行条件可以在源 AutoHotkey 脚本中轻松更改。

      https://github.com/r-alex-hall/farmComm

      它“不可见”地在会话 0 中生成应用程序,但可以很容易地修改它(将值为“隐藏”的变量更改为“显示”)以使生成的进程的 GUI 可见(如果它们有 GUI) .但是,如果它们是可见的,它们可能会触发 Windows 唠叨以查看会话 0 中的“消息”,和/或仅在会话 0 中可见(这似乎包括“安全桌面”可见的任何时间——对于例如,当工作站被锁定、与用户会话断开连接或没有用户登录时)。

      在撰写本文时,如果任何远程桌面 (RDP) 会话在farmComm 生成的进程运行时启动,farcomComm 将终止这些进程并尝试重新启动它们以响应 RDP 会话,如果它们是应用程序尝试访问图形硬件,可能会导致它们崩溃(因为 RDP 限制了对图形硬件的访问)。可能这个 RDP 问题也可以解决。 . .或者您可以调整源以永不终止进程,或永不迁移到其他会话。 (注意:一个可能的计划更改是让您能够编写脚本来编写farmComm 是否以及何时终止、不终止、挂起或恢复进程——或者就此而言,编写脚本以在用户从空闲状态恢复时运行完全不同的进程。

      脚本可以编译成可执行文件,在我的发行版中就是这样。

      此工具集的关键是特定版本的 paexec(它将应用程序启动到会话 0),以及 AutoHotkey 对用户活动(或缺少)的非常可靠的响应,以及关于会话的系统信息的检索。启动进程“隐藏”(没有可见的 GUI)的选项也是通过 AutoHotkey。

      披露:我编写(或编码)farmComm 脚本,并将其发布到公共领域。

      【讨论】:

      • 有趣,你能简单解释一下这是如何实现的吗?看来这是一个非常独特的能力。
      • README.md 的技术细节部分 (==HOW IT WORKS==) 给出了我最好的解释,或者懒得给出:p 但我不确定文档是否这么说:它使用特定版本的 PaExec 在 SYSTEM 帐户下启动任何视频卡访问进程,我认为是在 Session0 中。
      猜你喜欢
      • 1970-01-01
      • 2023-04-08
      • 2011-07-29
      • 1970-01-01
      • 2014-11-01
      • 2013-04-28
      • 1970-01-01
      • 2017-08-30
      • 2011-11-09
      相关资源
      最近更新 更多