diff options
author | trawick <trawick@13f79535-47bb-0310-9956-ffa450edef68> | 2013-10-20 23:40:35 +0000 |
---|---|---|
committer | trawick <trawick@13f79535-47bb-0310-9956-ffa450edef68> | 2013-10-20 23:40:35 +0000 |
commit | a7321531ca179d82199245851e5c5fb86aaf13ec (patch) | |
tree | c802387315565766e1b75a91ae15134cc27abdd3 /shmem | |
parent | 5b4556a7990da02ab864aa309f18f97d33b4fdc3 (diff) | |
download | libapr-a7321531ca179d82199245851e5c5fb86aaf13ec.tar.gz |
Merge r1531768 and r1533979 from trunk:
r1531768:
Windows: Create named shared memory segments under the "Local"
namespace if the caller is unprivileged, fixing an inability of
unprivileged callers to use apr_shm_create() with named shared
memory segments under recent Windows.
r1533979:
Add apr_shm_create_ex() and apr_shm_attach_ex(), which
provide the ability to select the Global or Local
namespace on Windows.
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/branches/1.5.x@1534011 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'shmem')
-rw-r--r-- | shmem/beos/shm.c | 17 | ||||
-rw-r--r-- | shmem/os2/shm.c | 17 | ||||
-rw-r--r-- | shmem/unix/shm.c | 17 | ||||
-rw-r--r-- | shmem/win32/shm.c | 161 |
4 files changed, 193 insertions, 19 deletions
diff --git a/shmem/beos/shm.c b/shmem/beos/shm.c index 1f06f78ac..e61d806e9 100644 --- a/shmem/beos/shm.c +++ b/shmem/beos/shm.c @@ -71,6 +71,15 @@ APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *p, + apr_int32_t flags) +{ + return apr_shm_create(m, reqsize, filename, p); +} + APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m) { delete_area(m->aid); @@ -133,6 +142,14 @@ APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_shm_attach_ex(apr_shm_t **m, + const char *filename, + apr_pool_t *pool, + apr_int32_t flags) +{ + return apr_shm_attach(m, filename, pool); +} + APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m) { delete_area(m->aid); diff --git a/shmem/os2/shm.c b/shmem/os2/shm.c index 340cae407..1734674a8 100644 --- a/shmem/os2/shm.c +++ b/shmem/os2/shm.c @@ -56,6 +56,15 @@ APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *p, + apr_int32_t flags) +{ + return apr_shm_create(m, reqsize, filename, p); +} + APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m) { DosFreeMem(m->memblock); @@ -90,6 +99,14 @@ APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_shm_attach_ex(apr_shm_t **m, + const char *filename, + apr_pool_t *pool, + apr_int32_t flags) +{ + return apr_shm_attach(m, filename, pool); +} + APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m) { int rc = 0; diff --git a/shmem/unix/shm.c b/shmem/unix/shm.c index 73a729df9..87a7ce045 100644 --- a/shmem/unix/shm.c +++ b/shmem/unix/shm.c @@ -365,6 +365,15 @@ APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, } } +APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *p, + apr_int32_t flags) +{ + return apr_shm_create(m, reqsize, filename, p); +} + APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename, apr_pool_t *pool) { @@ -570,6 +579,14 @@ APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, } } +APR_DECLARE(apr_status_t) apr_shm_attach_ex(apr_shm_t **m, + const char *filename, + apr_pool_t *pool, + apr_int32_t flags) +{ + return apr_shm_attach(m, filename, pool); +} + APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m) { apr_status_t rv = shm_cleanup_attach(m); diff --git a/shmem/win32/shm.c b/shmem/win32/shm.c index 85926ab7e..56d982600 100644 --- a/shmem/win32/shm.c +++ b/shmem/win32/shm.c @@ -56,10 +56,69 @@ static apr_status_t shm_cleanup(void* shm) return rv; } -APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, - apr_size_t reqsize, - const char *file, - apr_pool_t *pool) +/* See if the caller is able to create a map in the global namespace by + * checking if the SE_CREATE_GLOBAL_NAME privilege is enabled. + * + * Prior to APR 1.5.0, named shared memory segments were always created + * in the global segment. However, with recent versions of Windows this + * fails for unprivileged processes. Thus, with older APR, named shared + * memory segments can't be created by unprivileged processes on newer + * Windows. + * + * By checking if the caller has the privilege, shm APIs can decide + * whether to use the Global or Local namespace. + * + * If running on an SDK without the required API definitions *OR* + * some processing failure occurs trying to check the privilege, fall + * back to earlier behavior -- always try to use the Global namespace. + */ +#ifdef SE_CREATE_GLOBAL_NAME +static int can_create_global_maps(void) +{ + BOOL ok, has_priv; + LUID priv_id; + PRIVILEGE_SET privs; + HANDLE hToken; + + ok = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken); + if (!ok && GetLastError() == ERROR_NO_TOKEN) { + /* no thread-specific access token, so try to get process access token + */ + ok = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken); + } + + if (ok) { + ok = LookupPrivilegeValue(NULL, SE_CREATE_GLOBAL_NAME, &priv_id); + } + + if (ok) { + privs.PrivilegeCount = 1; + privs.Control = PRIVILEGE_SET_ALL_NECESSARY; + privs.Privilege[0].Luid = priv_id; + privs.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED; + ok = PrivilegeCheck(hToken, &privs, &has_priv); + } + + if (ok && !has_priv) { + return 0; + } + else { + return 1; + } +} +#else /* SE_CREATE_GLOBAL_NAME */ +/* SDK definitions missing */ +static int can_create_global_maps(void) +{ + return 1; +} +#endif /* SE_CREATE_GLOBAL_NAME */ + +APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m, + apr_size_t reqsize, + const char *file, + apr_pool_t *pool, + apr_int32_t flags) { static apr_size_t memblock = 0; HANDLE hMap, hFile; @@ -96,6 +155,8 @@ APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, mapkey = NULL; } else { + int global; + /* Do file backed, which is not an inherited handle * While we could open APR_EXCL, it doesn't seem that Unix * ever did. Ignore that error here, but fail later when @@ -112,9 +173,18 @@ APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, /* res_name_from_filename turns file into a pseudo-name * without slashes or backslashes, and prepends the \global - * prefix on Win2K and later + * or \local prefix on Win2K and later */ - mapkey = res_name_from_filename(file, 1, pool); + if (flags & APR_SHM_NS_GLOBAL) { + global = 1; + } + else if (flags & APR_SHM_NS_LOCAL) { + global = 0; + } + else { + global = can_create_global_maps(); + } + mapkey = res_name_from_filename(file, global, pool); } #if APR_HAS_UNICODE_FS @@ -170,6 +240,14 @@ APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, + apr_size_t reqsize, + const char *file, + apr_pool_t *pool) +{ + return apr_shm_create_ex(m, reqsize, file, pool, 0); +} + APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m) { apr_status_t rv = shm_cleanup(m); @@ -183,24 +261,20 @@ APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename, return apr_file_remove(filename, pool); } -APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, - const char *file, - apr_pool_t *pool) +static apr_status_t shm_attach_internal(apr_shm_t **m, + const char *file, + apr_pool_t *pool, + int global) { HANDLE hMap; void *mapkey; void *base; - if (!file) { - return APR_EINVAL; - } - else { - /* res_name_from_filename turns file into a pseudo-name - * without slashes or backslashes, and prepends the \global - * prefix on Win2K and later - */ - mapkey = res_name_from_filename(file, 1, pool); - } + /* res_name_from_filename turns file into a pseudo-name + * without slashes or backslashes, and prepends the \global + * or local prefix on Win2K and later + */ + mapkey = res_name_from_filename(file, global, pool); #if APR_HAS_UNICODE_FS IF_WIN_OS_IS_UNICODE @@ -264,6 +338,55 @@ APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_shm_attach_ex(apr_shm_t **m, + const char *file, + apr_pool_t *pool, + apr_int32_t flags) +{ + apr_status_t rv; + int can_create_global; + int try_global_local[3] = {-1, -1, -1}; + int cur; + + if (!file) { + return APR_EINVAL; + } + + if (flags & APR_SHM_NS_LOCAL) { + try_global_local[0] = 0; /* only search local */ + } + else if (flags & APR_SHM_NS_GLOBAL) { + try_global_local[0] = 1; /* only search global */ + } + else { + can_create_global = can_create_global_maps(); + if (!can_create_global) { /* unprivileged process */ + try_global_local[0] = 0; /* search local before global */ + try_global_local[1] = 1; + } + else { + try_global_local[0] = 1; /* search global before local */ + try_global_local[1] = 0; + } + } + + for (cur = 0; try_global_local[cur] != -1; cur++) { + rv = shm_attach_internal(m, file, pool, try_global_local[cur]); + if (!APR_STATUS_IS_ENOENT(rv)) { + break; + } + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, + const char *file, + apr_pool_t *pool) +{ + return apr_shm_attach_ex(m, file, pool, 0); +} + APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m) { apr_status_t rv = shm_cleanup(m); |