diff options
author | Robert Collins <rbtcollins@hotmail.com> | 2001-10-01 06:49:20 +0400 |
---|---|---|
committer | Robert Collins <rbtcollins@hotmail.com> | 2001-10-01 06:49:20 +0400 |
commit | 9a04d19e00a635d966f3413b1db92d62490b8643 (patch) | |
tree | fcc89a81f125bd3604f93c1877e277643de71106 /winsup/cygwin | |
parent | e6b9398b2aed96a6d121762fd6e17fbcb1d5f25f (diff) |
Mon Oct 1 12:38:00 2001 Robert Collins <rbtcollins@hotmail.com>
* cygserver.cc (client_request::serve): New function.
* cygserver_process.cc: Inlude <pthread.h> for pthread_once.
(process_cache::process_cache): Initialise a crtiical section for write access.
(process_cache::process): Use the critical section. Also add missing entries to
the cache.
(do_process_init): New function to initalise class process static variables.
(process::process): Ensure that the process access critical section is initialised.
(process::handle): Close the handle of old process's when they have terminated
and we are returning the handle for a process with the same pid.
* cygserver_shm.cc: Run indent.
Include cygserver_process.h to allow process cache functionality.
(client_request_shm_get::serve): New parameter for process cache support.
Use the process cache, not OpenProcess to get a handle to the originating process.
Fix a handle leak with token_handle.
* cygserver_shm.h (class client_request_shm_get): Update ::serve for process cache support.
* cygserver_transport_pipes.cc: Redefine debug_printf to be conditional on DEBUG.
* include/cygwin/cygserver.h: Do not implement client_request::serve in the header.
* include/cygwin/cygserver_process.h (class process_cache): Add a write access cri
tical section to prevent races when requests from a multithreaded application arrive.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r-- | winsup/cygwin/ChangeLog | 21 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver.cc | 9 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver_process.cc | 30 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver_shm.cc | 245 | ||||
-rw-r--r-- | winsup/cygwin/cygserver_shm.h | 2 | ||||
-rwxr-xr-x | winsup/cygwin/cygserver_transport_pipes.cc | 3 | ||||
-rwxr-xr-x | winsup/cygwin/include/cygwin/cygserver.h | 2 | ||||
-rwxr-xr-x | winsup/cygwin/include/cygwin/cygserver_process.h | 1 |
8 files changed, 202 insertions, 111 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 9974fc3a1..b9670a7f0 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,24 @@ +Mon Oct 1 12:38:00 2001 Robert Collins <rbtcollins@hotmail.com> + + * cygserver.cc (client_request::serve): New function. + * cygserver_process.cc: Inlude <pthread.h> for pthread_once. + (process_cache::process_cache): Initialise a crtiical section for write access. + (process_cache::process): Use the critical section. Also add missing entries to + the cache. + (do_process_init): New function to initalise class process static variables. + (process::process): Ensure that the process access critical section is initialised. + (process::handle): Close the handle of old process's when they have terminated + and we are returning the handle for a process with the same pid. + * cygserver_shm.cc: Run indent. + Include cygserver_process.h to allow process cache functionality. + (client_request_shm_get::serve): New parameter for process cache support. + Use the process cache, not OpenProcess to get a handle to the originating process. + Fix a handle leak with token_handle. + * cygserver_shm.h (class client_request_shm_get): Update ::serve for process cache support. + * cygserver_transport_pipes.cc: Redefine debug_printf to be conditional on DEBUG. + * include/cygwin/cygserver.h: Do not implement client_request::serve in the header. + * include/cygwin/cygserver_process.h (class process_cache): Add a write access critical section to prevent races when requests from a multithreaded application arrive. + Sun Sep 30 23:41:00 2001 Robert Collins <rbtcollins@hotmail.com> * Makefile.in: Add cygserver_process.o to cygserver.exe. diff --git a/winsup/cygwin/cygserver.cc b/winsup/cygwin/cygserver.cc index 083df06af..a9b743c58 100755 --- a/winsup/cygwin/cygserver.cc +++ b/winsup/cygwin/cygserver.cc @@ -163,6 +163,15 @@ check_and_dup_handle (HANDLE from_process, HANDLE to_process, } void +client_request::serve (transport_layer_base *conn, class process_cache *cache) +{ + printf ("*****************************************\n" + "A call to the base client_request class has occured\n" + "This indicates a mismatch in a virtual function definition somewhere\n"); + exit (1); +} + +void client_request_attach_tty::serve(transport_layer_base *conn, class process_cache *cache) { HANDLE from_process_handle = NULL; diff --git a/winsup/cygwin/cygserver_process.cc b/winsup/cygwin/cygserver_process.cc index 8ec1c03e3..d02905b03 100755 --- a/winsup/cygwin/cygserver_process.cc +++ b/winsup/cygwin/cygserver_process.cc @@ -18,24 +18,37 @@ #include <sys/socket.h> #include <netdb.h> #include "wincap.h" +#include <pthread.h> #include <cygwin/cygserver_process.h> #define debug_printf if (DEBUG) printf #define DEBUG 1 +/* the cache structures and classes are designed for one cache per server process. + * To make multiple process caches, a redesign will be needed + */ + /* process cache */ process_cache::process_cache () : head (NULL) { + /* there can only be one */ + InitializeCriticalSection (&cache_write_access); } class process * process_cache::process (long pid) { class process_entry *entry = head; + /* TODO: make this more granular, so a search doesn't involve the write lock */ + EnterCriticalSection (&cache_write_access); while (entry && entry->process.winpid != pid) entry = entry->next; if (!entry) - return NULL; + { + entry = new process_entry (pid); + entry->next = (process_entry *) InterlockedExchangePointer (&head, entry); + } + LeaveCriticalSection (&cache_write_access); return &entry->process; } @@ -45,10 +58,23 @@ process_entry::process_entry (long pid) : next (NULL), process (pid) } /* process's */ +static CRITICAL_SECTION process_access; +static pthread_once_t process_init; + +void +do_process_init (void) +{ + InitializeCriticalSection (&process_access); + /* we don't have a cache shutdown capability today */ +} + process::process (long pid) : winpid (pid) { + pthread_once(&process_init, do_process_init); + EnterCriticalSection (&process_access); thehandle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid); debug_printf ("Got handle %p for new cache process %ld\n", thehandle, pid); + LeaveCriticalSection (&process_access); } HANDLE @@ -65,6 +91,8 @@ process::handle () if (exitstate != STILL_ACTIVE) { /* FIXME: call the cleanup list */ + CloseHandle (thehandle); + debug_printf ("Process id %ld has terminated, attempting to open a new handle\n", winpid); thehandle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, winpid); /* FIXME: what if this fails */ } diff --git a/winsup/cygwin/cygserver_shm.cc b/winsup/cygwin/cygserver_shm.cc index e4da727e6..3b8bd9dd2 100755 --- a/winsup/cygwin/cygserver_shm.cc +++ b/winsup/cygwin/cygserver_shm.cc @@ -45,6 +45,7 @@ #endif //#include "perprocess.h" #include "cygserver_shm.h" +#include <cygwin/cygserver_process.h> // FIXME IS THIS CORRECT /* Implementation notes: We use two shared memory regions per key: @@ -55,7 +56,8 @@ * Also, IPC_PRIVATE keys create unique mappings each time. The shm_ids just * keep monotonically incrementing - system wide. */ -size_t getsystemallocgranularity () +size_t +getsystemallocgranularity () { SYSTEM_INFO sysinfo; static size_t buffer_offset = 0; @@ -66,14 +68,15 @@ size_t getsystemallocgranularity () return buffer_offset; } -client_request_shm_get::client_request_shm_get () : client_request (CYGSERVER_REQUEST_SHM_GET) +client_request_shm_get::client_request_shm_get ():client_request (CYGSERVER_REQUEST_SHM_GET) { header.cb = sizeof (parameters); buffer = (char *) ¶meters; header.error_code = 0; } -client_request_shm_get::client_request_shm_get (int nshm_id, pid_t npid) : client_request (CYGSERVER_REQUEST_SHM_GET) +client_request_shm_get::client_request_shm_get (int nshm_id, pid_t npid): +client_request (CYGSERVER_REQUEST_SHM_GET) { header.cb = sizeof (parameters); buffer = (char *) ¶meters; @@ -84,7 +87,10 @@ client_request_shm_get::client_request_shm_get (int nshm_id, pid_t npid) : clien } client_request_shm_get::client_request_shm_get (key_t nkey, size_t nsize, - int nshmflg, char psdbuf[4096], pid_t npid): client_request (CYGSERVER_REQUEST_SHM_GET) + int nshmflg, + char psdbuf[4096], + pid_t npid): +client_request (CYGSERVER_REQUEST_SHM_GET) { header.cb = sizeof (parameters); buffer = (char *) ¶meters; @@ -115,10 +121,9 @@ shmat (int shmid, const void *shmaddr, int parameters.in.shmflg) void *rv = MapViewOfFile (shm->attachmap, - - (parameters.in. - shmflg & SHM_RDONLY) ? FILE_MAP_READ : - FILE_MAP_WRITE, 0, + + (parameters.in.shmflg & SHM_RDONLY) ? + FILE_MAP_READ : FILE_MAP_WRITE, 0, 0, 0); if (!rv) @@ -161,7 +166,8 @@ shmat (int shmid, const void *shmaddr, int parameters.in.shmflg) /* for dll size */ #ifdef __INSIDE_CYGWIN__ void -client_request_shm_get::serve (transport_layer_base * conn) +client_request_shm_get::serve (transport_layer_base * conn, + process_cache * cache) { } #else @@ -171,9 +177,9 @@ extern GENERIC_MAPPING access_mapping; extern int check_and_dup_handle (HANDLE from_process, HANDLE to_process, HANDLE from_process_token, - DWORD access, - HANDLE from_handle, - HANDLE* to_handle_ptr, BOOL bInheritHandle); + DWORD access, + HANDLE from_handle, + HANDLE * to_handle_ptr, BOOL bInheritHandle); //FIXME: where should this live static shmnode *shm_head = NULL; @@ -182,7 +188,8 @@ static long new_id = 0; static long new_private_key = 0; void -client_request_shm_get::serve (transport_layer_base * conn) +client_request_shm_get::serve (transport_layer_base * conn, + process_cache * cache) { // DWORD sd_size = 4096; // char sd_buf[4096]; @@ -195,26 +202,29 @@ client_request_shm_get::serve (transport_layer_base * conn) HANDLE token_handle = NULL; DWORD rc; - from_process_handle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, parameters.in.pid); + from_process_handle = cache->process (parameters.in.pid)->handle (); + /* possible TODO: reduce the access on the handle before we use it */ + /* Note that unless we do this, we don't need to call CloseHandle - it's kept open + * by the process cache until the process terminates. + * We may need a refcount on the cache however... + */ if (!from_process_handle) { - printf ("error opening process (%lu)\n", GetLastError ()); + debug_printf ("error opening process (%lu)\n", GetLastError ()); header.error_code = EACCES; return; } conn->impersonate_client (); - + rc = OpenThreadToken (GetCurrentThread (), - TOKEN_QUERY, - TRUE, - &token_handle); + TOKEN_QUERY, TRUE, &token_handle); conn->revert_to_self (); if (!rc) { - printf ("error opening thread token (%lu)\n", GetLastError ()); + debug_printf ("error opening thread token (%lu)\n", GetLastError ()); header.error_code = EACCES; CloseHandle (from_process_handle); return; @@ -229,7 +239,7 @@ client_request_shm_get::serve (transport_layer_base * conn) SECURITY_ATTRIBUTES sa; sa.nLength = sizeof (sa); sa.lpSecurityDescriptor = psd; - sa.bInheritHandle = TRUE; /* the memory structures inherit ok */ + sa.bInheritHandle = TRUE; /* the memory structures inherit ok */ char *shmname = NULL, *shmaname = NULL; char stringbuf[29], stringbuf1[29]; @@ -237,37 +247,39 @@ client_request_shm_get::serve (transport_layer_base * conn) if (parameters.in.type == SHM_REATTACH) { /* just find and fill out the existing shm_id */ - shmnode *tempnode = shm_head; - while (tempnode) - { - if (tempnode->shm_id == parameters.in.shm_id) - { - parameters.out.shm_id = tempnode->shm_id; - parameters.out.key = tempnode->key; - if (check_and_dup_handle (GetCurrentProcess (),from_process_handle, - token_handle, - DUPLICATE_SAME_ACCESS, - tempnode->filemap, ¶meters.out.filemap, TRUE) != 0) - { - printf ("error duplicating filemap handle (%lu)\n", GetLastError ()); - header.error_code = EACCES; - CloseHandle (from_process_handle); - } - if (check_and_dup_handle (GetCurrentProcess (),from_process_handle, - token_handle, - DUPLICATE_SAME_ACCESS, - tempnode->attachmap, ¶meters.out.attachmap, TRUE) != 0) - { - printf ("error duplicating attachmap handle (%lu)\n", GetLastError ()); - header.error_code = EACCES; - CloseHandle (from_process_handle); - } - return; - } - tempnode = tempnode->next; - } - header.error_code = EINVAL; - return; + shmnode *tempnode = shm_head; + while (tempnode) + { + if (tempnode->shm_id == parameters.in.shm_id) + { + parameters.out.shm_id = tempnode->shm_id; + parameters.out.key = tempnode->key; + if (check_and_dup_handle + (GetCurrentProcess (), from_process_handle, token_handle, + DUPLICATE_SAME_ACCESS, tempnode->filemap, + ¶meters.out.filemap, TRUE) != 0) + { + debug_printf ("error duplicating filemap handle (%lu)\n", + GetLastError ()); + header.error_code = EACCES; + } + if (check_and_dup_handle + (GetCurrentProcess (), from_process_handle, token_handle, + DUPLICATE_SAME_ACCESS, tempnode->attachmap, + ¶meters.out.attachmap, TRUE) != 0) + { + debug_printf ("error duplicating attachmap handle (%lu)\n", + GetLastError ()); + header.error_code = EACCES; + } + CloseHandle (token_handle); + return; + } + tempnode = tempnode->next; + } + header.error_code = EINVAL; + CloseHandle (token_handle); + return; } /* it's a original request from the users */ @@ -280,22 +292,22 @@ client_request_shm_get::serve (transport_layer_base * conn) /* create the mapping name (CYGWINSHMKPRIVATE_0x01234567 */ /* The K refers to Key, the actual mapped area has D */ long private_key = (int) InterlockedIncrement (&new_private_key); - snprintf (stringbuf , 29, "CYGWINSHMKPRIVATE_0x%0x", private_key); - shmname = stringbuf; - snprintf (stringbuf1, 29, "CYGWINSHMDPRIVATE_0x%0x", private_key); - shmaname = stringbuf1; + snprintf (stringbuf, 29, "CYGWINSHMKPRIVATE_0x%0x", private_key); + shmname = stringbuf; + snprintf (stringbuf1, 29, "CYGWINSHMDPRIVATE_0x%0x", private_key); + shmaname = stringbuf1; } else { - /* create the mapping name (CYGWINSHMK0x0123456789abcdef */ - /* The K refers to Key, the actual mapped area has D */ - - snprintf (stringbuf , 29, "CYGWINSHMK0x%0qx", parameters.in.key); - shmname = stringbuf; - snprintf (stringbuf1, 29, "CYGWINSHMD0x%0qx", parameters.in.key); - shmaname = stringbuf1; - debug_printf ("system id strings are \n%s\n%s\n",shmname,shmaname); - debug_printf ("key input value is 0x%0qx\n", parameters.in.key); + /* create the mapping name (CYGWINSHMK0x0123456789abcdef */ + /* The K refers to Key, the actual mapped area has D */ + + snprintf (stringbuf, 29, "CYGWINSHMK0x%0qx", parameters.in.key); + shmname = stringbuf; + snprintf (stringbuf1, 29, "CYGWINSHMD0x%0qx", parameters.in.key); + shmaname = stringbuf1; + debug_printf ("system id strings are \n%s\n%s\n", shmname, shmaname); + debug_printf ("key input value is 0x%0qx\n", parameters.in.key); } /* attempt to open the key */ @@ -322,6 +334,7 @@ client_request_shm_get::serve (transport_layer_base * conn) && tempnode->shmds->shm_segsz < parameters.in.size) { header.error_code = EINVAL; + CloseHandle (token_handle); return; } /* FIXME: can the same process call this twice without error ? test @@ -331,8 +344,11 @@ client_request_shm_get::serve (transport_layer_base * conn) && (parameters.in.shmflg & IPC_EXCL)) { header.error_code = EEXIST; - debug_printf ("attempt to exclusively create already created shm_area with key 0x%0qx\n",parameters.in.key); + debug_printf + ("attempt to exclusively create already created shm_area with key 0x%0qx\n", + parameters.in.key); // FIXME: free the mutex + CloseHandle (token_handle); return; } // FIXME: do we need to other tests of the requested mode with the @@ -345,29 +361,34 @@ client_request_shm_get::serve (transport_layer_base * conn) * let them attempt the open. */ parameters.out.shm_id = tempnode->shm_id; -if (check_and_dup_handle (GetCurrentProcess (),from_process_handle, - token_handle, - DUPLICATE_SAME_ACCESS, - tempnode->filemap, ¶meters.out.filemap,TRUE) != 0) - { - printf ("error duplicating filemap handle (%lu)\n", GetLastError ()); - header.error_code = EACCES; + if (check_and_dup_handle (GetCurrentProcess (), from_process_handle, + token_handle, + DUPLICATE_SAME_ACCESS, + tempnode->filemap, + ¶meters.out.filemap, TRUE) != 0) + { + printf ("error duplicating filemap handle (%lu)\n", + GetLastError ()); + header.error_code = EACCES; /*mutex*/ - CloseHandle (from_process_handle); - return; - } -if (check_and_dup_handle (GetCurrentProcess (),from_process_handle, - token_handle, - DUPLICATE_SAME_ACCESS, - tempnode->attachmap, ¶meters.out.attachmap, TRUE) != 0) - { - printf ("error duplicating attachmap handle (%lu)\n", GetLastError ()); - header.error_code = EACCES; + CloseHandle (token_handle); + return; + } + if (check_and_dup_handle (GetCurrentProcess (), from_process_handle, + token_handle, + DUPLICATE_SAME_ACCESS, + tempnode->attachmap, + ¶meters.out.attachmap, TRUE) != 0) + { + printf ("error duplicating attachmap handle (%lu)\n", + GetLastError ()); + header.error_code = EACCES; /*mutex*/ - CloseHandle (from_process_handle); -return; - } + CloseHandle (token_handle); + return; + } + CloseHandle (token_handle); return; } tempnode = tempnode->next; @@ -395,6 +416,7 @@ return; // free the mutex // we can assume that it exists, and that it was an access problem. header.error_code = EACCES; + CloseHandle (token_handle); return; } @@ -412,19 +434,21 @@ return; /* FIXME free mutex */ CloseHandle (filemap); header.error_code = EEXIST; + CloseHandle (token_handle); return; } } - /* we created a new mapping */ - if (parameters.in.key != IPC_PRIVATE && - (parameters.in.shmflg & IPC_CREAT) == 0) - { - CloseHandle (filemap); - /* FIXME free mutex */ - header.error_code = ENOENT; - return; - } + /* we created a new mapping */ + if (parameters.in.key != IPC_PRIVATE && + (parameters.in.shmflg & IPC_CREAT) == 0) + { + CloseHandle (filemap); + /* FIXME free mutex */ + header.error_code = ENOENT; + CloseHandle (token_handle); + return; + } conn->impersonate_client (); void *mapptr = MapViewOfFile (filemap, FILE_MAP_WRITE, 0, 0, 0); @@ -436,6 +460,7 @@ return; //FIXME: close filemap and free the mutex /* we couldn't access the mapped area with the requested permissions */ header.error_code = EACCES; + CloseHandle (token_handle); return; } @@ -459,6 +484,7 @@ return; UnmapViewOfFile (mapptr); CloseHandle (filemap); /* FIXME exit the mutex */ + CloseHandle (token_handle); return; } @@ -471,6 +497,7 @@ return; CloseHandle (filemap); CloseHandle (attachmap); /* FIXME exit mutex */ + CloseHandle (token_handle); return; } @@ -501,31 +528,35 @@ return; /* we now have the area in the daemon list, opened. - FIXME: leave the system wide shm mutex */ + FIXME: leave the system wide shm mutex */ parameters.out.shm_id = tempnode->shm_id; -if (check_and_dup_handle (GetCurrentProcess (),from_process_handle, - token_handle, - DUPLICATE_SAME_ACCESS, - tempnode->filemap, ¶meters.out.filemap, TRUE) != 0) + if (check_and_dup_handle (GetCurrentProcess (), from_process_handle, + token_handle, + DUPLICATE_SAME_ACCESS, + tempnode->filemap, ¶meters.out.filemap, + TRUE) != 0) { printf ("error duplicating filemap handle (%lu)\n", GetLastError ()); header.error_code = EACCES; - CloseHandle (from_process_handle); + CloseHandle (token_handle); /* mutex et al */ -return; + return; } -if (check_and_dup_handle (GetCurrentProcess (),from_process_handle, - token_handle, - DUPLICATE_SAME_ACCESS, - tempnode->attachmap, ¶meters.out.attachmap, TRUE) != 0) + if (check_and_dup_handle (GetCurrentProcess (), from_process_handle, + token_handle, + DUPLICATE_SAME_ACCESS, + tempnode->attachmap, ¶meters.out.attachmap, + TRUE) != 0) { printf ("error duplicating attachmap handle (%lu)\n", GetLastError ()); header.error_code = EACCES; CloseHandle (from_process_handle); + CloseHandle (token_handle); /* more cleanup... yay! */ -return; + return; } + CloseHandle (token_handle); return; } #endif diff --git a/winsup/cygwin/cygserver_shm.h b/winsup/cygwin/cygserver_shm.h index e4ac62e4c..25f747fb0 100644 --- a/winsup/cygwin/cygserver_shm.h +++ b/winsup/cygwin/cygserver_shm.h @@ -20,7 +20,7 @@ details. */ class client_request_shm_get : public client_request { public: - virtual void serve (transport_layer_base *conn); + virtual void serve (transport_layer_base *conn, process_cache *cache); client_request_shm_get::client_request_shm_get(key_t, size_t, int, char psdbuf[4096], pid_t); client_request_shm_get::client_request_shm_get(); client_request_shm_get::client_request_shm_get(int,pid_t); diff --git a/winsup/cygwin/cygserver_transport_pipes.cc b/winsup/cygwin/cygserver_transport_pipes.cc index 487ea5281..d9accce1e 100755 --- a/winsup/cygwin/cygserver_transport_pipes.cc +++ b/winsup/cygwin/cygserver_transport_pipes.cc @@ -25,7 +25,8 @@ #ifndef __OUTSIDE_CYGWIN__ #include "winsup.h" #else -#define debug_printf printf +#define DEBUG 0 +#define debug_printf if (DEBUG) printf #endif transport_layer_pipes::transport_layer_pipes (HANDLE new_pipe) diff --git a/winsup/cygwin/include/cygwin/cygserver.h b/winsup/cygwin/include/cygwin/cygserver.h index 4bf30241b..ad7dd3ce3 100755 --- a/winsup/cygwin/include/cygwin/cygserver.h +++ b/winsup/cygwin/include/cygwin/cygserver.h @@ -87,7 +87,7 @@ class client_request public: client_request (cygserver_request_code id); virtual void send (transport_layer_base *conn); - virtual void serve (transport_layer_base *conn, class process_cache *cache) {}; + virtual void serve (transport_layer_base *conn, class process_cache *cache); virtual operator struct request_header (); cygserver_request_code req_id () {return header.req_id;}; virtual ~client_request(); diff --git a/winsup/cygwin/include/cygwin/cygserver_process.h b/winsup/cygwin/include/cygwin/cygserver_process.h index e761af3e2..35abf48bd 100755 --- a/winsup/cygwin/include/cygwin/cygserver_process.h +++ b/winsup/cygwin/include/cygwin/cygserver_process.h @@ -38,6 +38,7 @@ class process_cache class process *process (long); private: class process_entry *head; + CRITICAL_SECTION cache_write_access; }; #endif /* _CYGSERVER_PROCESS_ */ |