18329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI/*
28329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * Copyright (c) 2013 FNST, DAN LI <li.dan@cn.fujitsu.com>
38329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *
48329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * This program is free software;  you can redistribute it and/or modify
58329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * it under the terms of the GNU General Public License as published by
68329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * the Free Software Foundation; either version 2 of the License, or
78329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * (at your option) any later version.
88329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *
98329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * This program is distributed in the hope that it will be useful,
108329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * but WITHOUT ANY WARRANTY;  without even the implied warranty of
118329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
128329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * the GNU General Public License for more details.
138329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *
148329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * You should have received a copy of the GNU General Public License
158329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * along with this program;  if not, write to the Free Software
168329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
178329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI */
188329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
198329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI/*
208329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * Test Description:
218329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *  Verify error signal SIGBUS.
228329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *  "Attempted access to a portion of the buffer that does not correspond
238329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *   to the file."
248329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *
258329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI * Expected Result:
268329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *  mmap() should succeed returning the address of the mapped region,
278329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *  and an attempt to access the memory which does not correspond to the file
288329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *  should rise the signal SIGBUS.
298329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI */
308329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <stdio.h>
318329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <stdlib.h>
328329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <sys/types.h>
338329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <errno.h>
348329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <unistd.h>
358329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <fcntl.h>
368329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <string.h>
378329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <signal.h>
388329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <sys/stat.h>
398329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <sys/mman.h>
408329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include <setjmp.h>
418329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
428329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#include "test.h"
438329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
448329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI#define TEMPFILE	"mmapfile"
458329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
468329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIchar *TCID = "mmap13";
478329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIint TST_TOTAL = 1;
488329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
498329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic size_t page_sz;
508329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic char *addr;
518329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic int fildes;
528329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic volatile sig_atomic_t pass;
538329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic sigjmp_buf env;
548329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
558329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic void setup(void);
568329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic void cleanup(void);
578329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic void sig_handler(int sig);
588329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
598329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIint main(int argc, char *argv[])
608329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI{
618329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	int lc;
628329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	char *ch;
638329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
64d6d11d08678aac1ed2c370ea8e42e5f45aea07beCyril Hrubis	tst_parse_opts(argc, argv, NULL, NULL);
658329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
668329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	setup();
678329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
688329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	for (lc = 0; TEST_LOOPING(lc); lc++) {
698329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		tst_count = 0;
708329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
718329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		addr = mmap(NULL, page_sz * 2, PROT_READ | PROT_WRITE,
728329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI			    MAP_FILE | MAP_SHARED, fildes, 0);
738329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
748329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		if (addr == MAP_FAILED) {
758329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI			tst_resm(TFAIL | TERRNO, "mmap() failed on %s",
768329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI				 TEMPFILE);
778329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI			continue;
788329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		}
798329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
80e38b961c385192f0d804914b77bd590734b42e75Cyril Hrubis		if (sigsetjmp(env, 1) == 0) {
81e38b961c385192f0d804914b77bd590734b42e75Cyril Hrubis			ch = addr + page_sz + 1;
82e38b961c385192f0d804914b77bd590734b42e75Cyril Hrubis			*ch = 0;
838329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		}
848329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
85e38b961c385192f0d804914b77bd590734b42e75Cyril Hrubis		if (pass)
86e38b961c385192f0d804914b77bd590734b42e75Cyril Hrubis			tst_resm(TPASS, "Got SIGBUS "
87e38b961c385192f0d804914b77bd590734b42e75Cyril Hrubis					"as expected");
88e38b961c385192f0d804914b77bd590734b42e75Cyril Hrubis		else
89e38b961c385192f0d804914b77bd590734b42e75Cyril Hrubis			tst_resm(TFAIL, "Invalid access not "
90e38b961c385192f0d804914b77bd590734b42e75Cyril Hrubis						"rise SIGBUS");
91e38b961c385192f0d804914b77bd590734b42e75Cyril Hrubis
928329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		if (munmap(addr, page_sz * 2) != 0)
938329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI			tst_brkm(TFAIL | TERRNO, cleanup,
948329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI				 "failed to unmap the mmapped pages");
958329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
968329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		pass = 0;
978329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	}
988329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
998329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	cleanup();
1008329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	tst_exit();
1018329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI}
1028329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
1038329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic void setup(void)
1048329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI{
1058329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	tst_sig(NOFORK, sig_handler, cleanup);
1068329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
1078329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	TEST_PAUSE;
1088329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
1098329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	page_sz = getpagesize();
1108329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
1118329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	tst_tmpdir();
1128329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
1138329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0766);
1148329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	if (fildes < 0)
1158329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		tst_brkm(TFAIL | TERRNO, cleanup, "opening %s failed",
1168329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI			 TEMPFILE);
1178329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
1188329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	if (ftruncate(fildes, page_sz / 2) == -1)
1198329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		tst_brkm(TFAIL | TERRNO, cleanup, "ftruncate %s failed",
1208329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI			 TEMPFILE);
1218329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI}
1228329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
1238329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI/*
1248329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *   This function gets executed when the test process receives
1258329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *   the signal SIGBUS while trying to access the memory which
1268329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI *   does not correspond to the file.
1278329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI */
1288329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic void sig_handler(int sig)
1298329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI{
1308329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	if (sig == SIGBUS) {
1318329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		pass = 1;
1328329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		siglongjmp(env, 1);
1338329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	} else {
1348329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI		tst_brkm(TBROK, cleanup, "received an unexpected signal");
1358329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	}
1368329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI}
1378329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI
1388329ed8a449efe34672eabfe6ab44bf7116cc661DAN LIstatic void cleanup(void)
1398329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI{
1408329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	close(fildes);
1418329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI	tst_rmdir();
1428329ed8a449efe34672eabfe6ab44bf7116cc661DAN LI}
143