xref: /aosp_15_r20/external/ltp/testcases/kernel/mem/hugetlb/hugemmap/hugemmap18.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 /*
3  * Copyright (C) 2005-2007 David Gibson & Adam Litke, IBM Corporation.
4  * Author: David Gibson & Adam Litke
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Just as normal mmap()s can't have an address, length or offset which
11  * is not page aligned, so hugepage mmap()s can't have an address, length
12  * or offset with is not hugepage aligned.
13  *
14  * However, from time to time when the various mmap() /
15  * get_unmapped_area() paths are updated, somebody misses one of the
16  * necessary checks for the hugepage paths.  This testcase ensures
17  * that attempted hugepage mappings with parameters which are not
18  * correctly hugepage aligned are rejected.
19  *
20  * However starting with 3.10-rc1, length passed in mmap() doesn't need
21  * to be aligned because commit af73e4d9506d3b797509f3c030e7dcd554f7d9c4
22  * added ALIGN() to kernel side, in mmap_pgoff(), when mapping huge page
23  * files.
24  */
25 
26 #define _GNU_SOURCE
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <sys/mman.h>
30 
31 #include "hugetlb.h"
32 
33 #define MNTPOINT "hugetlbfs/"
34 static long hpage_size;
35 static int  fd = -1;
36 static long page_size;
37 
run_test(void)38 static void run_test(void)
39 {
40 	void *p, *q;
41 
42 	/*
43 	 * First see what an ok mapping looks like, as a basis for our
44 	 * bad addresses and so forth
45 	 */
46 	p = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
47 	if (p == MAP_FAILED) {
48 		tst_res(TFAIL|TERRNO, "mmap() without hint failed");
49 		return;
50 	}
51 	if (((unsigned long)p % hpage_size) != 0) {
52 		tst_res(TFAIL, "mmap() without hint at misaligned address");
53 		goto cleanup1;
54 	}
55 
56 	tst_res(TINFO, "Mapped at %p, length 0x%lx", p, hpage_size);
57 
58 	SAFE_MUNMAP(p, hpage_size);
59 
60 	/* 1) Try a misaligned hint address */
61 	q = mmap(p + page_size, hpage_size, PROT_READ|PROT_WRITE,
62 		 MAP_PRIVATE, fd, 0);
63 	if (q == MAP_FAILED) {
64 		/* Bad hint shouldn't fail, just ignore the hint */
65 		tst_res(TFAIL|TERRNO, "mmap() with hint failed");
66 		return;
67 	}
68 	if (((unsigned long)q % hpage_size) != 0) {
69 		tst_res(TFAIL, "mmap() with hint at misaligned address");
70 		goto cleanup2;
71 	}
72 	SAFE_MUNMAP(q, hpage_size);
73 
74 	/* 2) Try a misaligned address with MAP_FIXED */
75 	q = mmap(p + page_size, hpage_size, PROT_READ|PROT_WRITE,
76 		 MAP_PRIVATE|MAP_FIXED, fd, 0);
77 	if (q != MAP_FAILED) {
78 		tst_res(TFAIL, "mmap() MAP_FIXED at misaligned address succeeded");
79 		goto cleanup2;
80 	}
81 
82 	/* 3) Try a misaligned length */
83 	q = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
84 	if (q == MAP_FAILED) {
85 		tst_res(TFAIL, "mmap() with misaligned length 0x%lx failed",
86 			page_size);
87 		return;
88 	}
89 	SAFE_MUNMAP(q, hpage_size);
90 
91 	/* 4) Try a misaligned length with MAP_FIXED */
92 	q = mmap(p, page_size, PROT_READ|PROT_WRITE,
93 			MAP_PRIVATE|MAP_FIXED, fd, 0);
94 	if (q == MAP_FAILED) {
95 		tst_res(TFAIL, "mmap() MAP_FIXED with misaligned length 0x%lx "
96 			"failed", page_size);
97 		return;
98 	}
99 	SAFE_MUNMAP(q, hpage_size);
100 
101 	/* 5) Try a misaligned offset */
102 	q = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE,
103 		 MAP_PRIVATE, fd, page_size);
104 	if (q != MAP_FAILED) {
105 		tst_res(TFAIL, "mmap() with misaligned offset 0x%lx succeeded",
106 		     page_size);
107 		goto cleanup2;
108 	}
109 
110 	/* 6) Try a misaligned offset with MAP_FIXED*/
111 	q = mmap(p, hpage_size, PROT_READ|PROT_WRITE,
112 		 MAP_PRIVATE|MAP_FIXED, fd, page_size);
113 	if (q != MAP_FAILED) {
114 		tst_res(TFAIL, "mmap() MAP_FIXED with misaligned offset 0x%lx succeeded",
115 		     page_size);
116 		goto cleanup2;
117 	}
118 
119 	tst_res(TPASS, "mmap worked as expected with misaligned addr and length");
120 	return;
121 cleanup2:
122 	SAFE_MUNMAP(q, hpage_size);
123 	return;
124 cleanup1:
125 	SAFE_MUNMAP(p, hpage_size);
126 }
127 
setup(void)128 static void setup(void)
129 {
130 	hpage_size = SAFE_READ_MEMINFO("Hugepagesize:")*1024;
131 	page_size = getpagesize();
132 	fd = tst_creat_unlinked(MNTPOINT, 0);
133 }
134 
cleanup(void)135 static void cleanup(void)
136 {
137 	if (fd >= 0)
138 		SAFE_CLOSE(fd);
139 }
140 
141 static struct tst_test test = {
142 	.tags = (struct tst_tag[]) {
143 		{"linux-git", "af73e4d9506d"},
144 		{}
145 	},
146 	.needs_root = 1,
147 	.mntpoint = MNTPOINT,
148 	.needs_hugetlbfs = 1,
149 	.setup = setup,
150 	.cleanup = cleanup,
151 	.test_all = run_test,
152 	.hugepages = {4, TST_NEEDS},
153 };
154