Restrict shm_open and shm_unlink to SHMDIR. Fixes bugs 14752 and 15763.
[platform/upstream/glibc.git] / rt / tst-shm.c
1 /* Test program for POSIX shm_* functions.
2    Copyright (C) 2000-2013 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <errno.h>
21 #include <error.h>
22 #include <fcntl.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 #include <unistd.h>
29 #include <sys/mman.h>
30 #include <sys/stat.h>
31 #include <sys/wait.h>
32
33
34 /* We want to see output immediately.  */
35 #define STDOUT_UNBUFFERED
36
37
38 static int
39 do_open (void)
40 {
41   int fd;
42
43   /* Create the shared memory object.  */
44   fd = shm_open ("/shm-test", O_RDWR, 0600);
45   if (fd == -1)
46     {
47       /* We don't regard this as a bug.  Simply don't run the test.  It could
48          means there is no such implementation or the object is already in
49          use in which case we don't want to disturb.  */
50       perror ("failed to open shared memory object: shm_open");
51       return -1;
52     }
53
54   return fd;
55 }
56
57
58 static void
59 worker (int write_now)
60 {
61   struct timespec ts;
62   struct stat64 st;
63   int i;
64   int fd = do_open ();
65   char *mem;
66
67   if (fd == -1)
68     exit (fd);
69
70   if (fstat64 (fd, &st) == -1)
71     error (EXIT_FAILURE, 0, "stat failed");
72   if (st.st_size != 4000)
73     error (EXIT_FAILURE, 0, "size incorrect");
74
75   mem = mmap (NULL, 4000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
76   if (mem == MAP_FAILED)
77     error (EXIT_FAILURE, 0, "mmap failed");
78
79   ts.tv_sec = 0;
80   ts.tv_nsec = 500000000;
81
82   if (write_now)
83     for (i = 0; i <= 4; ++i)
84       mem[i] = i;
85   else
86     /* Wait until the first bytes of the memory region are 0, 1, 2, 3, 4.  */
87     while (1)
88       {
89         for (i = 0; i <= 4; ++i)
90           if (mem[i] != i)
91             break;
92
93         if (i > 4)
94           /* OK, that's done.  */
95           break;
96
97         nanosleep (&ts, NULL);
98       }
99
100   if (!write_now)
101     for (i = 0; i <= 4; ++i)
102       mem[i] = 4 + i;
103   else
104     /* Wait until the first bytes of the memory region are 4, 5, 6, 7, 8.  */
105     while (1)
106       {
107         for (i = 0; i <= 4; ++i)
108           if (mem[i] != 4 + i)
109             break;
110
111         if (i > 4)
112           /* OK, that's done.  */
113           break;
114
115         nanosleep (&ts, NULL);
116       }
117
118   if (munmap (mem, 4000) == -1)
119     error (EXIT_FAILURE, errno, "munmap");
120
121   close (fd);
122
123   exit (0);
124 }
125
126
127 static int
128 do_test (void)
129 {
130   int fd;
131   pid_t pid1;
132   pid_t pid2;
133   int status1;
134   int status2;
135   struct stat64 st;
136
137   fd = shm_open ("/../escaped", O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600);
138   if (fd != -1)
139     {
140       perror ("read file outside of SHMDIR directory");
141       return 1;
142     }
143
144
145   /* Create the shared memory object.  */
146   fd = shm_open ("/shm-test", O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600);
147   if (fd == -1)
148     {
149       /* We don't regard this as a bug.  Simply don't run the test.  It could
150          means there is no such implementation or the object is already in
151          use in which case we don't want to disturb.  */
152       perror ("failed to create a shared memory object: shm_open");
153       return 0;
154     }
155
156   /* Size the object.  We make it 4000 bytes long.  */
157   if (ftruncate (fd, 4000) == -1)
158     {
159       /* This failed.  Must be a bug in the implementation of the
160          shared memory itself.  */
161       perror ("failed to size of shared memory object: ftruncate");
162       close (fd);
163       shm_unlink ("/shm-test");
164       return 0;
165     }
166
167   if (fstat64 (fd, &st) == -1)
168     {
169       shm_unlink ("/shm-test");
170       error (EXIT_FAILURE, 0, "initial stat failed");
171     }
172   if (st.st_size != 4000)
173     {
174       shm_unlink ("/shm-test");
175       error (EXIT_FAILURE, 0, "initial size not correct");
176     }
177
178   /* Spawn to processes which will do the work.  */
179   pid1 = fork ();
180   if (pid1 == 0)
181     worker (0);
182   else if (pid1 == -1)
183     {
184       /* Couldn't create a second process.  */
185       perror ("fork");
186       close (fd);
187       shm_unlink ("/shm-test");
188       return 0;
189     }
190
191   pid2 = fork ();
192   if (pid2 == 0)
193     worker (1);
194   else if (pid2 == -1)
195     {
196       /* Couldn't create a second process.  */
197       int ignore;
198       perror ("fork");
199       kill (pid1, SIGTERM);
200       waitpid (pid1, &ignore, 0);
201       close (fd);
202       shm_unlink ("/shm-test");
203       return 0;
204     }
205
206   /* Wait until the two processes are finished.  */
207   waitpid (pid1, &status1, 0);
208   waitpid (pid2, &status2, 0);
209
210   /* Now we can unlink the shared object.  */
211   shm_unlink ("/shm-test");
212
213   return (!WIFEXITED (status1) || WEXITSTATUS (status1) != 0
214           || !WIFEXITED (status2) || WEXITSTATUS (status2) != 0);
215 }
216 #define TEST_FUNCTION do_test ()
217
218 #define CLEANUP_HANDLER shm_unlink ("/shm-test");
219
220
221 #include "../test-skeleton.c"