Windows 2008 Услуги RenderFarm: CreateProcessAsUser “сессия 0 изоляции” и OpenGL

У меня есть сервис Windows Server прежней версии и (порожденное) приложение, которое хорошо работает в XP-64 и W2K3, но перестало работать на W2K8. Я полагаю, что это из-за новой функции "Session 0 isolation".

Следовательно, я ищу заклинание образцов/настроек безопасности кода, которые позволяют Вам создать новый процесс из сервиса окон для Windows 2008 Server, таким образом, что я могу восстановить (и возможно превзойти), предыдущее поведение. Мне нужно решение что:

  1. Создает новый процесс на ненулевой сессии для обхождения сессии 0 ограничений изоляции (никакой доступ к аппаратному обеспечению машинной графики от сессии 0) - официальная строка MS на этом:

Поскольку Сессия 0 больше не является сеансом пользователя, сервисы, которые работают на Сессии 0, не имеют доступа к видеодрайверу. Это означает, что любая попытка, которую сервис предпринимает для рендеринга графических сбоев. Запросы разрешения дисплея и глубины цвета на Сессии 0 отчетов корректные результаты для системы до максимума 1920x1200 на уровне 32 бит на пиксель.

  1. Новый процесс получает окна, station/desktop (например, winsta0/default), который может использоваться для создания окон DCs. Я нашел решение (который запускается хорошо на интерактивной сессии) для этого здесь: Запуск Интерактивного Клиентского процесса в C++

  2. Окна DC при использовании в качестве основания для перечисления OpenGL DescribePixelFormat могут найти и использовать аппаратно ускоренный формат (в системе, соответственно оборудованной аппаратными средствами OpenGL.) Отмечают, что наше текущее решение работает хорошо над XP-64 и W2K3, кроме того, если сессия служб удаленных рабочих столов работает (VNC хорошо работает.) Решением, которое также позволило процессу работать (т.е. работать с аппаратным ускорением OpenGL, даже когда заседание служб удаленных рабочих столов открыто) был бы fanastic, хотя не требуемый.

Я застреваю в объекте № 1 в настоящее время, и хотя существуют некоторые подобные регистрации, которые обсуждают это (как это и это - они не подходящие решения, поскольку нет никакой гарантии сеанса пользователя, зарегистрированного уже для "взятия" идентификатора сессии от, и при этом я не работаю из учетной записи LocalSystem (я работаю от учетной записи домена за сервисом, для которого я могу скорректировать полномочия в причине, хотя я предпочел бы не должным быть наращивать приоритеты включать SeTcbPrivileges.)

Например - здесь незавершен, что я думаю, должен работать, но всегда возвращает ошибку 1314 на вызове SetTokenInformation (даже при том, что AdjustTokenPrivileges не возвратил ошибок), я использовал некоторые альтернативные стратегии, включающие "LogonUser" также (вместо того, чтобы открыть существующий маркер процесса), но я, может казаться, не выгружаю идентификатор сессии.

Я также сомнителен об использовании 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). (Обратите внимание, что я зарегистрирован в поле W2K8 через VNC, не RDC),

Таким образом - вопросы:

  1. Действительно ли этот подход допустим, или все инициируются сервисом процессы, ограниченные сессией 0 намеренно?
  2. Существует ли лучший подход (за исключением "Запуска на входе в систему" и автовходе в систему для серверов?)
  3. Есть ли что-то не так с этим кодом или другим способом создать маркер процесса, где я могу выгрузить идентификатор сессии, чтобы указать, что я хочу породить процесс на новой сессии? Я действительно пытался использовать LogonUser вместо OpenProcessToken, но это не работало также. (Я не забочусь, совместно используют ли все порожденные процессы ту же ненулевую сессию или не в этой точке.)

Любая справка, очень ценившая - Спасибо!

8
задан Community 23 May 2017 в 10:29
поделиться

1 ответ

Для всех, кто интересуется решением этой проблемы:

Я обсуждал эту проблему со службой поддержки MS для команды LogonSDK. Похоже, что невозможно полностью олицетворять интерактивного пользователя программно, например, получить физическую консоль и связанные с ней конструкции GDI, и нам, по сути, «просто повезло», что это работало до сих пор. Они подтвердили, что изоляция сеанса 0 была основной причиной регресса.

Их рекомендация состоит в том, чтобы включить автоматический вход в интерактивный сеанс и провести рефакторинг службы для взаимодействия с новым клиентским компонентом в интерактивном сеансе. Чтобы устранить недостаток безопасности, связанный с этим, они рекомендуют реализовать замену оболочки, чтобы перевести сервер в режим «киоска» при входе в систему (например, запретить доступ к обозревателю без соответствующих учетных данных и т. Д.)

С другой стороны, это должно решить проблемы, с которыми мы столкнулись в сеансах обслуживания терминалов, убивают наше аппаратное ускорение.

Я отправлю запрос в MS, чтобы рассмотреть этот вариант использования «фермы рендеринга» для поддержки «сеанса прокси-пользователя» в будущих выпусках, чтобы сервер мог запускать процессы с аппаратным ускорением без нарушения безопасности, требующего наличия существующего клиентский пользовательский процесс, который должен войти в систему с консоли.

9
ответ дан 5 December 2019 в 18:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: