0001
0002
0003
0004
0005
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
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 }