"Fossies" - the Fresh Open Source Software Archive

Member "libressl-2.9.2/tests/arc4randomforktest.c" (14 Nov 2017, 3861 Bytes) of package /linux/misc/libressl-2.9.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  * Copyright (c) 2014 Google Inc.
    3  *
    4  * Permission to use, copy, modify, and distribute this software for any
    5  * purpose with or without fee is hereby granted, provided that the above
    6  * copyright notice and this permission notice appear in all copies.
    7  *
    8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   15  */
   16 
   17 #include <sys/mman.h>
   18 #include <sys/wait.h>
   19 #include <assert.h>
   20 #include <err.h>
   21 #include <errno.h>
   22 #include <signal.h>
   23 #include <stdlib.h>
   24 #include <string.h>
   25 #include <unistd.h>
   26 #include <stdint.h>
   27 
   28 #define CHECK(x) assert(x)
   29 #define CHECK_EQ(a, b) assert((a) == (b))
   30 #define CHECK_NE(a, b) assert((a) != (b))
   31 #define CHECK_GE(a, b) assert((a) >= (b))
   32 #define CHECK_LE(a, b) assert((a) <= (b))
   33 
   34 /* Test arc4random_buf(3) instead of arc4random(3). */
   35 static int flagbuf;
   36 
   37 /* Initialize arc4random(3) before forking. */
   38 static int flagprefork;
   39 
   40 enum {
   41     N = 4096
   42 };
   43 
   44 typedef struct {
   45     uint32_t x[N];
   46 } Buf;
   47 
   48 static int
   49 isfullbuf(const Buf *buf)
   50 {
   51     size_t i;
   52     for (i = 0; i < N; i++)
   53         if (buf->x[i])
   54             return (1);
   55     return (0);
   56 }
   57 
   58 static void
   59 fillbuf(Buf *buf)
   60 {
   61     if (flagbuf) {
   62         arc4random_buf(buf->x, sizeof(buf->x));
   63     } else {
   64         size_t i;
   65         for (i = 0; i < N; i++)
   66             buf->x[i] = arc4random();
   67     }
   68 }
   69 
   70 static void
   71 usage()
   72 {
   73     errx(1, "usage: arc4random-fork [-bp]");
   74 }
   75 
   76 static pid_t
   77 safewaitpid(pid_t pid, int *status, int options)
   78 {
   79     pid_t ret;
   80     do {
   81         ret = waitpid(pid, status, options);
   82     } while (ret == -1 && errno == EINTR);
   83     return (ret);
   84 }
   85 
   86 int
   87 main(int argc, char *argv[])
   88 {
   89     int opt, status;
   90     Buf *bufparent, *bufchildone, *bufchildtwo;
   91     pid_t pidone, pidtwo;
   92     size_t i, countone = 0, counttwo = 0, countkids = 0;
   93 
   94     /* Ensure SIGCHLD isn't set to SIG_IGN. */
   95     const struct sigaction sa = {
   96         .sa_handler = SIG_DFL,
   97     };
   98     CHECK_EQ(0, sigaction(SIGCHLD, &sa, NULL));
   99 
  100     while ((opt = getopt(argc, argv, "bp")) != -1) {
  101         switch (opt) {
  102         case 'b':
  103             flagbuf = 1;
  104             break;
  105         case 'p':
  106             flagprefork = 1;
  107             break;
  108         default:
  109             usage();
  110         }
  111     }
  112 
  113     if (flagprefork)
  114         arc4random();
  115 
  116     bufparent = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
  117         MAP_ANON|MAP_PRIVATE, -1, 0);
  118     CHECK_NE(MAP_FAILED, bufparent);
  119 
  120     bufchildone = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
  121         MAP_ANON|MAP_SHARED, -1, 0);
  122     CHECK_NE(MAP_FAILED, bufchildone);
  123 
  124     bufchildtwo = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
  125         MAP_ANON|MAP_SHARED, -1, 0);
  126     CHECK_NE(MAP_FAILED, bufchildtwo);
  127 
  128     pidone = fork();
  129     CHECK_GE(pidone, 0);
  130     if (pidone == 0) {
  131         fillbuf(bufchildone);
  132         _exit(0);
  133     }
  134 
  135     pidtwo = fork();
  136     CHECK_GE(pidtwo, 0);
  137     if (pidtwo == 0) {
  138         fillbuf(bufchildtwo);
  139         _exit(0);
  140     }
  141 
  142     fillbuf(bufparent);
  143 
  144     CHECK_EQ(pidone, safewaitpid(pidone, &status, 0));
  145     CHECK(WIFEXITED(status));
  146     CHECK_EQ(0, WEXITSTATUS(status));
  147 
  148     CHECK_EQ(pidtwo, safewaitpid(pidtwo, &status, 0));
  149     CHECK(WIFEXITED(status));
  150     CHECK_EQ(0, WEXITSTATUS(status));
  151 
  152     CHECK(isfullbuf(bufchildone));
  153     CHECK(isfullbuf(bufchildtwo));
  154 
  155     for (i = 0; i < N; i++) {
  156         countone += bufparent->x[i] == bufchildone->x[i];
  157         counttwo += bufparent->x[i] == bufchildtwo->x[i];
  158         countkids += bufchildone->x[i] == bufchildtwo->x[i];
  159     }
  160 
  161     /*
  162      * These checks are inherently probabilistic and theoretically risk
  163      * flaking, but there's less than a 1 in 2^40 chance of more than
  164      * one pairwise match between two vectors of 4096 32-bit integers.
  165      */
  166     CHECK_LE(countone, 1);
  167     CHECK_LE(counttwo, 1);
  168     CHECK_LE(countkids, 1);
  169 
  170     return (0);
  171 }