Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2018 Dmitry Safonov, Arista Networks
0004  *
0005  * MAP_POPULATE | MAP_PRIVATE should COW VMA pages.
0006  */
0007 
0008 #define _GNU_SOURCE
0009 #include <errno.h>
0010 #include <fcntl.h>
0011 #include <sys/mman.h>
0012 #include <sys/socket.h>
0013 #include <sys/types.h>
0014 #include <sys/wait.h>
0015 #include <stdio.h>
0016 #include <stdlib.h>
0017 #include <string.h>
0018 #include <unistd.h>
0019 
0020 #ifndef MMAP_SZ
0021 #define MMAP_SZ     4096
0022 #endif
0023 
0024 #define BUG_ON(condition, description)                  \
0025     do {                                \
0026         if (condition) {                    \
0027             fprintf(stderr, "[FAIL]\t%s:%d\t%s:%s\n", __func__, \
0028                 __LINE__, (description), strerror(errno)); \
0029             exit(1);                    \
0030         }                           \
0031     } while (0)
0032 
0033 static int parent_f(int sock, unsigned long *smap, int child)
0034 {
0035     int status, ret;
0036 
0037     ret = read(sock, &status, sizeof(int));
0038     BUG_ON(ret <= 0, "read(sock)");
0039 
0040     *smap = 0x22222BAD;
0041     ret = msync(smap, MMAP_SZ, MS_SYNC);
0042     BUG_ON(ret, "msync()");
0043 
0044     ret = write(sock, &status, sizeof(int));
0045     BUG_ON(ret <= 0, "write(sock)");
0046 
0047     waitpid(child, &status, 0);
0048     BUG_ON(!WIFEXITED(status), "child in unexpected state");
0049 
0050     return WEXITSTATUS(status);
0051 }
0052 
0053 static int child_f(int sock, unsigned long *smap, int fd)
0054 {
0055     int ret, buf = 0;
0056 
0057     smap = mmap(0, MMAP_SZ, PROT_READ | PROT_WRITE,
0058             MAP_PRIVATE | MAP_POPULATE, fd, 0);
0059     BUG_ON(smap == MAP_FAILED, "mmap()");
0060 
0061     BUG_ON(*smap != 0xdeadbabe, "MAP_PRIVATE | MAP_POPULATE changed file");
0062 
0063     ret = write(sock, &buf, sizeof(int));
0064     BUG_ON(ret <= 0, "write(sock)");
0065 
0066     ret = read(sock, &buf, sizeof(int));
0067     BUG_ON(ret <= 0, "read(sock)");
0068 
0069     BUG_ON(*smap == 0x22222BAD, "MAP_POPULATE didn't COW private page");
0070     BUG_ON(*smap != 0xdeadbabe, "mapping was corrupted");
0071 
0072     return 0;
0073 }
0074 
0075 int main(int argc, char **argv)
0076 {
0077     int sock[2], child, ret;
0078     FILE *ftmp;
0079     unsigned long *smap;
0080 
0081     ftmp = tmpfile();
0082     BUG_ON(ftmp == 0, "tmpfile()");
0083 
0084     ret = ftruncate(fileno(ftmp), MMAP_SZ);
0085     BUG_ON(ret, "ftruncate()");
0086 
0087     smap = mmap(0, MMAP_SZ, PROT_READ | PROT_WRITE,
0088             MAP_SHARED, fileno(ftmp), 0);
0089     BUG_ON(smap == MAP_FAILED, "mmap()");
0090 
0091     *smap = 0xdeadbabe;
0092     /* Probably unnecessary, but let it be. */
0093     ret = msync(smap, MMAP_SZ, MS_SYNC);
0094     BUG_ON(ret, "msync()");
0095 
0096     ret = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sock);
0097     BUG_ON(ret, "socketpair()");
0098 
0099     child = fork();
0100     BUG_ON(child == -1, "fork()");
0101 
0102     if (child) {
0103         ret = close(sock[0]);
0104         BUG_ON(ret, "close()");
0105 
0106         return parent_f(sock[1], smap, child);
0107     }
0108 
0109     ret = close(sock[1]);
0110     BUG_ON(ret, "close()");
0111 
0112     return child_f(sock[0], smap, fileno(ftmp));
0113 }