|
|
Message-ID: <20260511123524.GE1827@brightrain.aerifal.cx>
Date: Mon, 11 May 2026 08:35:24 -0400
From: Rich Felker <dalias@...c.org>
To: SanthoshKumar Selvaraj <santhosh.kumar.selvaraj@...io>
Cc: "musl@...ts.openwall.com" <musl@...ts.openwall.com>
Subject: Re: sem_open and shm_open share the same namespace via
__shm_mapname
On Mon, May 11, 2026 at 09:24:45AM +0000, SanthoshKumar Selvaraj wrote:
> Hi,
>
> I'd like to report a namespace collision between sem_open and shm_open in musl's POSIX IPC implementation.
>
> The Problem
> Both shm_open (src/mman/shm_open.c) and sem_open (src/thread/sem_open.c) uses same __shm_mapname function to construct the name, which maps any name to /dev/shm/<name>:
>
> // src/mman/shm_open.c
>
> char *__shm_mapname(const char *name, char *buf)
>
> {
> ...
> memcpy(buf, "/dev/shm/", 9);
> memcpy(buf+9, name, p-name+1);
> return buf;
> }
>
>
> As a result, shm_open("/test") and sem_open("/test") both resolve to /dev/shm/test, causing them to collide when the same name is used for both a shared memory object and a named semaphore.
>
> Expected Behaviour (POSIX / glibc)
> The POSIX specification treats shared memory objects and named semaphores as separate namespaces. glibc enforces this by adding a sem. prefix in its sem_open path construction:
>
> shm_open("/test") → /dev/shm/test
> sem_open("/test") → /dev/shm/sem.test
>
>
> This is observable in practice: on glibc systems, a shared memory object and a semaphore with the same logical name coexist without conflict. On musl-based systems (Alpine Linux, embedded MUSL targets), they collide.
>
> Impact
> Any library or application that internally uses a named semaphore derived from a shared memory name — without expecting a collision — will silently fail or corrupt state on musl.
>
> A concrete example is Qt's QSharedMemory, which creates an accompanying QSystemSemaphore for locking using the same base name. To avoid this, Qt has had to add a platform-specific workaround for all musl targets to append _shm / _sem suffixes to avoid the collision or similar to glibc way of "sem." prefix.
>
> Suggested Fix
> In src/thread/sem_open.c, construct the semaphore path with a sem. prefix rather than reusing __shm_mapname directly:
>
> // Instead of:
> if (!(name = __shm_mapname(name, buf)))
> return SEM_FAILED;
>
> // Use a semaphore-specific path, e.g.:
> // /dev/shm/sem.<name>
>
>
> This would align musl's behaviour with glibc and the established convention, without breaking existing semaphore-only code.
>
> Thanks & Regards, SanthoshKumar Selvaraj Qt Company
Unfortunately this isn't a real solution, because shm_open of
"sem.foo" will still collide with sem_open of "foo". If we're going to
make a change here, it shouldn't be one we have to fix again later
because it's still broken in the same way, but a complete fix.
However, I'm not sure how much an action is really needed here. Both
of these are namespaces shared globally, and you can't just use fixed
names without some agreed-upon convention for assignment. Normally you
generate random non-colliding names or user-configured names and have
some protocol for sharing the names out of band. Nonetheless for
conformance reasons we should probably do something.
The best approach is probably using a character portable programs
cannot use in a shm name (something outside the Portable Filename
Character Set) as part of the semaphore prefix. Or, here's an idea
that would make the transition timeline controllable by users: use
such a name as a directory prefix, and only put semaphores in that
directory if the directory exists. Unlike the glibc approach this
would also avoid artificially limiting the semaphore name length
shorter than NAME_MAX.
Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.