Mail archive
alpine-user

Re: [alpine-user] Startup hangs (aports: sshd?)

From: Steffen Nurpmeso <steffen_at_sdaoden.eu>
Date: Mon, 21 Jan 2019 22:00:48 +0100

Steffen Nurpmeso wrote in <20190118230012.3me-O%steffen_at_sdaoden.eu>:
  ...
 |Anyway, i have written something that saves entropy in a file and
 |fills it in via ioctl(2), the stuff goes
 |
 | #?0|essex:tmp$ ./zt save /tmp/t.dat
 | - 3420 bits of entropy available at /dev/random
 | - 2396 bits of entropy remain at /dev/random
 | - 1024 bits / 115 bytes of entropy saved to /tmp/t.dat
 |...
 | #?0|essex:/etc/init.d# /tmp/zt load /tmp/t.dat
 | - 2631 bits of entropy available at /dev/random
 | - 115 bytes / 1024 bits of entropy read from /tmp/t.dat
 | - Entropy added
 | - 2905 bits of entropy are at at /dev/random
 |
 |So call this two hour hack stupid, but i will use it.

Because i have posted it, please let me post an update which will
read more bytes than the latter, as many as possible above some
treshold etc. (since the program is meant as a pool server, say).
My notebook booted without any hang today! And if people can
access the hardware / mount the device, well, in my case (no
crypto all-through) they could change the kernel or whatever.
Ciao!

/*_at_ Save and load Linux (2.6.0+) entropy.
 *_at_ Different to "cat XY > /dev/urandom" this increments "entropy_avail".
 *_at_ Synopsis: entropy-saver save [file]
 *_at_ Synopsis: entropy-saver load [file]
 *_at_ "file" defaults to a_RAND_FILE_STORE.
 *
 * 2019 Steffen (Daode) Nurpmeso <steffen_at_sdaoden.eu>.
 * Public Domain
 */

/* Random device*/
#define a_RAND_DEV "/dev/random"

/* Maximum number of bytes we handle (must be LT INT_MAX/8!) */
#define a_RAND_NO_BYTES 512

/* When saving, the minimum number of entropy_avail we keep in the pool.
 * _This_ is checked after we have read once (512 we test initially).
 * We will refuse to save a dump which offers less than 128 bits. */
#define a_RAND_ENTROPY_COUNT_MIN 1024

/* Default storage */
#define a_RAND_FILE_STORE "/var/lib/misc/random.dat"

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>

#include <linux/random.h>
#include <linux/version.h>

#if KERNEL_VERSION(2,6,0) >= LINUX_VERSION_CODE
# error Linux kernel version and IOCTL usage incompatible.
#endif

static char const a_rand_file_store[] = a_RAND_FILE_STORE;

