1/*-
2 * Copyright (c) 2006 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
--- 11 unchanged lines hidden (view full) ---
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: user/ngie/more-tests2/tests/sys/posixshm/posixshm_test.c 289437 2015-10-17 03:13:22Z ngie $");
29
30#include <sys/param.h>
31#include <sys/mman.h>
32#include <sys/resource.h>
33#include <sys/stat.h>
34#include <sys/syscall.h>
35#include <sys/wait.h>
36
--- 68 unchanged lines hidden (view full) ---
105
106 fd = shm_open(test_path, O_CREAT|O_EXCL|O_RDWR, 0777);
107 if (fd < 0 && errno == EEXIST) {
108 if (shm_unlink(test_path) < 0)
109 atf_tc_fail("shm_unlink");
110 fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777);
111 }
112 if (fd < 0)
113 atf_tc_fail("shm_open");
114 if (ftruncate(fd, getpagesize()) < 0)
115 atf_tc_fail("ftruncate");
116
117 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd,
118 0);
119 if (page == MAP_FAILED)
120 atf_tc_fail("mmap");
121
122 page[0] = '1';
123 if (munmap(page, getpagesize()) < 0)
124 atf_tc_fail("munmap");
125
126 return (fd);
127}
128
129ATF_TC_WITHOUT_HEAD(remap_object);
130ATF_TC_BODY(remap_object, tc)
131{
132 char *page;
133 int fd;
134
135 fd = scribble_object();
136
137 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd,
138 0);
139 if (page == MAP_FAILED) {
140 atf_tc_fail("mmap(2)");
141 close(fd);
142 shm_unlink(test_path);
143 return;
144 }
145
146 if (page[0] != '1') {
147 atf_tc_fail("missing data");
148 close(fd);
149 shm_unlink(test_path);
150 return;
151 }
152
153 close(fd);
154 if (munmap(page, getpagesize()) < 0) {
155 atf_tc_fail("munmap");
156 shm_unlink(test_path);
157 return;
158 }
159
160 if (shm_unlink(test_path) < 0) {
161 atf_tc_fail("shm_unlink");
162 return;
163 }
164
165}
166
167ATF_TC_WITHOUT_HEAD(reopen_object);
168ATF_TC_BODY(reopen_object, tc)
169{
170 char *page;
171 int fd;
172
173 fd = scribble_object();
174 close(fd);
175
176 fd = shm_open(test_path, O_RDONLY, 0777);
177 if (fd < 0) {
178 atf_tc_fail("shm_open(2)");
179 shm_unlink(test_path);
180 return;
181 }
182 page = mmap(0, getpagesize(), PROT_READ, MAP_SHARED, fd, 0);
183 if (page == MAP_FAILED) {
184 atf_tc_fail("mmap(2)");
185 close(fd);
186 shm_unlink(test_path);
187 return;
188 }
189
190 if (page[0] != '1') {
191 atf_tc_fail("missing data");
192 munmap(page, getpagesize());
193 close(fd);
194 shm_unlink(test_path);
195 return;
196 }
197
198 munmap(page, getpagesize());
199 close(fd);
200 shm_unlink(test_path);
201}
202
203ATF_TC_WITHOUT_HEAD(readonly_mmap_write);
204ATF_TC_BODY(readonly_mmap_write, tc)
205{
206 char *page;
207 int fd;
208
209 gen_test_path();
210
211 fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
212 if (fd < 0) {
213 atf_tc_fail("shm_open");
214 return;
215 }
216
217 /* PROT_WRITE should fail with EACCES. */
218 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd,
219 0);
220 if (page != MAP_FAILED) {
221 atf_tc_fail("mmap(PROT_WRITE) succeeded");
222 munmap(page, getpagesize());
223 close(fd);
224 shm_unlink(test_path);
225 return;
226 }
227 if (errno != EACCES) {
228 atf_tc_fail("mmap");
229 close(fd);
230 shm_unlink(test_path);
231 return;
232 }
233
234 close(fd);
235 shm_unlink(test_path);
236}
237
238ATF_TC_WITHOUT_HEAD(open_after_link);
239ATF_TC_BODY(open_after_link, tc)
240{
241 int fd;
242
243 gen_test_path();
244
245 fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
246 if (fd < 0) {
247 atf_tc_fail("shm_open(1)");
248 return;
249 }
250 close(fd);
251
252 if (shm_unlink(test_path) < 0) {
253 atf_tc_fail("shm_unlink");
254 return;
255 }
256
257 shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT);
258}
259
260ATF_TC_WITHOUT_HEAD(open_invalid_path);
261ATF_TC_BODY(open_invalid_path, tc)
262{
263
--- 19 unchanged lines hidden (view full) ---
283}
284
285ATF_TC_WITHOUT_HEAD(open_anon);
286ATF_TC_BODY(open_anon, tc)
287{
288 int fd;
289
290 fd = shm_open(SHM_ANON, O_RDWR, 0777);
291 if (fd < 0) {
292 atf_tc_fail("shm_open");
293 return;
294 }
295 close(fd);
296}
297
298ATF_TC_WITHOUT_HEAD(open_anon_readonly);
299ATF_TC_BODY(open_anon_readonly, tc)
300{
301
302 shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL);
--- 28 unchanged lines hidden (view full) ---
331ATF_TC_WITHOUT_HEAD(open_create_existing_object);
332ATF_TC_BODY(open_create_existing_object, tc)
333{
334 int fd;
335
336 gen_test_path();
337
338 fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777);
339 ATF_REQUIRE_MSG(fd != -1, "shm_open(O_CREAT) failed; errno=%d", errno);
340 close(fd);
341
342 shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL,
343 0777, EEXIST);
344
345 shm_unlink("shm_object");
346}
347
348ATF_TC_WITHOUT_HEAD(trunc_resets_object);
349ATF_TC_BODY(trunc_resets_object, tc)
350{
351 struct stat sb;
352 int fd;
353
354 gen_test_path();
355
356 /* Create object and set size to 1024. */
357 fd = shm_open(test_path, O_RDWR | O_CREAT, 0777);
358 if (fd < 0) {
359 atf_tc_fail("shm_open(1)");
360 return;
361 }
362 if (ftruncate(fd, 1024) < 0) {
363 atf_tc_fail("ftruncate");
364 close(fd);
365 return;
366 }
367 if (fstat(fd, &sb) < 0) {
368 atf_tc_fail("fstat(1)");
369 close(fd);
370 return;
371 }
372 if (sb.st_size != 1024) {
373 atf_tc_fail("size %d != 1024", (int)sb.st_size);
374 close(fd);
375 return;
376 }
377 close(fd);
378
379 /* Open with O_TRUNC which should reset size to 0. */
380 fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777);
381 if (fd < 0) {
382 atf_tc_fail("shm_open(2)");
383 return;
384 }
385 if (fstat(fd, &sb) < 0) {
386 atf_tc_fail("fstat(2)");
387 close(fd);
388 return;
389 }
390 if (sb.st_size != 0) {
391 atf_tc_fail("size after O_TRUNC %d != 0", (int)sb.st_size);
392 close(fd);
393 return;
394 }
395 close(fd);
396 if (shm_unlink(test_path) < 0) {
397 atf_tc_fail("shm_unlink");
398 return;
399 }
400}
401
402ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer);
403ATF_TC_BODY(unlink_bad_path_pointer, tc)
404{
405
406 shm_unlink_should_fail((char *)1024, EFAULT);
407}
--- 10 unchanged lines hidden (view full) ---
418 free(page);
419}
420
421ATF_TC_WITHOUT_HEAD(object_resize);
422ATF_TC_BODY(object_resize, tc)
423{
424 pid_t pid;
425 struct stat sb;
426 char *page;
427 int fd, status;
428
429 /* Start off with a size of a single page. */
430 fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0777);
431 if (fd < 0) {
432 atf_tc_fail("shm_open");
433 return;
434 }
435 if (ftruncate(fd, getpagesize()) < 0) {
436 atf_tc_fail("ftruncate(1)");
437 close(fd);
438 return;
439 }
440 if (fstat(fd, &sb) < 0) {
441 atf_tc_fail("fstat(1)");
442 close(fd);
443 return;
444 }
445 if (sb.st_size != getpagesize()) {
446 atf_tc_fail("first resize failed");
447 close(fd);
448 return;
449 }
450
451 /* Write a '1' to the first byte. */
452 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd,
453 0);
454 if (page == MAP_FAILED) {
455 atf_tc_fail("mmap(1)");
456 close(fd);
457 return;
458 }
459
460 page[0] = '1';
461
462 if (munmap(page, getpagesize()) < 0) {
463 atf_tc_fail("munmap(1)");
464 close(fd);
465 return;
466 }
467
468 /* Grow the object to 2 pages. */
469 if (ftruncate(fd, getpagesize() * 2) < 0) {
470 atf_tc_fail("ftruncate(2)");
471 close(fd);
472 return;
473 }
474 if (fstat(fd, &sb) < 0) {
475 atf_tc_fail("fstat(2)");
476 close(fd);
477 return;
478 }
479 if (sb.st_size != getpagesize() * 2) {
480 atf_tc_fail("second resize failed");
481 close(fd);
482 return;
483 }
484
485 /* Check for '1' at the first byte. */
486 page = mmap(0, getpagesize() * 2, PROT_READ | PROT_WRITE, MAP_SHARED,
487 fd, 0);
488 if (page == MAP_FAILED) {
489 atf_tc_fail("mmap(2)");
490 close(fd);
491 return;
492 }
493
494 if (page[0] != '1') {
495 atf_tc_fail("missing data at 0");
496 close(fd);
497 return;
498 }
499
500 /* Write a '2' at the start of the second page. */
501 page[getpagesize()] = '2';
502
503 /* Shrink the object back to 1 page. */
504 if (ftruncate(fd, getpagesize()) < 0) {
505 atf_tc_fail("ftruncate(3)");
506 close(fd);
507 return;
508 }
509 if (fstat(fd, &sb) < 0) {
510 atf_tc_fail("fstat(3)");
511 close(fd);
512 return;
513 }
514 if (sb.st_size != getpagesize()) {
515 atf_tc_fail("third resize failed");
516 close(fd);
517 return;
518 }
519
520 /*
521 * Fork a child process to make sure the second page is no
522 * longer valid.
523 */
524 pid = fork();
525 if (pid < 0) {
526 atf_tc_fail("fork");
527 close(fd);
528 return;
529 }
530
531 if (pid == 0) {
532 struct rlimit lim;
533 char c;
534
535 /* Don't generate a core dump. */
536 getrlimit(RLIMIT_CORE, &lim);
537 lim.rlim_cur = 0;
538 setrlimit(RLIMIT_CORE, &lim);
539
540 /*
541 * The previous ftruncate(2) shrunk the backing object
542 * so that this address is no longer valid, so reading
543 * from it should trigger a SIGSEGV.
544 */
545 c = page[getpagesize()];
546 fprintf(stderr, "child: page 1: '%c'\n", c);
547 exit(0);
548 }
549 if (wait(&status) < 0) {
550 atf_tc_fail("wait");
551 close(fd);
552 return;
553 }
554 if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGSEGV) {
555 atf_tc_fail("child terminated with status %x", status);
556 close(fd);
557 return;
558 }
559
560 /* Grow the object back to 2 pages. */
561 if (ftruncate(fd, getpagesize() * 2) < 0) {
562 atf_tc_fail("ftruncate(4)");
563 close(fd);
564 return;
565 }
566 if (fstat(fd, &sb) < 0) {
567 atf_tc_fail("fstat(4)");
568 close(fd);
569 return;
570 }
571 if (sb.st_size != getpagesize() * 2) {
572 atf_tc_fail("second resize failed");
573 close(fd);
574 return;
575 }
576
577 /*
578 * Note that the mapping at 'page' for the second page is
579 * still valid, and now that the shm object has been grown
580 * back up to 2 pages, there is now memory backing this page
581 * so the read will work. However, the data should be zero
582 * rather than '2' as the old data was thrown away when the
583 * object was shrunk and the new pages when an object are
584 * grown are zero-filled.
585 */
586 if (page[getpagesize()] != 0) {
587 atf_tc_fail("invalid data at %d", getpagesize());
588 close(fd);
589 return;
590 }
591
592 close(fd);
593}
594
595/* Signal handler which does nothing. */
596static void
597ignoreit(int sig __unused)
598{
--- 141 unchanged lines hidden ---
2 * Copyright (c) 2006 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
--- 11 unchanged lines hidden (view full) ---
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: user/ngie/more-tests2/tests/sys/posixshm/posixshm_test.c 289437 2015-10-17 03:13:22Z ngie $");
29
30#include <sys/param.h>
31#include <sys/mman.h>
32#include <sys/resource.h>
33#include <sys/stat.h>
34#include <sys/syscall.h>
35#include <sys/wait.h>
36
--- 68 unchanged lines hidden (view full) ---
105
106 fd = shm_open(test_path, O_CREAT|O_EXCL|O_RDWR, 0777);
107 if (fd < 0 && errno == EEXIST) {
108 if (shm_unlink(test_path) < 0)
109 atf_tc_fail("shm_unlink");
110 fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777);
111 }
112 if (fd < 0)
113 atf_tc_fail("shm_open");
114 if (ftruncate(fd, getpagesize()) < 0)
115 atf_tc_fail("ftruncate");
116
117 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd,
118 0);
119 if (page == MAP_FAILED)
120 atf_tc_fail("mmap");
121
122 page[0] = '1';
123 if (munmap(page, getpagesize()) < 0)
124 atf_tc_fail("munmap");
125
126 return (fd);
127}
128
129ATF_TC_WITHOUT_HEAD(remap_object);
130ATF_TC_BODY(remap_object, tc)
131{
132 char *page;
133 int fd;
134
135 fd = scribble_object();
136
137 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd,
138 0);
139 if (page == MAP_FAILED) {
140 atf_tc_fail("mmap(2)");
141 close(fd);
142 shm_unlink(test_path);
143 return;
144 }
145
146 if (page[0] != '1') {
147 atf_tc_fail("missing data");
148 close(fd);
149 shm_unlink(test_path);
150 return;
151 }
152
153 close(fd);
154 if (munmap(page, getpagesize()) < 0) {
155 atf_tc_fail("munmap");
156 shm_unlink(test_path);
157 return;
158 }
159
160 if (shm_unlink(test_path) < 0) {
161 atf_tc_fail("shm_unlink");
162 return;
163 }
164
165}
166
167ATF_TC_WITHOUT_HEAD(reopen_object);
168ATF_TC_BODY(reopen_object, tc)
169{
170 char *page;
171 int fd;
172
173 fd = scribble_object();
174 close(fd);
175
176 fd = shm_open(test_path, O_RDONLY, 0777);
177 if (fd < 0) {
178 atf_tc_fail("shm_open(2)");
179 shm_unlink(test_path);
180 return;
181 }
182 page = mmap(0, getpagesize(), PROT_READ, MAP_SHARED, fd, 0);
183 if (page == MAP_FAILED) {
184 atf_tc_fail("mmap(2)");
185 close(fd);
186 shm_unlink(test_path);
187 return;
188 }
189
190 if (page[0] != '1') {
191 atf_tc_fail("missing data");
192 munmap(page, getpagesize());
193 close(fd);
194 shm_unlink(test_path);
195 return;
196 }
197
198 munmap(page, getpagesize());
199 close(fd);
200 shm_unlink(test_path);
201}
202
203ATF_TC_WITHOUT_HEAD(readonly_mmap_write);
204ATF_TC_BODY(readonly_mmap_write, tc)
205{
206 char *page;
207 int fd;
208
209 gen_test_path();
210
211 fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
212 if (fd < 0) {
213 atf_tc_fail("shm_open");
214 return;
215 }
216
217 /* PROT_WRITE should fail with EACCES. */
218 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd,
219 0);
220 if (page != MAP_FAILED) {
221 atf_tc_fail("mmap(PROT_WRITE) succeeded");
222 munmap(page, getpagesize());
223 close(fd);
224 shm_unlink(test_path);
225 return;
226 }
227 if (errno != EACCES) {
228 atf_tc_fail("mmap");
229 close(fd);
230 shm_unlink(test_path);
231 return;
232 }
233
234 close(fd);
235 shm_unlink(test_path);
236}
237
238ATF_TC_WITHOUT_HEAD(open_after_link);
239ATF_TC_BODY(open_after_link, tc)
240{
241 int fd;
242
243 gen_test_path();
244
245 fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);
246 if (fd < 0) {
247 atf_tc_fail("shm_open(1)");
248 return;
249 }
250 close(fd);
251
252 if (shm_unlink(test_path) < 0) {
253 atf_tc_fail("shm_unlink");
254 return;
255 }
256
257 shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT);
258}
259
260ATF_TC_WITHOUT_HEAD(open_invalid_path);
261ATF_TC_BODY(open_invalid_path, tc)
262{
263
--- 19 unchanged lines hidden (view full) ---
283}
284
285ATF_TC_WITHOUT_HEAD(open_anon);
286ATF_TC_BODY(open_anon, tc)
287{
288 int fd;
289
290 fd = shm_open(SHM_ANON, O_RDWR, 0777);
291 if (fd < 0) {
292 atf_tc_fail("shm_open");
293 return;
294 }
295 close(fd);
296}
297
298ATF_TC_WITHOUT_HEAD(open_anon_readonly);
299ATF_TC_BODY(open_anon_readonly, tc)
300{
301
302 shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL);
--- 28 unchanged lines hidden (view full) ---
331ATF_TC_WITHOUT_HEAD(open_create_existing_object);
332ATF_TC_BODY(open_create_existing_object, tc)
333{
334 int fd;
335
336 gen_test_path();
337
338 fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777);
339 ATF_REQUIRE_MSG(fd != -1, "shm_open(O_CREAT) failed; errno=%d", errno);
340 close(fd);
341
342 shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL,
343 0777, EEXIST);
344
345 shm_unlink("shm_object");
346}
347
348ATF_TC_WITHOUT_HEAD(trunc_resets_object);
349ATF_TC_BODY(trunc_resets_object, tc)
350{
351 struct stat sb;
352 int fd;
353
354 gen_test_path();
355
356 /* Create object and set size to 1024. */
357 fd = shm_open(test_path, O_RDWR | O_CREAT, 0777);
358 if (fd < 0) {
359 atf_tc_fail("shm_open(1)");
360 return;
361 }
362 if (ftruncate(fd, 1024) < 0) {
363 atf_tc_fail("ftruncate");
364 close(fd);
365 return;
366 }
367 if (fstat(fd, &sb) < 0) {
368 atf_tc_fail("fstat(1)");
369 close(fd);
370 return;
371 }
372 if (sb.st_size != 1024) {
373 atf_tc_fail("size %d != 1024", (int)sb.st_size);
374 close(fd);
375 return;
376 }
377 close(fd);
378
379 /* Open with O_TRUNC which should reset size to 0. */
380 fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777);
381 if (fd < 0) {
382 atf_tc_fail("shm_open(2)");
383 return;
384 }
385 if (fstat(fd, &sb) < 0) {
386 atf_tc_fail("fstat(2)");
387 close(fd);
388 return;
389 }
390 if (sb.st_size != 0) {
391 atf_tc_fail("size after O_TRUNC %d != 0", (int)sb.st_size);
392 close(fd);
393 return;
394 }
395 close(fd);
396 if (shm_unlink(test_path) < 0) {
397 atf_tc_fail("shm_unlink");
398 return;
399 }
400}
401
402ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer);
403ATF_TC_BODY(unlink_bad_path_pointer, tc)
404{
405
406 shm_unlink_should_fail((char *)1024, EFAULT);
407}
--- 10 unchanged lines hidden (view full) ---
418 free(page);
419}
420
421ATF_TC_WITHOUT_HEAD(object_resize);
422ATF_TC_BODY(object_resize, tc)
423{
424 pid_t pid;
425 struct stat sb;
426 char *page;
427 int fd, status;
428
429 /* Start off with a size of a single page. */
430 fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0777);
431 if (fd < 0) {
432 atf_tc_fail("shm_open");
433 return;
434 }
435 if (ftruncate(fd, getpagesize()) < 0) {
436 atf_tc_fail("ftruncate(1)");
437 close(fd);
438 return;
439 }
440 if (fstat(fd, &sb) < 0) {
441 atf_tc_fail("fstat(1)");
442 close(fd);
443 return;
444 }
445 if (sb.st_size != getpagesize()) {
446 atf_tc_fail("first resize failed");
447 close(fd);
448 return;
449 }
450
451 /* Write a '1' to the first byte. */
452 page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd,
453 0);
454 if (page == MAP_FAILED) {
455 atf_tc_fail("mmap(1)");
456 close(fd);
457 return;
458 }
459
460 page[0] = '1';
461
462 if (munmap(page, getpagesize()) < 0) {
463 atf_tc_fail("munmap(1)");
464 close(fd);
465 return;
466 }
467
468 /* Grow the object to 2 pages. */
469 if (ftruncate(fd, getpagesize() * 2) < 0) {
470 atf_tc_fail("ftruncate(2)");
471 close(fd);
472 return;
473 }
474 if (fstat(fd, &sb) < 0) {
475 atf_tc_fail("fstat(2)");
476 close(fd);
477 return;
478 }
479 if (sb.st_size != getpagesize() * 2) {
480 atf_tc_fail("second resize failed");
481 close(fd);
482 return;
483 }
484
485 /* Check for '1' at the first byte. */
486 page = mmap(0, getpagesize() * 2, PROT_READ | PROT_WRITE, MAP_SHARED,
487 fd, 0);
488 if (page == MAP_FAILED) {
489 atf_tc_fail("mmap(2)");
490 close(fd);
491 return;
492 }
493
494 if (page[0] != '1') {
495 atf_tc_fail("missing data at 0");
496 close(fd);
497 return;
498 }
499
500 /* Write a '2' at the start of the second page. */
501 page[getpagesize()] = '2';
502
503 /* Shrink the object back to 1 page. */
504 if (ftruncate(fd, getpagesize()) < 0) {
505 atf_tc_fail("ftruncate(3)");
506 close(fd);
507 return;
508 }
509 if (fstat(fd, &sb) < 0) {
510 atf_tc_fail("fstat(3)");
511 close(fd);
512 return;
513 }
514 if (sb.st_size != getpagesize()) {
515 atf_tc_fail("third resize failed");
516 close(fd);
517 return;
518 }
519
520 /*
521 * Fork a child process to make sure the second page is no
522 * longer valid.
523 */
524 pid = fork();
525 if (pid < 0) {
526 atf_tc_fail("fork");
527 close(fd);
528 return;
529 }
530
531 if (pid == 0) {
532 struct rlimit lim;
533 char c;
534
535 /* Don't generate a core dump. */
536 getrlimit(RLIMIT_CORE, &lim);
537 lim.rlim_cur = 0;
538 setrlimit(RLIMIT_CORE, &lim);
539
540 /*
541 * The previous ftruncate(2) shrunk the backing object
542 * so that this address is no longer valid, so reading
543 * from it should trigger a SIGSEGV.
544 */
545 c = page[getpagesize()];
546 fprintf(stderr, "child: page 1: '%c'\n", c);
547 exit(0);
548 }
549 if (wait(&status) < 0) {
550 atf_tc_fail("wait");
551 close(fd);
552 return;
553 }
554 if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGSEGV) {
555 atf_tc_fail("child terminated with status %x", status);
556 close(fd);
557 return;
558 }
559
560 /* Grow the object back to 2 pages. */
561 if (ftruncate(fd, getpagesize() * 2) < 0) {
562 atf_tc_fail("ftruncate(4)");
563 close(fd);
564 return;
565 }
566 if (fstat(fd, &sb) < 0) {
567 atf_tc_fail("fstat(4)");
568 close(fd);
569 return;
570 }
571 if (sb.st_size != getpagesize() * 2) {
572 atf_tc_fail("second resize failed");
573 close(fd);
574 return;
575 }
576
577 /*
578 * Note that the mapping at 'page' for the second page is
579 * still valid, and now that the shm object has been grown
580 * back up to 2 pages, there is now memory backing this page
581 * so the read will work. However, the data should be zero
582 * rather than '2' as the old data was thrown away when the
583 * object was shrunk and the new pages when an object are
584 * grown are zero-filled.
585 */
586 if (page[getpagesize()] != 0) {
587 atf_tc_fail("invalid data at %d", getpagesize());
588 close(fd);
589 return;
590 }
591
592 close(fd);
593}
594
595/* Signal handler which does nothing. */
596static void
597ignoreit(int sig __unused)
598{
--- 141 unchanged lines hidden ---