cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}