From e0bdf94f32f1efb60720d10c9b49308bab406f01 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 17 Aug 2007 19:58:57 +0000 Subject: [PATCH] * autoload.cc (CloseDesktop): Define. (CreateDesktopA): Define. (SetThreadDesktop): Define. * spawn.cc (spawn_guts): When starting a process under another user account, don't open up permissions on current window station and desktop. Instead, if not in interactive session, create a new per-user window station plus default desktop and use that for the child process. --- winsup/cygwin/ChangeLog | 10 ++++++ winsup/cygwin/autoload.cc | 3 ++ winsup/cygwin/spawn.cc | 68 +++++++++++++++++++++++++++++---------- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index a6198ced9..a3585494b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,13 @@ +2007-08-17 Corinna Vinschen + + * autoload.cc (CloseDesktop): Define. + (CreateDesktopA): Define. + (SetThreadDesktop): Define. + * spawn.cc (spawn_guts): When starting a process under another user + account, don't open up permissions on current window station and + desktop. Instead, if not in interactive session, create a new per-user + window station plus default desktop and use that for the child process. + 2007-08-16 Corinna Vinschen * fhandler_disk_file.cc (fhandler_disk_file::fchmod): Handle S_IFSOCK diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 09e645a72..c89333401 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -322,7 +322,9 @@ LoadDLLfuncEx (LsaRegisterLogonProcess, 12, secur32, 1) LoadDLLfunc (CharToOemA, 8, user32) LoadDLLfunc (CloseClipboard, 0, user32) +LoadDLLfunc (CloseDesktop, 4, user32) LoadDLLfunc (CloseWindowStation, 4, user32) +LoadDLLfunc (CreateDesktopA, 24, user32) LoadDLLfunc (CreateWindowExA, 48, user32) LoadDLLfunc (CreateWindowStationA, 16, user32) LoadDLLfunc (DefWindowProcA, 16, user32) @@ -349,6 +351,7 @@ LoadDLLfunc (RegisterClassA, 4, user32) LoadDLLfunc (RegisterClipboardFormatA, 4, user32) LoadDLLfunc (SendMessageA, 16, user32) LoadDLLfunc (SetClipboardData, 8, user32) +LoadDLLfunc (SetThreadDesktop, 4, user32) LoadDLLfunc (SetProcessWindowStation, 4, user32) LoadDLLfunc (accept, 12, ws2_32) diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 6a658e92e..48895312f 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -512,25 +512,49 @@ loop: if (mode == _P_OVERLAY) myself.set_acl(); - /* allow the child to interact with our window station/desktop */ - HANDLE hwst, hdsk; - SECURITY_INFORMATION dsi = DACL_SECURITY_INFORMATION; - NTSTATUS status; + char wstname[1024] = { '\0' }; + HWINSTA hwst_orig = NULL, hwst = NULL; + HDESK hdsk_orig = NULL, hdsk = NULL; + PSECURITY_ATTRIBUTES sa; DWORD n; - char wstname[1024]; - char dskname[1024]; - hwst = GetProcessWindowStation (); - if ((status = NtSetSecurityObject (hwst, dsi, get_null_sd ()))) - system_printf ("NtSetSecurityObject, %lx", status); - GetUserObjectInformation (hwst, UOI_NAME, wstname, 1024, &n); - hdsk = GetThreadDesktop (GetCurrentThreadId ()); - if ((status = NtSetSecurityObject (hdsk, dsi, get_null_sd ()))) - system_printf ("NtSetSecurityObject, %lx", status); - GetUserObjectInformation (hdsk, UOI_NAME, dskname, 1024, &n); - strcat (wstname, "\\"); - strcat (wstname, dskname); - si.lpDesktop = wstname; + hwst_orig = GetProcessWindowStation (); + hdsk_orig = GetThreadDesktop (GetCurrentThreadId ()); + GetUserObjectInformation (hwst_orig, UOI_NAME, wstname, 1024, &n); + /* Prior to Vista it was possible to start a service with the + "Interact with desktop" flag. This started the service in the + interactive window station of the console. A big security + risk, but we don't want to disable this behaviour for older + OSes because it's still heavily used by some users. They have + been warned. */ + if (!strcasematch (wstname, "WinSta0")) + { + char sid[128]; + + sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024), + cygheap->user.sid ()); + /* We're create a window station per user, not per logon session. + First of all we might not have a valid logon session for + the user (logon by create_token), and second, it doesn't + make sense in terms of security to create a new window + station for every logon of the same user. It just fills up + the system with window stations for no good reason. */ + hwst = CreateWindowStationA (cygheap->user.get_windows_id (sid), 0, + GENERIC_READ | GENERIC_WRITE, sa); + if (!hwst) + system_printf ("CreateWindowStation failed, %E"); + else if (!SetProcessWindowStation (hwst)) + system_printf ("SetProcessWindowStation failed, %E"); + else if (!(hdsk = CreateDesktopA ("Default", NULL, NULL, 0, + GENERIC_ALL, sa))) + system_printf ("CreateDesktop failed, %E"); + else + { + stpcpy (stpcpy (wstname, sid), "\\Default"); + si.lpDesktop = wstname; + debug_printf ("Desktop: %s", si.lpDesktop); + } + } rc = CreateProcessAsUser (cygheap->user.primary_token (), runpath, /* image name - with full path */ @@ -543,6 +567,16 @@ loop: NULL, &si, &pi); + if (hwst) + { + SetProcessWindowStation (hwst_orig); + CloseWindowStation (hwst); + } + if (hdsk) + { + SetThreadDesktop (hdsk_orig); + CloseDesktop (hdsk); + } } /* Restore impersonation. In case of _P_OVERLAY this isn't