diff mbox series

[7/8] Hugetlb: Migrating libhugetlbfs misalign

Message ID 20221201120248.139396-8-tsahu@linux.ibm.com
State Superseded
Headers show
Series Hugetlb:Migrating the libhugetlbfs tests | expand

Commit Message

Tarun Sahu Dec. 1, 2022, 12:02 p.m. UTC
Migrating the libhugetlbfs/testcases/misalign.c test

Test 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 af73e4d9506d
("hugetlbfs: fix mmap failure in unaligned size request")' added ALIGN()
to kernel side, in mmap_pgoff(), when mapping huge page files.

Signed-off-by: Tarun Sahu <tsahu@linux.ibm.com>
---
 runtest/hugetlb                               |   1 +
 testcases/kernel/mem/.gitignore               |   1 +
 .../kernel/mem/hugetlb/hugemmap/hugemmap18.c  | 153 ++++++++++++++++++
 3 files changed, 155 insertions(+)
 create mode 100644 testcases/kernel/mem/hugetlb/hugemmap/hugemmap18.c
diff mbox series

Patch

diff --git a/runtest/hugetlb b/runtest/hugetlb
index 5fac3481c..de76cdaf2 100644
--- a/runtest/hugetlb
+++ b/runtest/hugetlb
@@ -19,6 +19,7 @@  hugemmap14 hugemmap14
 hugemmap15 hugemmap15
 hugemmap16 hugemmap16
 hugemmap17 hugemmap17
+hugemmap18 hugemmap18
 hugemmap05_1 hugemmap05 -m
 hugemmap05_2 hugemmap05 -s
 hugemmap05_3 hugemmap05 -s -m
diff --git a/testcases/kernel/mem/.gitignore b/testcases/kernel/mem/.gitignore
index 6aa54f902..daee70586 100644
--- a/testcases/kernel/mem/.gitignore
+++ b/testcases/kernel/mem/.gitignore
@@ -18,6 +18,7 @@ 
 /hugetlb/hugemmap/hugemmap15
 /hugetlb/hugemmap/hugemmap16
 /hugetlb/hugemmap/hugemmap17
+/hugetlb/hugemmap/hugemmap18
 /hugetlb/hugeshmat/hugeshmat01
 /hugetlb/hugeshmat/hugeshmat02
 /hugetlb/hugeshmat/hugeshmat03
diff --git a/testcases/kernel/mem/hugetlb/hugemmap/hugemmap18.c b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap18.c
new file mode 100644
index 000000000..607072937
--- /dev/null
+++ b/testcases/kernel/mem/hugetlb/hugemmap/hugemmap18.c
@@ -0,0 +1,153 @@ 
+// 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},
+};