about summary refs log tree commit diff
path: root/sysdeps/pthread
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2021-02-03 08:55:13 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2021-02-08 14:10:42 -0300
commite9fed2438a1ff475821864f906286dc58907f06b (patch)
tree185b4a49e256ef312e65eafebf836ba17ea2ccef /sysdeps/pthread
parent7f61f785f16d22f185de77086c44a88218436cfb (diff)
downloadglibc-e9fed2438a1ff475821864f906286dc58907f06b.tar.gz
glibc-e9fed2438a1ff475821864f906286dc58907f06b.tar.xz
glibc-e9fed2438a1ff475821864f906286dc58907f06b.zip
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.
Diffstat (limited to 'sysdeps/pthread')
-rw-r--r--sysdeps/pthread/sem_open.c34
-rw-r--r--sysdeps/pthread/sem_unlink.c10
2 files changed, 26 insertions, 18 deletions
diff --git a/sysdeps/pthread/sem_open.c b/sysdeps/pthread/sem_open.c
index b0b722121d..d666414f32 100644
--- a/sysdeps/pthread/sem_open.c
+++ b/sysdeps/pthread/sem_open.c
@@ -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
diff --git a/sysdeps/pthread/sem_unlink.c b/sysdeps/pthread/sem_unlink.c
index faafbe4e91..1f06a55b8e 100644
--- a/sysdeps/pthread/sem_unlink.c
+++ b/sysdeps/pthread/sem_unlink.c
@@ -27,11 +27,15 @@
 int
 sem_unlink (const char *name)
 {
-  /* Construct the filename.  */
-  SHM_GET_NAME (ENOENT, -1, SEM_SHM_PREFIX);
+  struct shmdir_name dirname;
+  if (__shm_get_name (&dirname, name, true) != 0)
+    {
+      __set_errno (ENOENT);
+      return -1;
+    }
 
   /* Now try removing it.  */
-  int ret = unlink (shm_name);
+  int ret = unlink (dirname.name);
   if (ret < 0 && errno == EPERM)
     __set_errno (EACCES);
   return ret;