large_vm_fork_separation.c (1944B)
1// SPDX-License-Identifier: GPL-2.0+ 2// 3// Copyright 2019, Michael Ellerman, IBM Corp. 4// 5// Test that allocating memory beyond the memory limit and then forking is 6// handled correctly, ie. the child is able to access the mappings beyond the 7// memory limit and the child's writes are not visible to the parent. 8 9#include <stdio.h> 10#include <stdlib.h> 11#include <sys/mman.h> 12#include <sys/types.h> 13#include <sys/wait.h> 14#include <unistd.h> 15 16#include "utils.h" 17 18 19#ifndef MAP_FIXED_NOREPLACE 20#define MAP_FIXED_NOREPLACE MAP_FIXED // "Should be safe" above 512TB 21#endif 22 23 24static int test(void) 25{ 26 int p2c[2], c2p[2], rc, status, c, *p; 27 unsigned long page_size; 28 pid_t pid; 29 30 page_size = sysconf(_SC_PAGESIZE); 31 SKIP_IF(page_size != 65536); 32 33 // Create a mapping at 512TB to allocate an extended_id 34 p = mmap((void *)(512ul << 40), page_size, PROT_READ | PROT_WRITE, 35 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE, -1, 0); 36 if (p == MAP_FAILED) { 37 perror("mmap"); 38 printf("Error: couldn't mmap(), confirm kernel has 4TB support?\n"); 39 return 1; 40 } 41 42 printf("parent writing %p = 1\n", p); 43 *p = 1; 44 45 FAIL_IF(pipe(p2c) == -1 || pipe(c2p) == -1); 46 47 pid = fork(); 48 if (pid == 0) { 49 FAIL_IF(read(p2c[0], &c, 1) != 1); 50 51 pid = getpid(); 52 printf("child writing %p = %d\n", p, pid); 53 *p = pid; 54 55 FAIL_IF(write(c2p[1], &c, 1) != 1); 56 FAIL_IF(read(p2c[0], &c, 1) != 1); 57 exit(0); 58 } 59 60 c = 0; 61 FAIL_IF(write(p2c[1], &c, 1) != 1); 62 FAIL_IF(read(c2p[0], &c, 1) != 1); 63 64 // Prevent compiler optimisation 65 barrier(); 66 67 rc = 0; 68 printf("parent reading %p = %d\n", p, *p); 69 if (*p != 1) { 70 printf("Error: BUG! parent saw child's write! *p = %d\n", *p); 71 rc = 1; 72 } 73 74 FAIL_IF(write(p2c[1], &c, 1) != 1); 75 FAIL_IF(waitpid(pid, &status, 0) == -1); 76 FAIL_IF(!WIFEXITED(status) || WEXITSTATUS(status)); 77 78 if (rc == 0) 79 printf("success: test completed OK\n"); 80 81 return rc; 82} 83 84int main(void) 85{ 86 return test_harness(test, "large_vm_fork_separation"); 87}