aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/Makefile3
-rwxr-xr-xtests/run_tests.py3
-rw-r--r--tests/shm-perms.c130
3 files changed, 135 insertions, 1 deletions
diff --git a/tests/Makefile b/tests/Makefile
index 3e0a832..f7e9b26 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -9,7 +9,8 @@ LIB_TESTS = gethugepagesize test_root find_path unlinked_fd misalign \
misaligned_offset brk_near_huge task-size-overrun stack_grow_into_huge \
counters quota heap-overflow get_huge_pages get_hugepage_region \
shmoverride_linked gethugepagesizes \
- madvise_reserve fadvise_reserve readahead_reserve
+ madvise_reserve fadvise_reserve readahead_reserve \
+ shm-perms
LIB_TESTS_64 = straddle_4GB huge_at_4GB_normal_below \
huge_below_4GB_normal_above
NOLIB_TESTS = malloc malloc_manysmall dummy heapshrink shmoverride_unlinked
diff --git a/tests/run_tests.py b/tests/run_tests.py
index 871ae7c..a0357ee 100755
--- a/tests/run_tests.py
+++ b/tests/run_tests.py
@@ -482,6 +482,9 @@ def functional_tests():
do_test("readahead_reserve.sh")
do_test("madvise_reserve.sh")
do_test("fadvise_reserve.sh")
+ sysctls = setup_shm_sysctl(64*1048576)
+ do_test("shm-perms")
+ restore_shm_sysctl(sysctls)
# Tests requiring an active mount and hugepage COW
do_test("private")
diff --git a/tests/shm-perms.c b/tests/shm-perms.c
new file mode 100644
index 0000000..47d4d6b
--- /dev/null
+++ b/tests/shm-perms.c
@@ -0,0 +1,130 @@
+/*
+ * libhugetlbfs - Easy use of Linux hugepages
+ *
+ * This 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.
+ *
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <errno.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <hugetlbfs.h>
+#include "hugetests.h"
+
+#define P "shm-perms"
+#define DESC \
+ "* Test shared memory behavior when multiple threads are attached *\n"\
+ "* to a segment with different permissions. A segment is created *\n"\
+ "* and children attach read-only to check reservation accounting. *"
+
+#define SEGMENT_SIZE ((size_t)0x4000000)
+#define SEGMENT_KEY 0x82ba15ff
+#define SEGMENT_ADDR ((void *)0x40000000)
+
+#define STRIDE 0x200000
+
+static int global_shmid = -1;
+
+void cleanup(void)
+{
+ remove_shmid(global_shmid);
+}
+
+int attach_segment(size_t segsize, int shmflags, int shmperms)
+{
+ int shmid;
+
+ /* Create/get large segment */
+ shmid = shmget(SEGMENT_KEY, segsize, shmflags);
+ if (shmid == -1) {
+ perror("shmget(SEGMENT)");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Attach large segment */
+ if (shmat(shmid, SEGMENT_ADDR, shmperms) == (void *)-1) {
+ perror("shmat(SEGMENT)");
+ exit(EXIT_FAILURE);
+ }
+
+ global_shmid = shmid;
+ return shmid;
+}
+
+int main(int argc, char **argv)
+{
+ char *p;
+ pid_t *wait_list;
+ int i, iterations;
+ long hpage_size = check_hugepagesize();
+ long total_hpages = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL);
+
+ /* Setup */
+ test_init(argc, argv);
+ check_hugetlb_shm_group();
+ if (hpage_size > SEGMENT_SIZE)
+ CONFIG("Page size is too large for configured SEGMENT_SIZE\n");
+ check_free_huge_pages(SEGMENT_SIZE / hpage_size);
+
+ iterations = (total_hpages * hpage_size) / SEGMENT_SIZE + 1;
+ verbose_printf("iterations = %d\n", iterations);
+
+ wait_list = malloc(sizeof(pid_t) * iterations);
+ if (wait_list == NULL)
+ FAIL("Failed to allocate wait_list");
+
+ /* Create, attach and part init segment */
+ attach_segment(SEGMENT_SIZE, IPC_CREAT|SHM_HUGETLB|0640, 0);
+ p = (char *)SEGMENT_ADDR;
+ for (i = 0; i < 4; i++, p += STRIDE)
+ memset(p, 0x55, STRIDE);
+
+ /* Detach segment */
+ if (shmdt(SEGMENT_ADDR) != 0)
+ FAIL("shmdt(SEGMENT)");
+
+ /* Create children to reattach read-only */
+ for (i = 0; i < iterations; i++) {
+ pid_t pid;
+ pid = fork();
+ if (pid == -1)
+ FAIL("fork");
+
+ if (pid) {
+ wait_list[i] = pid;
+ } else {
+ attach_segment(0, 0, SHM_RDONLY);
+ if (shmdt(SEGMENT_ADDR) != 0) {
+ perror("shmdt(SEGMENT)");
+ exit(EXIT_FAILURE);
+ }
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ /* Wait for all children to exit */
+ for (i = 0; i < iterations; i++) {
+ int status;
+ if (waitpid(wait_list[i], &status, 0) == -1)
+ FAIL("waitpid");
+ if (status != EXIT_SUCCESS)
+ FAIL("Child exited with failure");
+ }
+
+ PASS();
+}