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