With APR on Windows, creating shared memory or a cross-process mutex with a
"file" name parameter results in a resource being created with a "Global"
prefix, which in turn restricts the call to Administrator (or more
accurately, a thread with the specific privilege
to make that call; let's just call that "Administrator" for simplicity).
(I think this is just for shared memory???)
A typical way to encounter this is that some dude in httpd-land decides
that mod_lua should start creating APR shared memory at startup and a
filename should always be specified, and suddenly httpd running as you on
Windows can no longer use mod_lua. Any number of other httpd modules try
do something similar (though I haven't investigated if there's a way to
configure around it); additionally, APR's testshm won't work as a regular
user.
The attached patch uses "Local" as the prefix if the calling thread doesn't
have the necessary privilege to create one under the global namespace. But
this function is also used for attach-type operations,
Has anyone investigated this before?
I suspect that the internal support routine res_name_from_file() (affected
by the patch) and callers need to be refactored so that
a. proc mutexes aren't affected
b. when trying to attach to shared memory from a caller without the
privilege, first try with the Local prefix (which is probably where it is)
and then try with the Global prefix (in case the shm was created by a
process with the privilege)
Unless someone has hints, I'll proceed in that manner.
--
Born in Roswell... married an alien...
http://emptyhammock.com/
Index: file_io/win32/open.c
===================================================================
--- file_io/win32/open.c (revision 1531529)
+++ file_io/win32/open.c (working copy)
@@ -147,6 +147,41 @@
apr_size_t r, d;
if (apr_os_level >= APR_WIN_2000) {
+#ifdef SE_CREATE_GLOBAL_NAME
+ if (global && apr_os_level >= APR_WIN_2003) {
+ /* We'll see if the caller is able to create an object in the
global
+ * namespace and, if not, create it in the local namespace
instead.
+ *
+ * NOTE: This utility function is used for both creating
objects and
+ * accessing them; use of the Global prefix will be based
purely on
+ * whether the user could create them.
+ */
+ 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) {
+ global = 0;
+ }
+ }
+#endif /* SE_CREATE_GLOBAL_NAME */
if (global)
wpre = L"Global\\";
else