1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 /*
3 * Copyright (C) 2008 David Gibson, IBM Corporation.
4 * Author: David Gibson
5 */
6
7 /*\
8 * [Description]
9 *
10 * This checks copy-on-write semantics, specifically the semantics of a
11 * MAP_PRIVATE mapping across a fork(). Some versions of the powerpc
12 * kernel had a bug in huge_ptep_set_wrprotect() which would fail to
13 * flush the hash table after setting the write protect bit in the parent's
14 * page tables, thus allowing the parent to pollute the child's mapping.
15 *
16 */
17
18 #include <sys/wait.h>
19 #include <sys/mman.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23
24 #include "hugetlb.h"
25
26 #define C1 0x1234ABCD
27 #define C2 ~0x1234ABCD
28 #define C3 0xfeef5678
29 #define MNTPOINT "hugetlbfs/"
30 static int fd = -1;
31 static long hpage_size;
32
run_test(void)33 static void run_test(void)
34 {
35 volatile unsigned int *p;
36 int parent_readback;
37 pid_t pid;
38
39 p = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
40 *p = C1;
41
42 pid = SAFE_FORK();
43 if (pid != 0) {
44 *p = C2;
45 TST_CHECKPOINT_WAKE_AND_WAIT(0);
46 parent_readback = *p;
47 TST_CHECKPOINT_WAKE(0);
48 } else {
49 unsigned int child_readback = 0;
50
51 TST_CHECKPOINT_WAIT(0);
52 child_readback = *p;
53 *p = C3;
54 TST_CHECKPOINT_WAKE_AND_WAIT(0);
55 TST_EXP_EXPR(child_readback == C1, "0x%x == child_readback (0x%x)",
56 C1, child_readback);
57 exit(0);
58 }
59 tst_reap_children();
60 TST_EXP_EXPR(parent_readback == C2, "0x%x == parent_readback (0x%x)",
61 C2, parent_readback);
62
63 SAFE_MUNMAP((void *)p, hpage_size);
64 }
65
setup(void)66 static void setup(void)
67 {
68 hpage_size = SAFE_READ_MEMINFO("Hugepagesize:")*1024;
69 fd = tst_creat_unlinked(MNTPOINT, 0);
70 }
71
cleanup(void)72 static void cleanup(void)
73 {
74 if (fd > 0)
75 SAFE_CLOSE(fd);
76 }
77
78 static struct tst_test test = {
79 .tags = (struct tst_tag[]) {
80 {"linux-git", "86df86424939"},
81 {}
82 },
83 .needs_root = 1,
84 .needs_checkpoints = 1,
85 .mntpoint = MNTPOINT,
86 .needs_hugetlbfs = 1,
87 .forks_child = 1,
88 .setup = setup,
89 .cleanup = cleanup,
90 .test_all = run_test,
91 .hugepages = {2, TST_NEEDS},
92 };
93