[SERVICES]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 24 Nov 2012 00:53:01 +0000 (00:53 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 24 Nov 2012 00:53:01 +0000 (00:53 +0000)
- (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

reactos/base/system/services/driver.c
reactos/base/system/services/services.c

index 236657d..b8023dc 100644 (file)
 
 /* 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;
index ca7401e..982e0fb 100644 (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
 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 */