// SPDX-License-Identifier: LGPL-2.1-or-later /* * Copyright (C) 2005-2007 David Gibson & Adam Litke, IBM Corporation. * Author: David Gibson & Adam Litke */ /*\ * [Description] * * Just as normal mmap()s can't have an address, length or offset which * is not page aligned, so hugepage mmap()s can't have an address, length * or offset with is not hugepage aligned. * * However, from time to time when the various mmap() / * get_unmapped_area() paths are updated, somebody misses one of the * necessary checks for the hugepage paths. This testcase ensures * that attempted hugepage mappings with parameters which are not * correctly hugepage aligned are rejected. * * However starting with 3.10-rc1, length passed in mmap() doesn't need * to be aligned because commit af73e4d9506d3b797509f3c030e7dcd554f7d9c4 * added ALIGN() to kernel side, in mmap_pgoff(), when mapping huge page * files. */ #define _GNU_SOURCE #include #include #include #include "hugetlb.h" #define MNTPOINT "hugetlbfs/" static long hpage_size; static int fd = -1; static long page_size; static void run_test(void) { void *p, *q; /* * First see what an ok mapping looks like, as a basis for our * bad addresses and so forth */ p = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); if (p == MAP_FAILED) { tst_res(TFAIL|TERRNO, "mmap() without hint failed"); return; } if (((unsigned long)p % hpage_size) != 0) { tst_res(TFAIL, "mmap() without hint at misaligned address"); goto cleanup1; } tst_res(TINFO, "Mapped at %p, length 0x%lx", p, hpage_size); SAFE_MUNMAP(p, hpage_size); /* 1) Try a misaligned hint address */ q = mmap(p + page_size, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); if (q == MAP_FAILED) { /* Bad hint shouldn't fail, just ignore the hint */ tst_res(TFAIL|TERRNO, "mmap() with hint failed"); return; } if (((unsigned long)q % hpage_size) != 0) { tst_res(TFAIL, "mmap() with hint at misaligned address"); goto cleanup2; } SAFE_MUNMAP(q, hpage_size); /* 2) Try a misaligned address with MAP_FIXED */ q = mmap(p + page_size, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, fd, 0); if (q != MAP_FAILED) { tst_res(TFAIL, "mmap() MAP_FIXED at misaligned address succeeded"); goto cleanup2; } /* 3) Try a misaligned length */ q = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); if (q == MAP_FAILED) { tst_res(TFAIL, "mmap() with misaligned length 0x%lx failed", page_size); return; } SAFE_MUNMAP(q, hpage_size); /* 4) Try a misaligned length with MAP_FIXED */ q = mmap(p, page_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, fd, 0); if (q == MAP_FAILED) { tst_res(TFAIL, "mmap() MAP_FIXED with misaligned length 0x%lx " "failed", page_size); return; } SAFE_MUNMAP(q, hpage_size); /* 5) Try a misaligned offset */ q = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, page_size); if (q != MAP_FAILED) { tst_res(TFAIL, "mmap() with misaligned offset 0x%lx succeeded", page_size); goto cleanup2; } /* 6) Try a misaligned offset with MAP_FIXED*/ q = mmap(p, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, fd, page_size); if (q != MAP_FAILED) { tst_res(TFAIL, "mmap() MAP_FIXED with misaligned offset 0x%lx succeeded", page_size); goto cleanup2; } tst_res(TPASS, "mmap worked as expected with misaligned addr and length"); return; cleanup2: SAFE_MUNMAP(q, hpage_size); return; cleanup1: SAFE_MUNMAP(p, hpage_size); } static void setup(void) { hpage_size = SAFE_READ_MEMINFO("Hugepagesize:")*1024; page_size = getpagesize(); fd = tst_creat_unlinked(MNTPOINT, 0); } static void cleanup(void) { if (fd >= 0) SAFE_CLOSE(fd); } static struct tst_test test = { .tags = (struct tst_tag[]) { {"linux-git", "af73e4d9506d"}, {} }, .needs_root = 1, .mntpoint = MNTPOINT, .needs_hugetlbfs = 1, .setup = setup, .cleanup = cleanup, .test_all = run_test, .hugepages = {4, TST_NEEDS}, };