diff options
author | Munkyu Im <munkyu.im@samsung.com> | 2016-10-13 22:18:30 +0900 |
---|---|---|
committer | Munkyu Im <munkyu.im@samsung.com> | 2016-10-14 12:07:01 +0900 |
commit | 98046ab6c35ce83999c9a18811a4e40f307bc0f1 (patch) | |
tree | bd1dc2e28dffd71f70eba73d129cfe15c8641b06 | |
parent | 1e884dfd8d10ad3c5cbd415467c1723b1e37c0f8 (diff) | |
download | qemu-98046ab6c35ce83999c9a18811a4e40f307bc0f1.tar.gz qemu-98046ab6c35ce83999c9a18811a4e40f307bc0f1.tar.bz2 qemu-98046ab6c35ce83999c9a18811a4e40f307bc0f1.zip |
emulator: respawning when elevated
In order to prevent potential elevation of privilege attack, lower
privilege processes can't interfere with higher privilege on Windows.
Emulator is usually launched by emulator manager that has high integrity
level, then drag-and-drop from Explorer (mostly medium integrity level)
does not work.
So, when emulator process has elevated integrity level, we try to
respawn emulator with medium integrity level.
Change-Id: I17f29e411252758098304ba25b60219d07aa0d7c
Signed-off-by: Munkyu Im <munkyu.im@samsung.com>
Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
-rw-r--r-- | tizen/src/emulator.c | 14 | ||||
-rw-r--r-- | tizen/src/util/osutil-win32.c | 168 | ||||
-rw-r--r-- | tizen/src/util/osutil.h | 1 | ||||
-rw-r--r-- | version.rc | 4 |
4 files changed, 159 insertions, 28 deletions
diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index 940e0d1409..94b0fcc2e9 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -47,7 +47,10 @@ #include "ecs/ecs.h" #include "util/device_hotplug.h" #include "util/exported_strings.h" - +#ifdef CONFIG_WIN32 +#include <windows.h> +#include <sddl.h> +#endif #ifdef CONFIG_QT #include <qt5_supplement.h> #endif @@ -346,6 +349,15 @@ int main(int argc, char *argv[], char **envp) init_error_handler(); return emulator_main(argc, argv, envp); } +#elif defined (CONFIG_WIN32) +int main(int argc, char *argv[]) +{ + if (!check_integrity_level_and_respawn()) { + init_error_handler(); + return emulator_main(argc, argv, NULL); + } + return 0; +} #else int main(int argc, char *argv[]) { diff --git a/tizen/src/util/osutil-win32.c b/tizen/src/util/osutil-win32.c index bced9f8e7a..f733aedc67 100644 --- a/tizen/src/util/osutil-win32.c +++ b/tizen/src/util/osutil-win32.c @@ -96,12 +96,12 @@ void make_vm_lock_os(gchar *vms_path) GetLastError()); } lock_file = CreateFile(lock_filename, - GENERIC_READ | GENERIC_WRITE, - 0, // No share - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, - NULL); + GENERIC_READ | GENERIC_WRITE, + 0, // No share + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, + NULL); if (lock_file == INVALID_HANDLE_VALUE) { DWORD error = GetLastError(); // On Windows, the file opened by CreateFile has exclusive lock @@ -202,12 +202,12 @@ bool make_sdcard_lock_os(char *sdcard) fname = g_strdup_printf("%s.lck", sdcard); h = CreateFile(fname, - GENERIC_READ, - 0, // No share - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, - NULL); + GENERIC_READ, + 0, // No share + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, + NULL); if (h == INVALID_HANDLE_VALUE) { LOG_WARNING("Failed to CreateFile a sdcard lock file: %d\n", @@ -278,11 +278,11 @@ void get_java_path_win32(const char **java_path) /* Opens above key to query the current version */ res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - strKey, - 0, - KEY_QUERY_VALUE | - MY_KEY_WOW64_64KEY, - &hKey); + strKey, + 0, + KEY_QUERY_VALUE | + MY_KEY_WOW64_64KEY, + &hKey); if (res != ERROR_SUCCESS) { LOG_WARNING("Java Runtime Environment key not found\n"); goto javahome_not_found; @@ -290,11 +290,11 @@ void get_java_path_win32(const char **java_path) /* Queries for the current version */ res = RegQueryValueEx(hKey, - "CurrentVersion", - NULL, - NULL, - (LPBYTE)strVersion, - &dwBufLen); + "CurrentVersion", + NULL, + NULL, + (LPBYTE)strVersion, + &dwBufLen); RegCloseKey(hKey); if (res != ERROR_SUCCESS) { LOG_WARNING("JRE CurrentVersion not found\n"); @@ -307,11 +307,11 @@ void get_java_path_win32(const char **java_path) /* Opens above key to query the JavaHome */ res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, - strKey, - 0, - KEY_QUERY_VALUE | - MY_KEY_WOW64_64KEY, - &hKey); + strKey, + 0, + KEY_QUERY_VALUE | + MY_KEY_WOW64_64KEY, + &hKey); if (res == ERROR_SUCCESS) { /* Queries for the JavaHome */ dwBufLen = PATH_MAX; @@ -337,3 +337,117 @@ javahome_not_found: *java_path = current_java_path; } + +bool check_integrity_level_and_respawn(void) +{ + BOOL bResult = false; + HANDLE hToken = NULL; + HANDLE hNewToken = NULL; + PSID pIntegritySid = NULL; + TOKEN_MANDATORY_LABEL TIL = { { 0, }, }; + PTOKEN_MANDATORY_LABEL pTIL = NULL; + PROCESS_INFORMATION ProcInfo = { 0, }; + STARTUPINFO StartupInfo = { 0, }; + SID_IDENTIFIER_AUTHORITY + MLAuthority = { SECURITY_MANDATORY_LABEL_AUTHORITY }; + DWORD dwIntegrityLevel, dwSize = 0; + + if(!OpenProcessToken(GetCurrentProcess(), + TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT | TOKEN_QUERY | + TOKEN_ASSIGN_PRIMARY, &hToken)) { + LOG_WARNING("OpenProcessToken Error %lu\n", GetLastError()); + goto CleanExit; + } + + if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize)) { + DWORD dwResult = GetLastError(); + if (dwResult != ERROR_INSUFFICIENT_BUFFER) { + LOG_WARNING("GetTokenInformation Error %lu\n", dwResult); + goto CleanExit; + } + } + + pTIL = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, dwSize); + if (!pTIL) { + LOG_WARNING("LocalAlloc Error %lu\n", GetLastError()); + goto CleanExit; + } + + if (!GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, + dwSize, &dwSize)) { + LOG_WARNING("GetTokenInformation Error %lu\n", GetLastError()); + goto CleanExit; + } + + dwIntegrityLevel = *GetSidSubAuthority(pTIL->Label.Sid, + (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid) - 1)); + + if (dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID && + dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID) { + // We have medium integrity level. So keep going on. + goto CleanExit; + } + + LOG_INFO("Running with elevated integrity level. Try to respawn.\n"); + + if (!DuplicateTokenEx(hToken, 0, NULL, SecurityImpersonation, + TokenPrimary, &hNewToken)) { + LOG_WARNING("DuplicateTokenEx Error %lu\n", GetLastError()); + goto CleanExit; + } + + if (!AllocateAndInitializeSid(&MLAuthority, 1, SECURITY_MANDATORY_MEDIUM_RID, + 0, 0, 0, 0, 0, 0, 0, &pIntegritySid)) { + LOG_WARNING("AllocateAndInitializeSid Error %lu\n", GetLastError()); + goto CleanExit; + } + + TIL.Label.Attributes = SE_GROUP_INTEGRITY; + TIL.Label.Sid = pIntegritySid; + + if (!SetTokenInformation(hNewToken, + TokenIntegrityLevel, + &TIL, + sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(pIntegritySid))) { + LOG_WARNING("SetTokenInformation Error %lu\n", GetLastError()); + goto CleanExit; + } + + if (!CreateProcessAsUser(hNewToken, 0, GetCommandLine(), + NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcInfo)) { + LOG_WARNING( "CreateProcessAsUser Error %lu\n", GetLastError()); + goto CleanExit; + } + + LOG_INFO("Respawning success. Waiting for child process.\n"); + bResult = true; + WaitForSingleObject(ProcInfo.hProcess, INFINITE); + +CleanExit: + if (ProcInfo.hProcess != NULL) { + CloseHandle(ProcInfo.hProcess); + } + + if (ProcInfo.hThread != NULL) { + CloseHandle(ProcInfo.hThread); + } + + if (pIntegritySid != NULL) { + LocalFree(pIntegritySid); + } + + if (hNewToken != NULL) { + CloseHandle(hNewToken); + } + + if (hToken != NULL) { + CloseHandle(hToken); + } + + if (pTIL != NULL) { + LocalFree(pTIL); + } + + return bResult; +} + diff --git a/tizen/src/util/osutil.h b/tizen/src/util/osutil.h index 7dc9fea2f4..d478155f28 100644 --- a/tizen/src/util/osutil.h +++ b/tizen/src/util/osutil.h @@ -57,6 +57,7 @@ bool make_sdcard_lock_posix(char *sdcard); int remove_sdcard_lock_posix(char *sdcard); #else void get_java_path_win32(const char **java_path); +bool check_integrity_level_and_respawn(void); #endif void set_bin_path_os(char const *const); diff --git a/version.rc b/version.rc index c7922d5200..86455bb873 100644 --- a/version.rc +++ b/version.rc @@ -14,7 +14,11 @@ FILESUBTYPE VFT2_UNKNOWN BLOCK "040904E4" { VALUE "CompanyName", "http://www.qemu-project.org" +#ifdef CONFIG_MARU + VALUE "FileDescription", "Tizen Emulator" +#else VALUE "FileDescription", "QEMU machine emulators and tools" +#endif VALUE "FileVersion", QEMU_VERSION VALUE "LegalCopyright", "Copyright various authors. Released under the GNU General Public License." VALUE "LegalTrademarks", "QEMU is a trademark of Fabrice Bellard." |