int
main(int argc, char **argv){
   enum {a_LOAD, a_SAVE};

   struct{
      struct rand_pool_info rpi;
      char buf[a_RAND_NO_BYTES];
   } x;
   char *rpibuf; /* To make C++ happy: rpi.buf is char[0] */
   ssize_t len;
   char const *store;
   int rv, accu, randfd, storfd, iocarg;

   /* Command line handling */
   if(argc < 2 || argc > 3)
      goto jeuse;

   if(!strcmp(argv[1], "load"))
      accu = a_LOAD;
   else if(!strcmp(argv[1], "save"))
      accu = a_SAVE;
   else{
jeuse:
      fprintf(stderr,
         "Synopsis: entropy-saver save [storage-file]\n"
         "Synopsis: entropy-saver load [storage-file]\n"
         "\n"
         "storage-file defaults to " a_RAND_FILE_STORE "\n"
         "Exit: sysexits.h: EX_USAGE, EX_NOPERM, EX_IOERR, EX_TEMPFAIL\n");
      rv = EX_USAGE;
      goto jleave;
   }

   /* Open our two files according to chosen action */
   randfd = open(a_RAND_DEV, (O_RDONLY | O_NONBLOCK));
   if(randfd == -1){
      accu = errno;
      fprintf(stderr, "Failed to open " a_RAND_DEV ": %s\n",
         strerror(accu));
      rv = (accu == EACCES || accu == EPERM) ? EX_NOPERM : EX_IOERR;
      goto jleave;
   }

   store = (argv[2] != NULL) ? argv[2] : a_rand_file_store;
   storfd = open(store, (accu == a_LOAD ? O_RDONLY
         : O_WRONLY | O_CREAT | O_TRUNC), (S_IRUSR | S_IWUSR));
   if(storfd == -1){
      accu = errno;
      fprintf(stderr, "Failed to open %s: %s\n", store, strerror(accu));
      rv = (accu == EACCES || accu == EPERM) ? EX_NOPERM : EX_IOERR;
      goto jerr1;
   }

   /* For at least statistics query entropy count once */
   rv = ioctl(randfd, (int)RNDGETENTCNT, &iocarg);
   if(rv == -1){
      fprintf(stderr, "Failed to query available entropy of " a_RAND_DEV
         ": %s\n", strerror(errno));
      rv = EX_IOERR;
      goto jerr2;
   }
   x.rpi.entropy_count = iocarg;

   rpibuf = (char*)x.rpi.buf;

   if(accu == a_LOAD){
      printf("- %d bits of entropy available at " a_RAND_DEV "\n",
         x.rpi.entropy_count);

      /* INT: entropy bits */
      len = read(storfd, &x.rpi.entropy_count, sizeof x.rpi.entropy_count);
      if(len == -1){
         fprintf(stderr, "Failed to read from %s: %s\n",
            store, strerror(errno));
         rv = EX_IOERR;
         goto jerr2;
      }
      if(len != sizeof x.rpi.entropy_count){
         fprintf(stderr, "Storage %s: seems corrupted (false format)\n",
            store);
         rv = EX_IOERR;
         goto jerr2;
      }
      /* The former because we will refuse to save less than that, the latter
       * rather arbitrary (like the suff as such?) */
      if(x.rpi.entropy_count < 128 || x.rpi.entropy_count > 1000000){
         fprintf(stderr, "Storage %s seems corrupted (%d entropy bits)\n",
            store, x.rpi.entropy_count);
         rv = EX_IOERR;
         goto jerr2;
      }

      /* REST: pool bytes */
      len = read(storfd, rpibuf, sizeof x.buf);
      if(len == -1){
         fprintf(stderr, "Failed to read from %s: %s\n",
            store, strerror(errno));
         rv = EX_IOERR;
         goto jerr2;
      }
      if(len == 0){
         fprintf(stderr, "Storage %s: seems corrupted (no entropy)\n",
            store);
         rv = EX_TEMPFAIL;
         goto jerr2;
      }
      x.rpi.buf_size = (int)len;

      if(read(storfd, &accu, 1) != 0){
         fprintf(stderr, "Storage %s: seems corrupted (no EOF seen)\n",
            store);
         rv = EX_IOERR;
         goto jerr2;
      }

      printf("- %d bytes / %d bits of entropy read from %s\n",
         x.rpi.buf_size, x.rpi.entropy_count, store);

      accu = ioctl(randfd, RNDADDENTROPY, &x.rpi);
      if(accu == -1){
         fprintf(stderr, "Failed to add %d bits of entropy to " a_RAND_DEV
            ": %s\n", x.rpi.entropy_count, strerror(errno));
         rv = EX_IOERR;
         goto jerr2;
      }

      /* For at least statistics */
      rv = ioctl(randfd, (int)RNDGETENTCNT, &iocarg);
      if(rv != -1)
         printf("- %d bits of entropy are at at " a_RAND_DEV "\n", iocarg);
   }else{
      /* Since we are reading in non-blocking mode, and since reading from
       * /dev/random returns not that much in this mode, read in a loop until
       * it no longer serves / the entropy count falls under a a_RAND_ */
      size_t rem_size;
      int entrop_cnt;

      entrop_cnt = x.rpi.entropy_count;
      printf("- %d bits of entropy available at " a_RAND_DEV "%s\n",
         entrop_cnt, (entrop_cnt <= 512 ? ": temporary failure" : ""));
      if(entrop_cnt <= 512){
         rv = EX_TEMPFAIL;
         goto jerr2;
      }

      x.rpi.buf_size = x.rpi.entropy_count = 0;
      rem_size = sizeof x.buf;
jread_more:
      len = read(randfd, rpibuf, rem_size);
      if(len == -1){
         /* Ignore the EAGAIN that /dev/random reports when it would block
          * (Bernd Petrovitsch (bernd at petrovitsch dot priv dot at)) */
         if(errno == EAGAIN)
            goto jread_done;

         fprintf(stderr, "Failed to read from " a_RAND_DEV ": %s\n",
            strerror(errno));
         rv = EX_IOERR;
         goto jerr2;
      }
      x.rpi.buf_size += (int)len;
      rpibuf += len;
      rem_size -= len;

      rv = ioctl(randfd, (int)RNDGETENTCNT, &iocarg);
      if(rv == -1){
         fprintf(stderr, "Failed to query remaining entropy of " a_RAND_DEV
            ": %s\n", strerror(errno));
         rv = EX_IOERR;
         goto jerr2;
      }
      entrop_cnt -= iocarg;
      x.rpi.entropy_count += entrop_cnt;

      /* Try to read more? */
      if(len > 0 && (entrop_cnt = iocarg) >= a_RAND_ENTROPY_COUNT_MIN &&
            rem_size >= 64)
         goto jread_more;
      printf("- %d bits of entropy remain at " a_RAND_DEV "\n", iocarg);

jread_done:
      if(x.rpi.entropy_count <= 128){
         fprintf(stderr, "Insufficient entropy to save from " a_RAND_DEV
            " (%d bits)\n", x.rpi.entropy_count);
         rv = EX_TEMPFAIL;
         goto jerr2;
      }

      rpibuf = (char*)x.rpi.buf;
      len = x.rpi.buf_size;
      if((ssize_t)sizeof(x.rpi.entropy_count) != write(storfd,
               &x.rpi.entropy_count, sizeof x.rpi.entropy_count) ||
            len != write(storfd, rpibuf, len)){
         fprintf(stderr, "Failed to write to %s: %s\n",
            store, strerror(errno));
         rv = EX_IOERR;
         goto jerr2;
      }

      printf("- %d bits / %d bytes of entropy saved to %s\n",
         x.rpi.entropy_count, x.rpi.buf_size, store);
   }

   rv = 0;
jerr2:
   if(close(storfd) == -1)
      fprintf(stderr, "Error closing %s: %s\n", store, strerror(errno));
jerr1:
   if(close(randfd) == -1)
      fprintf(stderr, "Error closing " a_RAND_DEV ": %s\n",
         strerror(errno));
jleave:
   return rv;
}

/* s-it-mode */

--steffen
|
|Der Kragenbaer, The moon bear,
|der holt sich munter he cheerfully and one by one
|einen nach dem anderen runter wa.ks himself off
|(By Robert Gernhardt)


---
Unsubscribe:  alpine-user+unsubscribe_at_lists.alpinelinux.org
Help:         alpine-user+help_at_lists.alpinelinux.org
---
Received on Mon Jan 21 2019 - 22:00:48 UTC