// SPDX-License-Identifier: LGPL-2.1-or-later /* * Copyright (C) 2008 David Gibson, IBM Corporation. * Author: David Gibson */ /*\ * [Description] * * This checks copy-on-write semantics, specifically the semantics of a * MAP_PRIVATE mapping across a fork(). Some versions of the powerpc * kernel had a bug in huge_ptep_set_wrprotect() which would fail to * flush the hash table after setting the write protect bit in the parent's * page tables, thus allowing the parent to pollute the child's mapping. * */ #include #include #include #include #include #include "hugetlb.h" #define C1 0x1234ABCD #define C2 ~0x1234ABCD #define C3 0xfeef5678 #define MNTPOINT "hugetlbfs/" static int fd = -1; static long hpage_size; static void run_test(void) { volatile unsigned int *p; int parent_readback; pid_t pid; p = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); *p = C1; pid = SAFE_FORK(); if (pid != 0) { *p = C2; TST_CHECKPOINT_WAKE_AND_WAIT(0); parent_readback = *p; TST_CHECKPOINT_WAKE(0); } else { unsigned int child_readback = 0; TST_CHECKPOINT_WAIT(0); child_readback = *p; *p = C3; TST_CHECKPOINT_WAKE_AND_WAIT(0); TST_EXP_EXPR(child_readback == C1, "0x%x == child_readback (0x%x)", C1, child_readback); exit(0); } tst_reap_children(); TST_EXP_EXPR(parent_readback == C2, "0x%x == parent_readback (0x%x)", C2, parent_readback); SAFE_MUNMAP((void *)p, hpage_size); } static void setup(void) { hpage_size = SAFE_READ_MEMINFO("Hugepagesize:")*1024; 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", "86df86424939"}, {} }, .needs_root = 1, .needs_checkpoints = 1, .mntpoint = MNTPOINT, .needs_hugetlbfs = 1, .forks_child = 1, .setup = setup, .cleanup = cleanup, .test_all = run_test, .hugepages = {2, TST_NEEDS}, };