unplugged-system/external/ltp/testcases/kernel/mem/hugetlb/hugemmap/hugemmap18.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},
};