mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 21:36:11 +00:00
[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:
parent
ba30f8c018
commit
da5ab71ded
2 changed files with 86 additions and 46 deletions
|
@ -16,6 +16,50 @@
|
|||
|
||||
/* 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
|
||||
ScmLoadDriver(PSERVICE lpService)
|
||||
{
|
||||
|
@ -40,18 +84,28 @@ ScmLoadDriver(PSERVICE lpService)
|
|||
RtlInitUnicodeString(&DriverPath,
|
||||
pszDriverPath);
|
||||
|
||||
/* FIXME: Acquire privilege */
|
||||
|
||||
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);
|
||||
|
||||
/* FIXME: Release privilege */
|
||||
/* Release driver-loading privilege */
|
||||
EnablePrivilege(SE_LOAD_DRIVER_NAME, FALSE);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
dwError = RtlNtStatusToDosError(Status);
|
||||
}
|
||||
|
||||
done:
|
||||
HeapFree(GetProcessHeap(), 0, pszDriverPath);
|
||||
|
||||
return dwError;
|
||||
|
@ -82,17 +136,26 @@ ScmUnloadDriver(PSERVICE lpService)
|
|||
RtlInitUnicodeString(&DriverPath,
|
||||
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);
|
||||
|
||||
/* FIXME: Release privilege */
|
||||
/* Release driver-unloading privilege */
|
||||
EnablePrivilege(SE_LOAD_DRIVER_NAME, FALSE);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
dwError = RtlNtStatusToDosError(Status);
|
||||
}
|
||||
|
||||
done:
|
||||
HeapFree(GetProcessHeap(), 0, pszDriverPath);
|
||||
|
||||
return dwError;
|
||||
|
|
|
@ -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
|
||||
ShutdownHandlerRoutine(DWORD dwCtrlType)
|
||||
{
|
||||
|
@ -378,7 +356,7 @@ wWinMain(HINSTANCE hInstance,
|
|||
{
|
||||
HANDLE hScmStartEvent = NULL;
|
||||
SC_RPC_LOCK Lock = NULL;
|
||||
BOOL bDeleteCriticalSection = FALSE;
|
||||
BOOL bCanDeleteNamedPipeCriticalSection = FALSE;
|
||||
DWORD dwError;
|
||||
|
||||
DPRINT("SERVICES: Service Control Manager\n");
|
||||
|
@ -400,6 +378,10 @@ wWinMain(HINSTANCE hInstance,
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Initialize our communication named pipe's critical section */
|
||||
ScmInitNamedPipeCriticalSection();
|
||||
bCanDeleteNamedPipeCriticalSection = TRUE;
|
||||
|
||||
// ScmInitThreadManager();
|
||||
|
||||
/* FIXME: more initialization */
|
||||
|
@ -422,12 +404,20 @@ wWinMain(HINSTANCE hInstance,
|
|||
/* Update service database */
|
||||
ScmGetBootAndSystemDriverState();
|
||||
|
||||
/* Start the RPC server */
|
||||
ScmStartRpcServer();
|
||||
|
||||
/* Register service process with CSRSS */
|
||||
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");
|
||||
|
||||
/* Signal start event */
|
||||
|
@ -439,20 +429,6 @@ wWinMain(HINSTANCE hInstance,
|
|||
/* Wait for the LSA server */
|
||||
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 */
|
||||
ScmAutoStartServices();
|
||||
|
||||
|
@ -467,7 +443,8 @@ wWinMain(HINSTANCE hInstance,
|
|||
WaitForSingleObject(hScmShutdownEvent, INFINITE);
|
||||
|
||||
done:
|
||||
if (bDeleteCriticalSection == TRUE)
|
||||
/* Delete our communication named pipe's critical section */
|
||||
if (bCanDeleteNamedPipeCriticalSection == TRUE)
|
||||
ScmDeleteNamedPipeCriticalSection();
|
||||
|
||||
/* Close the shutdown event */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue