[SERVICES]

- (Re-)implement acquiring/releasing driver-loading and unloading privilege (Note: the two privileges have the same name SE_LOAD_DRIVER_NAME).
- Rework the SCM initialization code. In particular, acquiring the starting lock MUST BE done BEFORE starting the RPC server, otherwise, a program can try to start a service (and during this operation, the global start lock is acquired by the SCM) DURING the initialization of SCM, and in particular between the call to ScmStartRpcServer and ScmAcquireServiceStartLock. The SCM would then see an already-acquired start lock at this point and would fail to initialize. ==> This commit corrects this behaviour.

svn path=/trunk/; revision=57754
This commit is contained in:
Hermès Bélusca-Maïto 2012-11-24 00:53:01 +00:00
parent ba30f8c018
commit da5ab71ded
2 changed files with 86 additions and 46 deletions

View file

@ -16,6 +16,50 @@
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
static DWORD EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
{
DWORD dwRet = ERROR_SUCCESS;
HANDLE hToken = NULL;
if (OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
&hToken))
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
if (LookupPrivilegeValueW(NULL,
lpszPrivilegeName,
&tp.Privileges[0].Luid))
{
if (AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL))
{
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
dwRet = ERROR_NOT_ALL_ASSIGNED;
}
else
{
dwRet = GetLastError();
}
}
else
{
dwRet = GetLastError();
}
CloseHandle(hToken);
}
else
{
dwRet = GetLastError();
}
return dwRet;
}
DWORD DWORD
ScmLoadDriver(PSERVICE lpService) ScmLoadDriver(PSERVICE lpService)
{ {
@ -40,18 +84,28 @@ ScmLoadDriver(PSERVICE lpService)
RtlInitUnicodeString(&DriverPath, RtlInitUnicodeString(&DriverPath,
pszDriverPath); pszDriverPath);
/* FIXME: Acquire privilege */
DPRINT(" Path: %wZ\n", &DriverPath); DPRINT(" Path: %wZ\n", &DriverPath);
/* Acquire driver-loading privilege */
dwError = EnablePrivilege(SE_LOAD_DRIVER_NAME, TRUE);
if (dwError != ERROR_SUCCESS)
{
/* We encountered a failure, exit properly */
DPRINT1("SERVICES: Cannot acquire driver-loading privilege, error = %lu\n", dwError);
goto done;
}
Status = NtLoadDriver(&DriverPath); Status = NtLoadDriver(&DriverPath);
/* FIXME: Release privilege */ /* Release driver-loading privilege */
EnablePrivilege(SE_LOAD_DRIVER_NAME, FALSE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
dwError = RtlNtStatusToDosError(Status); dwError = RtlNtStatusToDosError(Status);
} }
done:
HeapFree(GetProcessHeap(), 0, pszDriverPath); HeapFree(GetProcessHeap(), 0, pszDriverPath);
return dwError; return dwError;
@ -82,17 +136,26 @@ ScmUnloadDriver(PSERVICE lpService)
RtlInitUnicodeString(&DriverPath, RtlInitUnicodeString(&DriverPath,
pszDriverPath); pszDriverPath);
/* FIXME: Acquire privilege */ /* Acquire driver-unloading privilege */
dwError = EnablePrivilege(SE_LOAD_DRIVER_NAME, TRUE);
if (dwError != ERROR_SUCCESS)
{
/* We encountered a failure, exit properly */
DPRINT1("SERVICES: Cannot acquire driver-unloading privilege, error = %lu\n", dwError);
goto done;
}
Status = NtUnloadDriver(&DriverPath); Status = NtUnloadDriver(&DriverPath);
/* FIXME: Release privilege */ /* Release driver-unloading privilege */
EnablePrivilege(SE_LOAD_DRIVER_NAME, FALSE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
dwError = RtlNtStatusToDosError(Status); dwError = RtlNtStatusToDosError(Status);
} }
done:
HeapFree(GetProcessHeap(), 0, pszDriverPath); HeapFree(GetProcessHeap(), 0, pszDriverPath);
return dwError; return dwError;

