Blame src/unix/random-getrandom.c

Packit Service e08953
/* Copyright libuv contributors. All rights reserved.
Packit Service e08953
 *
Packit Service e08953
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit Service e08953
 * of this software and associated documentation files (the "Software"), to
Packit Service e08953
 * deal in the Software without restriction, including without limitation the
Packit Service e08953
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit Service e08953
 * sell copies of the Software, and to permit persons to whom the Software is
Packit Service e08953
 * furnished to do so, subject to the following conditions:
Packit Service e08953
 *
Packit Service e08953
 * The above copyright notice and this permission notice shall be included in
Packit Service e08953
 * all copies or substantial portions of the Software.
Packit Service e08953
 *
Packit Service e08953
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service e08953
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service e08953
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Packit Service e08953
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Packit Service e08953
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Packit Service e08953
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Packit Service e08953
 * IN THE SOFTWARE.
Packit Service e08953
 */
Packit Service e08953
Packit Service e08953
#include "uv.h"
Packit Service e08953
#include "internal.h"
Packit Service e08953
Packit Service e08953
#ifdef __linux__
Packit Service e08953
Packit Service e08953
#include "linux-syscalls.h"
Packit Service e08953
Packit Service e08953
#define uv__random_getrandom_init() 0
Packit Service e08953
Packit Service e08953
#else  /* !__linux__ */
Packit Service e08953
Packit Service e08953
#include <stddef.h>
Packit Service e08953
#include <dlfcn.h>
Packit Service e08953
Packit Service e08953
typedef ssize_t (*uv__getrandom_cb)(void *, size_t, unsigned);
Packit Service e08953
Packit Service e08953
static uv__getrandom_cb uv__getrandom;
Packit Service e08953
static uv_once_t once = UV_ONCE_INIT;
Packit Service e08953
Packit Service e08953
static void uv__random_getrandom_init_once(void) {
Packit Service e08953
  uv__getrandom = (uv__getrandom_cb) dlsym(RTLD_DEFAULT, "getrandom");
Packit Service e08953
}
Packit Service e08953
Packit Service e08953
static int uv__random_getrandom_init(void) {
Packit Service e08953
  uv_once(&once, uv__random_getrandom_init_once);
Packit Service e08953
Packit Service e08953
  if (uv__getrandom == NULL)
Packit Service e08953
    return UV_ENOSYS;
Packit Service e08953
Packit Service e08953
  return 0;
Packit Service e08953
}
Packit Service e08953
Packit Service e08953
#endif  /* !__linux__ */
Packit Service e08953
Packit Service e08953
int uv__random_getrandom(void* buf, size_t buflen) {
Packit Service e08953
  ssize_t n;
Packit Service e08953
  size_t pos;
Packit Service e08953
  int rc;
Packit Service e08953
Packit Service e08953
  rc = uv__random_getrandom_init();
Packit Service e08953
  if (rc != 0)
Packit Service e08953
    return rc;
Packit Service e08953
Packit Service e08953
  for (pos = 0; pos != buflen; pos += n) {
Packit Service e08953
    do {
Packit Service e08953
      n = buflen - pos;
Packit Service e08953
Packit Service e08953
      /* Most getrandom() implementations promise that reads <= 256 bytes
Packit Service e08953
       * will always succeed and won't be interrupted by signals.
Packit Service e08953
       * It's therefore useful to split it up in smaller reads because
Packit Service e08953
       * one big read may, in theory, continuously fail with EINTR.
Packit Service e08953
       */
Packit Service e08953
      if (n > 256)
Packit Service e08953
        n = 256;
Packit Service e08953
Packit Service e08953
      n = uv__getrandom((char *) buf + pos, n, 0);
Packit Service e08953
    } while (n == -1 && errno == EINTR);
Packit Service e08953
Packit Service e08953
    if (n == -1)
Packit Service e08953
      return UV__ERR(errno);
Packit Service e08953
Packit Service e08953
    if (n == 0)
Packit Service e08953
      return UV_EIO;
Packit Service e08953
  }
Packit Service e08953
Packit Service e08953
  return 0;
Packit Service e08953
}