Skip to content

Commit

Permalink
Make macOS semaphore names more unique, improve assertion
Browse files Browse the repository at this point in the history
On macOS, semaphore names are global and processes can open semaphores of other processes by using their name. It was possible that multiple client/server processes randomly tried to create semaphores with the same memory address, which would cause them to have the same name. In that case, `sem_open` would fail because `O_EXCL` prevents creating semaphores if the name is already used.

This is made more unlikely by also including the PID in the semaphore name. Additionally, the semaphore name is prefixed with `/` to more closely follow the construction rules for semaphore names. In particular, the behavior is implementation-defined if the name is not prefixed with a slash.

See https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_open.html

Closes ddnet#8773.

More details are added to the assertion error message in case this does not end up fixing the issue.
  • Loading branch information
Robyt3 committed Aug 20, 2024
1 parent 580b269 commit 839c511
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions src/base/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -867,10 +867,15 @@ void sphore_destroy(SEMAPHORE *sem)
#elif defined(CONF_PLATFORM_MACOS)
void sphore_init(SEMAPHORE *sem)
{
char aBuf[32];
str_format(aBuf, sizeof(aBuf), "%p", (void *)sem);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "/%d.%p", pid(), (void *)sem);
*sem = sem_open(aBuf, O_CREAT | O_EXCL, S_IRWXU | S_IRWXG, 0);
dbg_assert(*sem != SEM_FAILED, "sem_open failure");
if(*sem == SEM_FAILED)
{
char aError[128];
str_format(aError, sizeof(aError), "sem_open failure, errno=%d, name='%s'", errno, aBuf);
dbg_assert(false, aError);
}
}
void sphore_wait(SEMAPHORE *sem)
{
Expand All @@ -888,8 +893,8 @@ void sphore_signal(SEMAPHORE *sem)
void sphore_destroy(SEMAPHORE *sem)
{
dbg_assert(sem_close(*sem) == 0, "sem_close failure");
char aBuf[32];
str_format(aBuf, sizeof(aBuf), "%p", (void *)sem);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "/%d.%p", pid(), (void *)sem);
dbg_assert(sem_unlink(aBuf) == 0, "sem_unlink failure");
}
#elif defined(CONF_FAMILY_UNIX)
Expand Down

0 comments on commit 839c511

Please sign in to comment.