View file

@ -327,28 +327,6 @@ StartScmNamedPipeThreadListener(VOID)
} }
VOID FASTCALL
AcquireLoadDriverPrivilege(VOID)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
/* Get a token for this process */
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
/* Get the LUID for the debug privilege */
LookupPrivilegeValue(NULL, SE_LOAD_DRIVER_NAME, &tkp.Privileges[0].Luid);
/* One privilege to set */
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
/* Get the debug privilege for this process */
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
}
}
BOOL WINAPI BOOL WINAPI
ShutdownHandlerRoutine(DWORD dwCtrlType) ShutdownHandlerRoutine(DWORD dwCtrlType)
{ {
@ -378,7 +356,7 @@ wWinMain(HINSTANCE hInstance,
{ {
HANDLE hScmStartEvent = NULL; HANDLE hScmStartEvent = NULL;
SC_RPC_LOCK Lock = NULL; SC_RPC_LOCK Lock = NULL;
BOOL bDeleteCriticalSection = FALSE; BOOL bCanDeleteNamedPipeCriticalSection = FALSE;
DWORD dwError; DWORD dwError;
DPRINT("SERVICES: Service Control Manager\n"); DPRINT("SERVICES: Service Control Manager\n");
@ -400,6 +378,10 @@ wWinMain(HINSTANCE hInstance,
goto done; goto done;
} }
/* Initialize our communication named pipe's critical section */
ScmInitNamedPipeCriticalSection();
bCanDeleteNamedPipeCriticalSection = TRUE;
// ScmInitThreadManager(); // ScmInitThreadManager();
/* FIXME: more initialization */ /* FIXME: more initialization */
@ -422,12 +404,20 @@ wWinMain(HINSTANCE hInstance,
/* Update service database */ /* Update service database */
ScmGetBootAndSystemDriverState(); ScmGetBootAndSystemDriverState();
/* Start the RPC server */
ScmStartRpcServer();
/* Register service process with CSRSS */ /* Register service process with CSRSS */
RegisterServicesProcess(GetCurrentProcessId()); RegisterServicesProcess(GetCurrentProcessId());
/* Acquire the service start lock until autostart services have been started */
dwError = ScmAcquireServiceStartLock(TRUE, &Lock);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("SERVICES: failed to acquire the service start lock (Error %lu)\n", dwError);
goto done;
}
/* Start the RPC server */
ScmStartRpcServer();
DPRINT("SERVICES: Initialized.\n"); DPRINT("SERVICES: Initialized.\n");
/* Signal start event */ /* Signal start event */
@ -439,20 +429,6 @@ wWinMain(HINSTANCE hInstance,
/* Wait for the LSA server */ /* Wait for the LSA server */
ScmWaitForLsa(); ScmWaitForLsa();
/* Acquire privileges to load drivers */
AcquireLoadDriverPrivilege();
ScmInitNamedPipeCriticalSection();
bDeleteCriticalSection = TRUE;
/* Acquire the service start lock until autostart services have been started */
dwError = ScmAcquireServiceStartLock(TRUE, &Lock);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("SERVICES: failed to acquire the service start lock (Error %lu)\n", dwError);
goto done;
}
/* Start auto-start services */ /* Start auto-start services */
ScmAutoStartServices(); ScmAutoStartServices();
@ -467,7 +443,8 @@ wWinMain(HINSTANCE hInstance,
WaitForSingleObject(hScmShutdownEvent, INFINITE); WaitForSingleObject(hScmShutdownEvent, INFINITE);
done: done:
if (bDeleteCriticalSection == TRUE) /* Delete our communication named pipe's critical section */
if (bCanDeleteNamedPipeCriticalSection == TRUE)
ScmDeleteNamedPipeCriticalSection(); ScmDeleteNamedPipeCriticalSection();
/* Close the shutdown event */ /* Close the shutdown event */