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/" 34static long hpage_size; 35static int fd = -1; 36static long page_size; 37 38static 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; 121cleanup2: 122 SAFE_MUNMAP(q, hpage_size); 123 return; 124cleanup1: 125 SAFE_MUNMAP(p, hpage_size); 126} 127 128static 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 135static void cleanup(void) 136{ 137 if (fd >= 0) 138 SAFE_CLOSE(fd); 139} 140 141static 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