mirror of
https://sourceware.org/git/glibc.git
synced 2025-12-24 17:51:17 +03:00
linux: Require /dev/shm as the shared memory file system
Previously, glibc would pick an arbitrary tmpfs file system from /proc/mounts if /dev/shm was not available. This could lead to an unsuitable file system being picked for the backing storage for shm_open, sem_open, and related functions. This patch introduces a new function, __shm_get_name, which builds the file name under the appropriate (now hard-coded) directory. It is called from the various shm_* and sem_* function. Unlike the SHM_GET_NAME macro it replaces, the callers handle the return values and errno updates. shm-directory.c is moved directly into the posix subdirectory because it can be implemented directly using POSIX functionality. It resides in libc because it is needed by both librt and nptl/htl. In the sem_open implementation, tmpfname is initialized directly from a string constant. This happens to remove one alloca call. Checked on x86_64-linux-gnu.
This commit is contained in:
committed by
Adhemerval Zanella
parent
7f61f785f1
commit
e9fed2438a
@@ -62,8 +62,9 @@ int __sem_mappings_lock attribute_hidden = LLL_LOCK_INITIALIZER;
|
||||
|
||||
/* Search for existing mapping and if possible add the one provided. */
|
||||
static sem_t *
|
||||
check_add_mapping (const char *name, size_t namelen, int fd, sem_t *existing)
|
||||
check_add_mapping (const char *name, int fd, sem_t *existing)
|
||||
{
|
||||
size_t namelen = strlen (name);
|
||||
sem_t *result = SEM_FAILED;
|
||||
|
||||
/* Get the information about the file. */
|
||||
@@ -150,8 +151,12 @@ sem_open (const char *name, int oflag, ...)
|
||||
return SEM_FAILED;
|
||||
}
|
||||
|
||||
/* Create the name of the final file in local variable SHM_NAME. */
|
||||
SHM_GET_NAME (EINVAL, SEM_FAILED, SEM_SHM_PREFIX);
|
||||
struct shmdir_name dirname;
|
||||
if (__shm_get_name (&dirname, name, true) != 0)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return SEM_FAILED;
|
||||
}
|
||||
|
||||
/* Disable asynchronous cancellation. */
|
||||
#ifdef __libc_ptf_call
|
||||
@@ -164,7 +169,7 @@ sem_open (const char *name, int oflag, ...)
|
||||
if ((oflag & O_CREAT) == 0 || (oflag & O_EXCL) == 0)
|
||||
{
|
||||
try_again:
|
||||
fd = __libc_open (shm_name,
|
||||
fd = __libc_open (dirname.name,
|
||||
(oflag & ~(O_CREAT|O_ACCMODE)) | O_NOFOLLOW | O_RDWR);
|
||||
|
||||
if (fd == -1)
|
||||
@@ -178,13 +183,12 @@ sem_open (const char *name, int oflag, ...)
|
||||
else
|
||||
/* Check whether we already have this semaphore mapped and
|
||||
create one if necessary. */
|
||||
result = check_add_mapping (name, namelen, fd, SEM_FAILED);
|
||||
result = check_add_mapping (name, fd, SEM_FAILED);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have to open a temporary file first since it must have the
|
||||
correct form before we can start using it. */
|
||||
char *tmpfname;
|
||||
mode_t mode;
|
||||
unsigned int value;
|
||||
va_list ap;
|
||||
@@ -217,16 +221,11 @@ sem_open (const char *name, int oflag, ...)
|
||||
memset ((char *) &sem.initsem + sizeof (struct new_sem), '\0',
|
||||
sizeof (sem_t) - sizeof (struct new_sem));
|
||||
|
||||
tmpfname = __alloca (shm_dirlen + sizeof SEM_SHM_PREFIX + 6);
|
||||
char *xxxxxx = __mempcpy (tmpfname, shm_dir, shm_dirlen);
|
||||
|
||||
char tmpfname[] = SHMDIR "sem.XXXXXX";
|
||||
int retries = 0;
|
||||
#define NRETRIES 50
|
||||
while (1)
|
||||
{
|
||||
/* Add the suffix for mktemp. */
|
||||
strcpy (xxxxxx, "XXXXXX");
|
||||
|
||||
/* We really want to use mktemp here. We cannot use mkstemp
|
||||
since the file must be opened with a specific mode. The
|
||||
mode cannot later be set since then we cannot apply the
|
||||
@@ -244,7 +243,12 @@ sem_open (const char *name, int oflag, ...)
|
||||
if (errno == EEXIST)
|
||||
{
|
||||
if (++retries < NRETRIES)
|
||||
continue;
|
||||
{
|
||||
/* Restore the six placeholder bytes before the
|
||||
null terminator before the next attempt. */
|
||||
memcpy (tmpfname + sizeof (tmpfname) - 7, "XXXXXX", 6);
|
||||
continue;
|
||||
}
|
||||
|
||||
__set_errno (EAGAIN);
|
||||
}
|
||||
@@ -265,7 +269,7 @@ sem_open (const char *name, int oflag, ...)
|
||||
fd, 0)) != MAP_FAILED)
|
||||
{
|
||||
/* Create the file. Don't overwrite an existing file. */
|
||||
if (link (tmpfname, shm_name) != 0)
|
||||
if (link (tmpfname, dirname.name) != 0)
|
||||
{
|
||||
/* Undo the mapping. */
|
||||
(void) munmap (result, sizeof (sem_t));
|
||||
@@ -290,7 +294,7 @@ sem_open (const char *name, int oflag, ...)
|
||||
/* Insert the mapping into the search tree. This also
|
||||
determines whether another thread sneaked by and already
|
||||
added such a mapping despite the fact that we created it. */
|
||||
result = check_add_mapping (name, namelen, fd, result);
|
||||
result = check_add_mapping (name, fd, result);
|
||||
}
|
||||
|
||||
/* Now remove the temporary name. This should never fail. If
|
||||
|
||||
Reference in New Issue
Block a user