154 lines
3.9 KiB
C
154 lines
3.9 KiB
C
// 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/mman.h>
|
|
|
|
#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},
|
|
};
|