1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Copyright (C) 2012 Linux Test Project, Inc.
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or
5f08c3bdfSopenharmony_ci * modify it under the terms of version 2 of the GNU General Public
6f08c3bdfSopenharmony_ci * License as published by the Free Software Foundation.
7f08c3bdfSopenharmony_ci *
8f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful,
9f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
10f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * Further, this software is distributed without any warranty that it
13f08c3bdfSopenharmony_ci * is free of the rightful claim of any third person regarding
14f08c3bdfSopenharmony_ci * infringement or the like.  Any license provided herein, whether
15f08c3bdfSopenharmony_ci * implied or otherwise, applies only to this software file.  Patent
16f08c3bdfSopenharmony_ci * licenses, if any, provided herein do not apply to combinations of
17f08c3bdfSopenharmony_ci * this program with other software, or any other product whatsoever.
18f08c3bdfSopenharmony_ci *
19f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License
20f08c3bdfSopenharmony_ci * along with this program; if not, write the Free Software
21f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22f08c3bdfSopenharmony_ci * 02110-1301, USA.
23f08c3bdfSopenharmony_ci */
24f08c3bdfSopenharmony_ci
25f08c3bdfSopenharmony_ci/*
26f08c3bdfSopenharmony_ci * errno tests for migrate_pages() syscall
27f08c3bdfSopenharmony_ci */
28f08c3bdfSopenharmony_ci#include <sys/types.h>
29f08c3bdfSopenharmony_ci#include <sys/syscall.h>
30f08c3bdfSopenharmony_ci#include <sys/wait.h>
31f08c3bdfSopenharmony_ci#include <sys/mman.h>
32f08c3bdfSopenharmony_ci#include <errno.h>
33f08c3bdfSopenharmony_ci#include <stdio.h>
34f08c3bdfSopenharmony_ci#include <stdlib.h>
35f08c3bdfSopenharmony_ci#include <string.h>
36f08c3bdfSopenharmony_ci#include <unistd.h>
37f08c3bdfSopenharmony_ci#include <pwd.h>
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_ci#include "test.h"
40f08c3bdfSopenharmony_ci#include "safe_macros.h"
41f08c3bdfSopenharmony_ci#include "lapi/syscalls.h"
42f08c3bdfSopenharmony_ci#include "numa_helper.h"
43f08c3bdfSopenharmony_ci#include "migrate_pages_common.h"
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_cichar *TCID = "migrate_pages01";
46f08c3bdfSopenharmony_ciint TST_TOTAL = 1;
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_cioption_t options[] = {
49f08c3bdfSopenharmony_ci	{NULL, NULL, NULL}
50f08c3bdfSopenharmony_ci};
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ci#ifdef HAVE_NUMA_V2
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_cistatic unsigned long *sane_old_nodes;
55f08c3bdfSopenharmony_cistatic unsigned long *sane_new_nodes;
56f08c3bdfSopenharmony_cistatic int sane_nodemask_size;
57f08c3bdfSopenharmony_cistatic int sane_max_node;
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_cistatic void setup(void);
60f08c3bdfSopenharmony_cistatic void cleanup(void);
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_cistatic void test_sane_nodes(void)
63f08c3bdfSopenharmony_ci{
64f08c3bdfSopenharmony_ci	tst_resm(TINFO, "test_empty_mask");
65f08c3bdfSopenharmony_ci	TEST(tst_syscall(__NR_migrate_pages, 0, sane_max_node,
66f08c3bdfSopenharmony_ci		     sane_old_nodes, sane_new_nodes));
67f08c3bdfSopenharmony_ci	check_ret(0);
68f08c3bdfSopenharmony_ci}
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_cistatic void test_invalid_pid(void)
71f08c3bdfSopenharmony_ci{
72f08c3bdfSopenharmony_ci	pid_t invalid_pid = -1;
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_ci	tst_resm(TINFO, "test_invalid_pid -1");
75f08c3bdfSopenharmony_ci	TEST(tst_syscall(__NR_migrate_pages, invalid_pid, sane_max_node,
76f08c3bdfSopenharmony_ci		     sane_old_nodes, sane_new_nodes));
77f08c3bdfSopenharmony_ci	check_ret(-1);
78f08c3bdfSopenharmony_ci	check_errno(ESRCH);
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci	tst_resm(TINFO, "test_invalid_pid unused pid");
81f08c3bdfSopenharmony_ci	invalid_pid = tst_get_unused_pid(cleanup);
82f08c3bdfSopenharmony_ci	TEST(tst_syscall(__NR_migrate_pages, invalid_pid, sane_max_node,
83f08c3bdfSopenharmony_ci		     sane_old_nodes, sane_new_nodes));
84f08c3bdfSopenharmony_ci	check_ret(-1);
85f08c3bdfSopenharmony_ci	check_errno(ESRCH);
86f08c3bdfSopenharmony_ci}
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_cistatic void test_invalid_masksize(void)
89f08c3bdfSopenharmony_ci{
90f08c3bdfSopenharmony_ci	tst_resm(TINFO, "test_invalid_masksize");
91f08c3bdfSopenharmony_ci	TEST(tst_syscall(__NR_migrate_pages, 0, -1, sane_old_nodes,
92f08c3bdfSopenharmony_ci		     sane_new_nodes));
93f08c3bdfSopenharmony_ci	check_ret(-1);
94f08c3bdfSopenharmony_ci	check_errno(EINVAL);
95f08c3bdfSopenharmony_ci}
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_cistatic void test_invalid_mem(void)
98f08c3bdfSopenharmony_ci{
99f08c3bdfSopenharmony_ci	unsigned long *p;
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci	tst_resm(TINFO, "test_invalid_mem -1");
102f08c3bdfSopenharmony_ci	TEST(tst_syscall(__NR_migrate_pages, 0, sane_max_node, -1, -1));
103f08c3bdfSopenharmony_ci	check_ret(-1);
104f08c3bdfSopenharmony_ci	check_errno(EFAULT);
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_ci	tst_resm(TINFO, "test_invalid_mem invalid prot");
107f08c3bdfSopenharmony_ci	p = mmap(NULL, getpagesize(), PROT_NONE,
108f08c3bdfSopenharmony_ci		 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
109f08c3bdfSopenharmony_ci	if (p == MAP_FAILED)
110f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "mmap");
111f08c3bdfSopenharmony_ci	TEST(tst_syscall(__NR_migrate_pages, 0, sane_max_node, p, p));
112f08c3bdfSopenharmony_ci	check_ret(-1);
113f08c3bdfSopenharmony_ci	check_errno(EFAULT);
114f08c3bdfSopenharmony_ci
115f08c3bdfSopenharmony_ci	SAFE_MUNMAP(cleanup, p, getpagesize());
116f08c3bdfSopenharmony_ci	tst_resm(TINFO, "test_invalid_mem unmmaped");
117f08c3bdfSopenharmony_ci	TEST(tst_syscall(__NR_migrate_pages, 0, sane_max_node, p, p));
118f08c3bdfSopenharmony_ci	check_ret(-1);
119f08c3bdfSopenharmony_ci	check_errno(EFAULT);
120f08c3bdfSopenharmony_ci}
121f08c3bdfSopenharmony_ci
122f08c3bdfSopenharmony_cistatic void test_invalid_nodes(void)
123f08c3bdfSopenharmony_ci{
124f08c3bdfSopenharmony_ci	int *nodes;
125f08c3bdfSopenharmony_ci	int num_nodes, ret, i;
126f08c3bdfSopenharmony_ci	int invalid_node = 0;
127f08c3bdfSopenharmony_ci	unsigned long *old_nodes, *new_nodes;
128f08c3bdfSopenharmony_ci
129f08c3bdfSopenharmony_ci	tst_resm(TINFO, "test_invalid_nodes");
130f08c3bdfSopenharmony_ci	ret = get_allowed_nodes_arr(NH_MEMS, &num_nodes, &nodes);
131f08c3bdfSopenharmony_ci	if (ret < 0)
132f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup,
133f08c3bdfSopenharmony_ci			 "get_allowed_nodes_arr: %d", ret);
134f08c3bdfSopenharmony_ci
135f08c3bdfSopenharmony_ci	/* get first node which is not in nodes */
136f08c3bdfSopenharmony_ci	for (i = 0; i < num_nodes; i++, invalid_node++)
137f08c3bdfSopenharmony_ci		if (invalid_node != nodes[i])
138f08c3bdfSopenharmony_ci			break;
139f08c3bdfSopenharmony_ci	if (invalid_node < sane_max_node) {
140f08c3bdfSopenharmony_ci		old_nodes = SAFE_MALLOC(NULL, sane_nodemask_size);
141f08c3bdfSopenharmony_ci		new_nodes = SAFE_MALLOC(NULL, sane_nodemask_size);
142f08c3bdfSopenharmony_ci		memcpy(old_nodes, sane_old_nodes, sane_nodemask_size);
143f08c3bdfSopenharmony_ci		memset(new_nodes, 0, sane_nodemask_size);
144f08c3bdfSopenharmony_ci		set_bit(new_nodes, invalid_node, 1);
145f08c3bdfSopenharmony_ci
146f08c3bdfSopenharmony_ci		TEST(tst_syscall(__NR_migrate_pages, 0, sane_max_node,
147f08c3bdfSopenharmony_ci			     old_nodes, new_nodes));
148f08c3bdfSopenharmony_ci		check_ret(-1);
149f08c3bdfSopenharmony_ci		check_errno(EINVAL);
150f08c3bdfSopenharmony_ci		free(old_nodes);
151f08c3bdfSopenharmony_ci		free(new_nodes);
152f08c3bdfSopenharmony_ci	} else {
153f08c3bdfSopenharmony_ci		tst_resm(TCONF, "All possible nodes are present");
154f08c3bdfSopenharmony_ci	}
155f08c3bdfSopenharmony_ci
156f08c3bdfSopenharmony_ci	free(nodes);
157f08c3bdfSopenharmony_ci}
158f08c3bdfSopenharmony_ci
159f08c3bdfSopenharmony_cistatic void test_invalid_perm(void)
160f08c3bdfSopenharmony_ci{
161f08c3bdfSopenharmony_ci	char nobody_uid[] = "nobody";
162f08c3bdfSopenharmony_ci	struct passwd *ltpuser;
163f08c3bdfSopenharmony_ci	int status;
164f08c3bdfSopenharmony_ci	pid_t child_pid;
165f08c3bdfSopenharmony_ci	pid_t parent_pid;
166f08c3bdfSopenharmony_ci	int ret = 0;
167f08c3bdfSopenharmony_ci
168f08c3bdfSopenharmony_ci	tst_resm(TINFO, "test_invalid_perm");
169f08c3bdfSopenharmony_ci	parent_pid = getpid();
170f08c3bdfSopenharmony_ci	fflush(stdout);
171f08c3bdfSopenharmony_ci	child_pid = fork();
172f08c3bdfSopenharmony_ci	switch (child_pid) {
173f08c3bdfSopenharmony_ci	case -1:
174f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "fork");
175f08c3bdfSopenharmony_ci		break;
176f08c3bdfSopenharmony_ci	case 0:
177f08c3bdfSopenharmony_ci		ltpuser = getpwnam(nobody_uid);
178f08c3bdfSopenharmony_ci		if (ltpuser == NULL)
179f08c3bdfSopenharmony_ci			tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed");
180f08c3bdfSopenharmony_ci		SAFE_SETUID(NULL, ltpuser->pw_uid);
181f08c3bdfSopenharmony_ci		TEST(tst_syscall(__NR_migrate_pages, parent_pid,
182f08c3bdfSopenharmony_ci			     sane_max_node, sane_old_nodes, sane_new_nodes));
183f08c3bdfSopenharmony_ci		ret |= check_ret(-1);
184f08c3bdfSopenharmony_ci		ret |= check_errno(EPERM);
185f08c3bdfSopenharmony_ci		exit(ret);
186f08c3bdfSopenharmony_ci	default:
187f08c3bdfSopenharmony_ci		SAFE_WAITPID(cleanup, child_pid, &status, 0);
188f08c3bdfSopenharmony_ci		if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
189f08c3bdfSopenharmony_ci			tst_resm(TFAIL, "child returns %d", status);
190f08c3bdfSopenharmony_ci	}
191f08c3bdfSopenharmony_ci}
192f08c3bdfSopenharmony_ci
193f08c3bdfSopenharmony_ciint main(int argc, char *argv[])
194f08c3bdfSopenharmony_ci{
195f08c3bdfSopenharmony_ci	int lc;
196f08c3bdfSopenharmony_ci
197f08c3bdfSopenharmony_ci	tst_parse_opts(argc, argv, options, NULL);
198f08c3bdfSopenharmony_ci
199f08c3bdfSopenharmony_ci	setup();
200f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); lc++) {
201f08c3bdfSopenharmony_ci		tst_count = 0;
202f08c3bdfSopenharmony_ci		test_sane_nodes();
203f08c3bdfSopenharmony_ci		test_invalid_pid();
204f08c3bdfSopenharmony_ci		test_invalid_masksize();
205f08c3bdfSopenharmony_ci		test_invalid_mem();
206f08c3bdfSopenharmony_ci		test_invalid_nodes();
207f08c3bdfSopenharmony_ci		test_invalid_perm();
208f08c3bdfSopenharmony_ci	}
209f08c3bdfSopenharmony_ci	cleanup();
210f08c3bdfSopenharmony_ci	tst_exit();
211f08c3bdfSopenharmony_ci}
212f08c3bdfSopenharmony_ci
213f08c3bdfSopenharmony_cistatic void setup(void)
214f08c3bdfSopenharmony_ci{
215f08c3bdfSopenharmony_ci	int node, ret;
216f08c3bdfSopenharmony_ci
217f08c3bdfSopenharmony_ci	tst_require_root();
218f08c3bdfSopenharmony_ci	TEST(tst_syscall(__NR_migrate_pages, 0, 0, NULL, NULL));
219f08c3bdfSopenharmony_ci
220f08c3bdfSopenharmony_ci	if (!is_numa(NULL, NH_MEMS, 1))
221f08c3bdfSopenharmony_ci		tst_brkm(TCONF, NULL, "requires NUMA with at least 1 node");
222f08c3bdfSopenharmony_ci
223f08c3bdfSopenharmony_ci	ret = get_allowed_nodes(NH_MEMS, 1, &node);
224f08c3bdfSopenharmony_ci	if (ret < 0)
225f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, NULL, "get_allowed_nodes_arr: %d",
226f08c3bdfSopenharmony_ci			 ret);
227f08c3bdfSopenharmony_ci
228f08c3bdfSopenharmony_ci	sane_max_node = LTP_ALIGN(get_max_node(), sizeof(unsigned long)*8);
229f08c3bdfSopenharmony_ci	sane_nodemask_size = sane_max_node / 8;
230f08c3bdfSopenharmony_ci	sane_old_nodes = SAFE_MALLOC(NULL, sane_nodemask_size);
231f08c3bdfSopenharmony_ci	sane_new_nodes = SAFE_MALLOC(NULL, sane_nodemask_size);
232f08c3bdfSopenharmony_ci	memset(sane_old_nodes, 0, sane_nodemask_size);
233f08c3bdfSopenharmony_ci	memset(sane_new_nodes, 0, sane_nodemask_size);
234f08c3bdfSopenharmony_ci
235f08c3bdfSopenharmony_ci	set_bit(sane_old_nodes, node, 1);
236f08c3bdfSopenharmony_ci	set_bit(sane_new_nodes, node, 1);
237f08c3bdfSopenharmony_ci
238f08c3bdfSopenharmony_ci	TEST_PAUSE;
239f08c3bdfSopenharmony_ci}
240f08c3bdfSopenharmony_ci
241f08c3bdfSopenharmony_cistatic void cleanup(void)
242f08c3bdfSopenharmony_ci{
243f08c3bdfSopenharmony_ci	free(sane_old_nodes);
244f08c3bdfSopenharmony_ci	free(sane_new_nodes);
245f08c3bdfSopenharmony_ci}
246f08c3bdfSopenharmony_ci
247f08c3bdfSopenharmony_ci#else
248f08c3bdfSopenharmony_ciint main(void)
249f08c3bdfSopenharmony_ci{
250f08c3bdfSopenharmony_ci	tst_brkm(TCONF, NULL, NUMA_ERROR_MSG);
251f08c3bdfSopenharmony_ci}
252f08c3bdfSopenharmony_ci#endif
253