• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) Ricardo Salveti de Araujo <rsalvetidev@gmail.com>, 2007
4  *
5  * DESCRIPTION
6  *     The remap_file_pages() system call is used to create a non-linear
7  *     mapping, that is, a mapping in which the pages of the file are mapped
8  *     into a non-sequential order in memory.  The advantage of using
9  *     remap_file_pages() over using repeated calls to mmap(2) is that
10  *     the former  approach  does  not require the kernel to create
11  *     additional VMA (Virtual Memory Area) data structures.
12  *
13  *     Runs remap_file_pages with wrong values and see if got the expected error
14  *
15  *     Setup:
16  *       1. Global:
17  *       2. Create a file, do a normal mmap with MAP_SHARED flag
18  *
19  *     Test:
20  *       1. Test with a valid mmap but without MAP_SHARED flag
21  *       2. Test with a invalid start argument
22  *       3. Test with a invalid size argument
23  *       4. Test with a invalid prot argument
24  *
25  * HISTORY
26  *
27  *     02/11/2008 - Removed the pgoff test case, as the latest kernels doesn't
28  *     verify the page offset (http://lkml.org/lkml/2007/11/29/325) - Ricardo
29  *     Salveti de Araujo, <rsalvetidev@gmail.com>
30  */
31 
32 #define _GNU_SOURCE
33 #include <sys/mman.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <errno.h>
40 #include <sys/syscall.h>
41 #include <linux/unistd.h>
42 
43 #include "tst_test.h"
44 #include "lapi/syscalls.h"
45 
46 #define WINDOW_START 0x48000000
47 
48 static unsigned int page_sz;
49 
50 static int fd;
51 static char *data = NULL;
52 static char *data01 = NULL;
53 
54 static void setup01(int test);
55 static void setup02(int test);
56 static void setup03(int test);
57 static void setup04(int test);
58 
59 static struct tcase {
60 	char *err_desc;
61 	int exp_errno;
62 	void (*setup)(int);
63 
64 	void *start;
65 	size_t size;
66 	int prot;
67 	ssize_t pgoff;
68 	int flags;
69 } tcases[] = {
70 	{"start is not valid MAP_SHARED mapping",
71 	 EINVAL, setup01, NULL, 0, 0, 2, 0},
72 	{"start is invalid", EINVAL, setup02, NULL, 0, 0, 2, 0},
73 	{"size is invalid", EINVAL, setup03,  NULL, 0, 0, 0, 0},
74 	{"prot is invalid", EINVAL, setup04, NULL, 0, 0, 2, 0}
75 };
76 
run(unsigned i)77 static void run(unsigned i)
78 {
79 	TEST(tst_syscall(__NR_remap_file_pages,
80 			 tcases[i].start, tcases[i].size,
81 			 tcases[i].prot, tcases[i].pgoff,
82 			 tcases[i].flags));
83 
84 	if ((TST_RET == -1) && (TST_ERR == tcases[i].exp_errno)) {
85 		tst_res(TPASS | TTERRNO, "remap_file_pages(2) %s",
86 			tcases[i].err_desc);
87 		return;
88 	}
89 
90 	tst_res(TFAIL | TTERRNO,
91 		"remap_file_pages(2) %s expected %s got",
92 		tcases[i].err_desc, tst_strerrno(tcases[i].exp_errno));
93 }
94 
setup01(int test)95 static void setup01(int test)
96 {
97 	tcases[test].start = data01;
98 	tcases[test].size = page_sz;
99 }
100 
setup02(int test)101 static void setup02(int test)
102 {
103 	tcases[test].start = data + page_sz;
104 	tcases[test].size = page_sz;
105 }
106 
setup03(int test)107 static void setup03(int test)
108 {
109 	tcases[test].start = data;
110 	tcases[test].size = 2 * page_sz;
111 }
112 
setup04(int test)113 static void setup04(int test)
114 {
115 	tcases[test].start = data;
116 	tcases[test].size = page_sz;
117 	tcases[test].prot = -1;
118 }
119 
setup(void)120 static void setup(void)
121 {
122 	unsigned int i;
123 
124 #if defined (__s390__) || (__s390x__) || (__ia64__)
125 	if ((tst_kvercmp(2, 6, 12)) < 0)
126 		tst_brk(TCONF,
127 			 "This test can only run on kernels that are 2.6.12 and higher");
128 #endif
129 
130 	page_sz = getpagesize();
131 
132 	fd = SAFE_OPEN("cache", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
133 	SAFE_FTRUNCATE(fd, page_sz);
134 
135 	data = SAFE_MMAP((void *)WINDOW_START, page_sz, PROT_READ | PROT_WRITE,
136 			 MAP_SHARED, fd, 0);
137 
138 	data01 = SAFE_MMAP(NULL, page_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE,
139 			   fd, 0);
140 
141 	for (i = 0; i < ARRAY_SIZE(tcases); i++) {
142 		if (tcases[i].setup)
143 			tcases[i].setup(i);
144 	}
145 }
146 
cleanup(void)147 static void cleanup(void)
148 {
149 	SAFE_CLOSE(fd);
150 
151 	if (data)
152 		SAFE_MUNMAP(data, page_sz);
153 
154 	if (data01)
155 		SAFE_MUNMAP(data01, page_sz);
156 }
157 
158 static struct tst_test test = {
159 	.tcnt = ARRAY_SIZE(tcases),
160 	.test = run,
161 	.cleanup = cleanup,
162 	.setup = setup,
163 	.needs_tmpdir = 1,
164 };
165