aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/posix
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/posix
parent7f61f785f16d22f185de77086c44a88218436cfb (diff)
downloadglibc-e9fed2438a1ff475821864f906286dc58907f06b.zip
glibc-e9fed2438a1ff475821864f906286dc58907f06b.tar.gz
glibc-e9fed2438a1ff475821864f906286dc58907f06b.tar.bz2
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/posix')
-rw-r--r--sysdeps/posix/Makefile6
-rw-r--r--sysdeps/posix/shm-directory.c38
-rw-r--r--sysdeps/posix/shm-directory.h66
-rw-r--r--sysdeps/posix/shm_open.c10
-rw-r--r--sysdeps/posix/shm_unlink.c13
5 files changed, 17 insertions, 116 deletions
diff --git a/sysdeps/posix/Makefile b/sysdeps/posix/Makefile
index 52f20f5..b58aa6a 100644
--- a/sysdeps/posix/Makefile
+++ b/sysdeps/posix/Makefile
@@ -3,9 +3,3 @@ L_tmpnam = 20
TMP_MAX = 238328
L_ctermid = 9
L_cuserid = 9
-
-ifeq ($(subdir)|$(have-thread-library),rt|no)
-# With NPTL, this lives in libpthread so it can be used for sem_open too.
-# Without NPTL, it's just private in librt.
-librt-routines += shm-directory
-endif
diff --git a/sysdeps/posix/shm-directory.c b/sysdeps/posix/shm-directory.c
deleted file mode 100644
index a0510c1..0000000
--- a/sysdeps/posix/shm-directory.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Determine directory for shm/sem files. Generic POSIX version.
- Copyright (C) 2014-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#include <shm-directory.h>
-#include <unistd.h>
-
-#if _POSIX_MAPPED_FILES
-
-# include <paths.h>
-
-# define SHMDIR (_PATH_DEV "shm/")
-
-const char *
-__shm_directory (size_t *len)
-{
- *len = sizeof SHMDIR - 1;
- return SHMDIR;
-}
-# if IS_IN (libpthread)
-hidden_def (__shm_directory)
-# endif
-
-#endif
diff --git a/sysdeps/posix/shm-directory.h b/sysdeps/posix/shm-directory.h
deleted file mode 100644
index 7254bda..0000000
--- a/sysdeps/posix/shm-directory.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Header for directory for shm/sem files.
- Copyright (C) 2014-2021 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#ifndef _SHM_DIRECTORY_H
-
-#include <errno.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-
-extern const char *__shm_directory (size_t *len);
-
-/* This defines local variables SHM_DIR and SHM_DIRLEN, giving the
- directory prefix (with trailing slash) and length (not including '\0'
- terminator) of the directory used for shm files. If that cannot be
- determined, it sets errno to ENOSYS and returns RETVAL_FOR_INVALID.
-
- This uses the local variable NAME as an lvalue, and increments it past
- any leading slashes. It then defines the local variable NAMELEN, giving
- strlen (NAME) + 1. If NAME is invalid, it sets errno to
- ERRNO_FOR_INVALID and returns RETVAL_FOR_INVALID. Finally, it defines
- the local variable SHM_NAME, giving the absolute file name of the shm
- file corresponding to NAME. PREFIX is a string constant used as a
- prefix on NAME. */
-
-#define SHM_GET_NAME(errno_for_invalid, retval_for_invalid, prefix) \
- size_t shm_dirlen; \
- const char *shm_dir = __shm_directory (&shm_dirlen); \
- /* If we don't know what directory to use, there is nothing we can do. */ \
- if (__glibc_unlikely (shm_dir == NULL)) \
- { \
- __set_errno (ENOSYS); \
- return retval_for_invalid; \
- } \
- /* Construct the filename. */ \
- while (name[0] == '/') \
- ++name; \
- size_t namelen = strlen (name) + 1; \
- /* Validate the filename. */ \
- if (namelen == 1 || namelen >= NAME_MAX || strchr (name, '/') != NULL) \
- { \
- __set_errno (errno_for_invalid); \
- return retval_for_invalid; \
- } \
- char *shm_name = __alloca (shm_dirlen + sizeof prefix - 1 + namelen); \
- __mempcpy (__mempcpy (__mempcpy (shm_name, shm_dir, shm_dirlen), \
- prefix, sizeof prefix - 1), \
- name, namelen)
-
-#endif /* shm-directory.h */
diff --git a/sysdeps/posix/shm_open.c b/sysdeps/posix/shm_open.c
index aabc724..1817c52 100644
--- a/sysdeps/posix/shm_open.c
+++ b/sysdeps/posix/shm_open.c
@@ -24,6 +24,7 @@
#else
+# include <errno.h>
# include <fcntl.h>
# include <pthread.h>
# include <shm-directory.h>
@@ -33,7 +34,12 @@
int
shm_open (const char *name, int oflag, mode_t mode)
{
- SHM_GET_NAME (EINVAL, -1, "");
+ struct shmdir_name dirname;
+ if (__shm_get_name (&dirname, name, false) != 0)
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
oflag |= O_NOFOLLOW | O_CLOEXEC;
@@ -41,7 +47,7 @@ shm_open (const char *name, int oflag, mode_t mode)
int state;
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
- int fd = open (shm_name, oflag, mode);
+ int fd = open (dirname.name, oflag, mode);
if (fd == -1 && __glibc_unlikely (errno == EISDIR))
/* It might be better to fold this error with EINVAL since
directory names are just another example for unsuitable shared
diff --git a/sysdeps/posix/shm_unlink.c b/sysdeps/posix/shm_unlink.c
index f3258a0..c90b854 100644
--- a/sysdeps/posix/shm_unlink.c
+++ b/sysdeps/posix/shm_unlink.c
@@ -25,16 +25,21 @@
#include <errno.h>
#include <string.h>
-#include "shm-directory.h"
+#include <shm-directory.h>
/* Remove shared memory object. */
int
shm_unlink (const char *name)
{
- SHM_GET_NAME (ENOENT, -1, "");
-
- int result = unlink (shm_name);
+ struct shmdir_name dirname;
+ if (__shm_get_name (&dirname, name, false) != 0)
+ {
+ __set_errno (ENOENT);
+ return -1;
+ }
+
+ int result = unlink (dirname.name);
if (result < 0 && errno == EPERM)
__set_errno (EACCES);
return result;