unix,win: add uv_random()
Add an API for obtaining cryptographically strong random data from the system PRNG. Co-authored-by: Saúl Ibarra Corretgé <s@saghul.net> Refs: https://github.com/libuv/libuv/pull/1055 PR-URL: https://github.com/libuv/libuv/pull/2347 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
parent
fd1502f563
commit
4ed2a78f0e
@ -14,6 +14,7 @@ set(uv_sources
|
|||||||
src/fs-poll.c
|
src/fs-poll.c
|
||||||
src/idna.c
|
src/idna.c
|
||||||
src/inet.c
|
src/inet.c
|
||||||
|
src/random.c
|
||||||
src/strscpy.c
|
src/strscpy.c
|
||||||
src/threadpool.c
|
src/threadpool.c
|
||||||
src/timer.c
|
src/timer.c
|
||||||
@ -108,6 +109,7 @@ set(uv_test_sources
|
|||||||
test/test-process-title-threadsafe.c
|
test/test-process-title-threadsafe.c
|
||||||
test/test-process-title.c
|
test/test-process-title.c
|
||||||
test/test-queue-foreach-delete.c
|
test/test-queue-foreach-delete.c
|
||||||
|
test/test-random.c
|
||||||
test/test-ref.c
|
test/test-ref.c
|
||||||
test/test-run-nowait.c
|
test/test-run-nowait.c
|
||||||
test/test-run-once.c
|
test/test-run-once.c
|
||||||
@ -236,6 +238,7 @@ else()
|
|||||||
src/unix/pipe.c
|
src/unix/pipe.c
|
||||||
src/unix/poll.c
|
src/unix/poll.c
|
||||||
src/unix/process.c
|
src/unix/process.c
|
||||||
|
src/unix/random-devurandom.c
|
||||||
src/unix/signal.c
|
src/unix/signal.c
|
||||||
src/unix/stream.c
|
src/unix/stream.c
|
||||||
src/unix/tcp.c
|
src/unix/tcp.c
|
||||||
@ -284,6 +287,14 @@ if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
|
|||||||
list(APPEND uv_sources src/unix/bsd-ifaddrs.c src/unix/kqueue.c)
|
list(APPEND uv_sources src/unix/bsd-ifaddrs.c src/unix/kqueue.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||||
|
list(APPEND uv_sources src/unix/random-getrandom.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
|
||||||
|
list(APPEND uv_sources src/unix/random-getentropy.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
list(APPEND uv_defines _DARWIN_UNLIMITED_SELECT=1 _DARWIN_USE_64_BIT_INODE=1)
|
list(APPEND uv_defines _DARWIN_UNLIMITED_SELECT=1 _DARWIN_USE_64_BIT_INODE=1)
|
||||||
list(APPEND uv_sources
|
list(APPEND uv_sources
|
||||||
@ -300,6 +311,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|||||||
src/unix/linux-inotify.c
|
src/unix/linux-inotify.c
|
||||||
src/unix/linux-syscalls.c
|
src/unix/linux-syscalls.c
|
||||||
src/unix/procfs-exepath.c
|
src/unix/procfs-exepath.c
|
||||||
|
src/unix/random-getrandom.c
|
||||||
|
src/unix/random-sysctl.c
|
||||||
src/unix/sysinfo-loadavg.c)
|
src/unix/sysinfo-loadavg.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
14
Makefile.am
14
Makefile.am
@ -35,6 +35,7 @@ libuv_la_SOURCES = src/fs-poll.c \
|
|||||||
src/idna.h \
|
src/idna.h \
|
||||||
src/inet.c \
|
src/inet.c \
|
||||||
src/queue.h \
|
src/queue.h \
|
||||||
|
src/random.c \
|
||||||
src/strscpy.c \
|
src/strscpy.c \
|
||||||
src/strscpy.h \
|
src/strscpy.h \
|
||||||
src/threadpool.c \
|
src/threadpool.c \
|
||||||
@ -105,6 +106,7 @@ libuv_la_SOURCES += src/unix/async.c \
|
|||||||
src/unix/pipe.c \
|
src/unix/pipe.c \
|
||||||
src/unix/poll.c \
|
src/unix/poll.c \
|
||||||
src/unix/process.c \
|
src/unix/process.c \
|
||||||
|
src/unix/random-devurandom.c \
|
||||||
src/unix/signal.c \
|
src/unix/signal.c \
|
||||||
src/unix/spinlock.h \
|
src/unix/spinlock.h \
|
||||||
src/unix/stream.c \
|
src/unix/stream.c \
|
||||||
@ -240,6 +242,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
|||||||
test/test-process-title.c \
|
test/test-process-title.c \
|
||||||
test/test-process-title-threadsafe.c \
|
test/test-process-title-threadsafe.c \
|
||||||
test/test-queue-foreach-delete.c \
|
test/test-queue-foreach-delete.c \
|
||||||
|
test/test-random.c \
|
||||||
test/test-ref.c \
|
test/test-ref.c \
|
||||||
test/test-run-nowait.c \
|
test/test-run-nowait.c \
|
||||||
test/test-run-once.c \
|
test/test-run-once.c \
|
||||||
@ -414,7 +417,8 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
|||||||
src/unix/darwin-proctitle.c \
|
src/unix/darwin-proctitle.c \
|
||||||
src/unix/fsevents.c \
|
src/unix/fsevents.c \
|
||||||
src/unix/kqueue.c \
|
src/unix/kqueue.c \
|
||||||
src/unix/proctitle.c
|
src/unix/proctitle.c \
|
||||||
|
src/unix/random-getentropy.c
|
||||||
test_run_tests_LDFLAGS += -lutil
|
test_run_tests_LDFLAGS += -lutil
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -434,7 +438,8 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
|||||||
src/unix/bsd-proctitle.c \
|
src/unix/bsd-proctitle.c \
|
||||||
src/unix/freebsd.c \
|
src/unix/freebsd.c \
|
||||||
src/unix/kqueue.c \
|
src/unix/kqueue.c \
|
||||||
src/unix/posix-hrtime.c
|
src/unix/posix-hrtime.c \
|
||||||
|
src/unix/random-getrandom.c
|
||||||
test_run_tests_LDFLAGS += -lutil
|
test_run_tests_LDFLAGS += -lutil
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -465,6 +470,8 @@ libuv_la_SOURCES += src/unix/linux-core.c \
|
|||||||
src/unix/linux-syscalls.h \
|
src/unix/linux-syscalls.h \
|
||||||
src/unix/procfs-exepath.c \
|
src/unix/procfs-exepath.c \
|
||||||
src/unix/proctitle.c \
|
src/unix/proctitle.c \
|
||||||
|
src/unix/random-getrandom.c \
|
||||||
|
src/unix/random-sysctl.c \
|
||||||
src/unix/sysinfo-loadavg.c
|
src/unix/sysinfo-loadavg.c
|
||||||
test_run_tests_LDFLAGS += -lutil
|
test_run_tests_LDFLAGS += -lutil
|
||||||
endif
|
endif
|
||||||
@ -498,7 +505,8 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
|||||||
src/unix/bsd-proctitle.c \
|
src/unix/bsd-proctitle.c \
|
||||||
src/unix/kqueue.c \
|
src/unix/kqueue.c \
|
||||||
src/unix/openbsd.c \
|
src/unix/openbsd.c \
|
||||||
src/unix/posix-hrtime.c
|
src/unix/posix-hrtime.c \
|
||||||
|
src/unix/random-getentropy.c
|
||||||
test_run_tests_LDFLAGS += -lutil
|
test_run_tests_LDFLAGS += -lutil
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,12 @@ Data types
|
|||||||
Replacement function for :man:`free(3)`.
|
Replacement function for :man:`free(3)`.
|
||||||
See :c:func:`uv_replace_allocator`.
|
See :c:func:`uv_replace_allocator`.
|
||||||
|
|
||||||
|
.. c:type:: void (*uv_random_cb)(uv_random_t* req, int status, void* buf, size_t buflen)
|
||||||
|
|
||||||
|
Callback passed to :c:func:`uv_random`. `status` is non-zero in case of
|
||||||
|
error. The `buf` pointer is the same pointer that was passed to
|
||||||
|
:c:func:`uv_random`.
|
||||||
|
|
||||||
.. c:type:: uv_file
|
.. c:type:: uv_file
|
||||||
|
|
||||||
Cross platform representation of a file handle.
|
Cross platform representation of a file handle.
|
||||||
@ -191,6 +197,9 @@ Data types
|
|||||||
char* value;
|
char* value;
|
||||||
} uv_env_item_t;
|
} uv_env_item_t;
|
||||||
|
|
||||||
|
.. c:type:: uv_random_t
|
||||||
|
|
||||||
|
Random data request type.
|
||||||
|
|
||||||
API
|
API
|
||||||
---
|
---
|
||||||
@ -648,3 +657,39 @@ API
|
|||||||
argument to `gettimeofday()` is not supported, as it is considered obsolete.
|
argument to `gettimeofday()` is not supported, as it is considered obsolete.
|
||||||
|
|
||||||
.. versionadded:: 1.28.0
|
.. versionadded:: 1.28.0
|
||||||
|
|
||||||
|
.. c:function:: int uv_random(uv_loop_t* loop, uv_random_t* req, void* buf, size_t buflen, unsigned int flags, uv_random_cb cb)
|
||||||
|
|
||||||
|
Fill `buf` with exactly `buflen` cryptographically strong random bytes
|
||||||
|
acquired from the system CSPRNG. `flags` is reserved for future extension
|
||||||
|
and must currently be 0.
|
||||||
|
|
||||||
|
Short reads are not possible. When less than `buflen` random bytes are
|
||||||
|
available, a non-zero error value is returned or passed to the callback.
|
||||||
|
|
||||||
|
The synchronous version may block indefinitely when not enough entropy
|
||||||
|
is available. The asynchronous version may not ever finish when the system
|
||||||
|
is low on entropy.
|
||||||
|
|
||||||
|
Sources of entropy:
|
||||||
|
|
||||||
|
- Windows: `RtlGenRandom <https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-rtlgenrandom>_`.
|
||||||
|
- Linux, Android: :man:`getrandom(2)` if available, or :man:`urandom(4)`
|
||||||
|
after reading from `/dev/random` once, or the `KERN_RANDOM`
|
||||||
|
:man:`sysctl(2)`.
|
||||||
|
- FreeBSD: `getrandom(2) <https://www.freebsd.org/cgi/man.cgi?query=getrandom&sektion=2>_`,
|
||||||
|
or `/dev/urandom` after reading from `/dev/random` once.
|
||||||
|
- macOS, OpenBSD: `getentropy(2) <https://man.openbsd.org/getentropy.2>_`
|
||||||
|
if available, or `/dev/urandom` after reading from `/dev/random` once.
|
||||||
|
- AIX: `/dev/random`.
|
||||||
|
- IBM i: `/dev/urandom`.
|
||||||
|
- Other UNIX: `/dev/urandom` after reading from `/dev/random` once.
|
||||||
|
|
||||||
|
:returns: 0 on success, or an error code < 0 on failure. The contents of
|
||||||
|
`buf` is undefined after an error.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
When using the synchronous version, both `loop` and `req` parameters
|
||||||
|
are not used and can be set to `NULL`.
|
||||||
|
|
||||||
|
.. versionadded:: 1.33.0
|
||||||
|
|||||||
26
include/uv.h
26
include/uv.h
@ -177,6 +177,7 @@ extern "C" {
|
|||||||
XX(WORK, work) \
|
XX(WORK, work) \
|
||||||
XX(GETADDRINFO, getaddrinfo) \
|
XX(GETADDRINFO, getaddrinfo) \
|
||||||
XX(GETNAMEINFO, getnameinfo) \
|
XX(GETNAMEINFO, getnameinfo) \
|
||||||
|
XX(RANDOM, random) \
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define XX(code, _) UV_ ## code = UV__ ## code,
|
#define XX(code, _) UV_ ## code = UV__ ## code,
|
||||||
@ -234,6 +235,7 @@ typedef struct uv_connect_s uv_connect_t;
|
|||||||
typedef struct uv_udp_send_s uv_udp_send_t;
|
typedef struct uv_udp_send_s uv_udp_send_t;
|
||||||
typedef struct uv_fs_s uv_fs_t;
|
typedef struct uv_fs_s uv_fs_t;
|
||||||
typedef struct uv_work_s uv_work_t;
|
typedef struct uv_work_s uv_work_t;
|
||||||
|
typedef struct uv_random_s uv_random_t;
|
||||||
|
|
||||||
/* None of the above. */
|
/* None of the above. */
|
||||||
typedef struct uv_env_item_s uv_env_item_t;
|
typedef struct uv_env_item_s uv_env_item_t;
|
||||||
@ -330,6 +332,10 @@ typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req,
|
|||||||
int status,
|
int status,
|
||||||
const char* hostname,
|
const char* hostname,
|
||||||
const char* service);
|
const char* service);
|
||||||
|
typedef void (*uv_random_cb)(uv_random_t* req,
|
||||||
|
int status,
|
||||||
|
void* buf,
|
||||||
|
size_t buflen);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
long tv_sec;
|
long tv_sec;
|
||||||
@ -1574,6 +1580,26 @@ UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size
|
|||||||
UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
|
UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
|
||||||
UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);
|
UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);
|
||||||
|
|
||||||
|
|
||||||
|
struct uv_random_s {
|
||||||
|
UV_REQ_FIELDS
|
||||||
|
/* read-only */
|
||||||
|
uv_loop_t* loop;
|
||||||
|
/* private */
|
||||||
|
int status;
|
||||||
|
void* buf;
|
||||||
|
size_t buflen;
|
||||||
|
uv_random_cb cb;
|
||||||
|
struct uv__work work_req;
|
||||||
|
};
|
||||||
|
|
||||||
|
UV_EXTERN int uv_random(uv_loop_t* loop,
|
||||||
|
uv_random_t* req,
|
||||||
|
void *buf,
|
||||||
|
size_t buflen,
|
||||||
|
unsigned flags, /* For future extension; must be 0. */
|
||||||
|
uv_random_cb cb);
|
||||||
|
|
||||||
#if defined(IF_NAMESIZE)
|
#if defined(IF_NAMESIZE)
|
||||||
# define UV_IF_NAMESIZE (IF_NAMESIZE + 1)
|
# define UV_IF_NAMESIZE (IF_NAMESIZE + 1)
|
||||||
#elif defined(IFNAMSIZ)
|
#elif defined(IFNAMSIZ)
|
||||||
|
|||||||
120
src/random.c
Normal file
120
src/random.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/* Copyright libuv contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uv.h"
|
||||||
|
#include "uv-common.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# include "win/internal.h"
|
||||||
|
#else
|
||||||
|
# include "unix/internal.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int uv__random(void* buf, size_t buflen) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
#if defined(__PASE__)
|
||||||
|
rc = uv__random_readpath("/dev/urandom", buf, buflen);
|
||||||
|
#elif defined(_AIX)
|
||||||
|
rc = uv__random_readpath("/dev/random", buf, buflen);
|
||||||
|
#elif defined(__APPLE__) || defined(__OpenBSD__)
|
||||||
|
rc = uv__random_getentropy(buf, buflen);
|
||||||
|
if (rc == UV_ENOSYS)
|
||||||
|
rc = uv__random_devurandom(buf, buflen);
|
||||||
|
#elif defined(__FreeBSD__) || defined(__linux__)
|
||||||
|
rc = uv__random_getrandom(buf, buflen);
|
||||||
|
if (rc == UV_ENOSYS)
|
||||||
|
rc = uv__random_devurandom(buf, buflen);
|
||||||
|
# if defined(__linux__)
|
||||||
|
switch (rc) {
|
||||||
|
case UV_EACCES:
|
||||||
|
case UV_EIO:
|
||||||
|
case UV_ELOOP:
|
||||||
|
case UV_EMFILE:
|
||||||
|
case UV_ENFILE:
|
||||||
|
case UV_ENOENT:
|
||||||
|
case UV_EPERM:
|
||||||
|
rc = uv__random_sysctl(buf, buflen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
uv__once_init();
|
||||||
|
rc = uv__random_rtlgenrandom(buf, buflen);
|
||||||
|
#else
|
||||||
|
rc = uv__random_devurandom(buf, buflen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void uv__random_work(struct uv__work* w) {
|
||||||
|
uv_random_t* req;
|
||||||
|
|
||||||
|
req = container_of(w, uv_random_t, work_req);
|
||||||
|
req->status = uv__random(req->buf, req->buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void uv__random_done(struct uv__work* w, int status) {
|
||||||
|
uv_random_t* req;
|
||||||
|
|
||||||
|
req = container_of(w, uv_random_t, work_req);
|
||||||
|
uv__req_unregister(req->loop, req);
|
||||||
|
|
||||||
|
if (status == 0)
|
||||||
|
status = req->status;
|
||||||
|
|
||||||
|
req->cb(req, status, req->buf, req->buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv_random(uv_loop_t* loop,
|
||||||
|
uv_random_t* req,
|
||||||
|
void *buf,
|
||||||
|
size_t buflen,
|
||||||
|
unsigned flags,
|
||||||
|
uv_random_cb cb) {
|
||||||
|
if (buflen > 0x7FFFFFFFu)
|
||||||
|
return UV_E2BIG;
|
||||||
|
|
||||||
|
if (flags != 0)
|
||||||
|
return UV_EINVAL;
|
||||||
|
|
||||||
|
if (cb == NULL)
|
||||||
|
return uv__random(buf, buflen);
|
||||||
|
|
||||||
|
uv__req_init(loop, req, UV_RANDOM);
|
||||||
|
req->loop = loop;
|
||||||
|
req->status = 0;
|
||||||
|
req->cb = cb;
|
||||||
|
req->buf = buf;
|
||||||
|
req->buflen = buflen;
|
||||||
|
|
||||||
|
uv__work_submit(loop,
|
||||||
|
&req->work_req,
|
||||||
|
UV__WORK_CPU,
|
||||||
|
uv__random_work,
|
||||||
|
uv__random_done);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -372,6 +372,10 @@ int uv_cancel(uv_req_t* req) {
|
|||||||
loop = ((uv_getnameinfo_t*) req)->loop;
|
loop = ((uv_getnameinfo_t*) req)->loop;
|
||||||
wreq = &((uv_getnameinfo_t*) req)->work_req;
|
wreq = &((uv_getnameinfo_t*) req)->work_req;
|
||||||
break;
|
break;
|
||||||
|
case UV_RANDOM:
|
||||||
|
loop = ((uv_random_t*) req)->loop;
|
||||||
|
wreq = &((uv_random_t*) req)->work_req;
|
||||||
|
break;
|
||||||
case UV_WORK:
|
case UV_WORK:
|
||||||
loop = ((uv_work_t*) req)->loop;
|
loop = ((uv_work_t*) req)->loop;
|
||||||
wreq = &((uv_work_t*) req)->work_req;
|
wreq = &((uv_work_t*) req)->work_req;
|
||||||
|
|||||||
@ -270,6 +270,12 @@ uv_handle_type uv__handle_type(int fd);
|
|||||||
FILE* uv__open_file(const char* path);
|
FILE* uv__open_file(const char* path);
|
||||||
int uv__getpwuid_r(uv_passwd_t* pwd);
|
int uv__getpwuid_r(uv_passwd_t* pwd);
|
||||||
|
|
||||||
|
/* random */
|
||||||
|
int uv__random_devurandom(void* buf, size_t buflen);
|
||||||
|
int uv__random_getrandom(void* buf, size_t buflen);
|
||||||
|
int uv__random_getentropy(void* buf, size_t buflen);
|
||||||
|
int uv__random_readpath(const char* path, void* buf, size_t buflen);
|
||||||
|
int uv__random_sysctl(void* buf, size_t buflen);
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
int uv___stream_fd(const uv_stream_t* handle);
|
int uv___stream_fd(const uv_stream_t* handle);
|
||||||
|
|||||||
@ -203,6 +203,22 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif /* __NR_statx */
|
#endif /* __NR_statx */
|
||||||
|
|
||||||
|
#ifndef __NR_getrandom
|
||||||
|
# if defined(__x86_64__)
|
||||||
|
# define __NR_getrandom 318
|
||||||
|
# elif defined(__i386__)
|
||||||
|
# define __NR_getrandom 355
|
||||||
|
# elif defined(__aarch64__)
|
||||||
|
# define __NR_getrandom 384
|
||||||
|
# elif defined(__arm__)
|
||||||
|
# define __NR_getrandom (UV_SYSCALL_BASE + 384)
|
||||||
|
# elif defined(__ppc__)
|
||||||
|
# define __NR_getrandom 359
|
||||||
|
# elif defined(__s390__)
|
||||||
|
# define __NR_getrandom 349
|
||||||
|
# endif
|
||||||
|
#endif /* __NR_getrandom */
|
||||||
|
|
||||||
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
|
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
unsigned long args[4];
|
unsigned long args[4];
|
||||||
@ -367,3 +383,12 @@ int uv__statx(int dirfd,
|
|||||||
return errno = ENOSYS, -1;
|
return errno = ENOSYS, -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) {
|
||||||
|
#if defined(__NR_getrandom)
|
||||||
|
return syscall(__NR_getrandom, buf, buflen, flags);
|
||||||
|
#else
|
||||||
|
return errno = ENOSYS, -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
@ -148,5 +148,6 @@ int uv__statx(int dirfd,
|
|||||||
int flags,
|
int flags,
|
||||||
unsigned int mask,
|
unsigned int mask,
|
||||||
struct uv__statx* statxbuf);
|
struct uv__statx* statxbuf);
|
||||||
|
ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags);
|
||||||
|
|
||||||
#endif /* UV_LINUX_SYSCALL_H_ */
|
#endif /* UV_LINUX_SYSCALL_H_ */
|
||||||
|
|||||||
93
src/unix/random-devurandom.c
Normal file
93
src/unix/random-devurandom.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/* Copyright libuv contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uv.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static uv_once_t once = UV_ONCE_INIT;
|
||||||
|
static int status;
|
||||||
|
|
||||||
|
|
||||||
|
int uv__random_readpath(const char* path, void* buf, size_t buflen) {
|
||||||
|
struct stat s;
|
||||||
|
size_t pos;
|
||||||
|
ssize_t n;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = uv__open_cloexec(path, O_RDONLY);
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
return UV__ERR(errno);
|
||||||
|
|
||||||
|
if (fstat(fd, &s)) {
|
||||||
|
uv__close(fd);
|
||||||
|
return UV__ERR(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISCHR(s.st_mode)) {
|
||||||
|
uv__close(fd);
|
||||||
|
return UV_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (pos = 0; pos != buflen; pos += n) {
|
||||||
|
do
|
||||||
|
n = read(fd, (char*) buf + pos, buflen - pos);
|
||||||
|
while (n == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
if (n == -1) {
|
||||||
|
uv__close(fd);
|
||||||
|
return UV__ERR(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
uv__close(fd);
|
||||||
|
return UV_EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uv__close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void uv__random_devurandom_init(void) {
|
||||||
|
char c;
|
||||||
|
|
||||||
|
/* Linux's and NetBSD's random(4) man page suggests applications should read
|
||||||
|
* at least once from /dev/random before switching to /dev/urandom in order
|
||||||
|
* to seed the system RNG. Reads from /dev/random can of course block
|
||||||
|
* indefinitely until entropy is available but that's the point.
|
||||||
|
*/
|
||||||
|
status = uv__random_readpath("/dev/random", &c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv__random_devurandom(void* buf, size_t buflen) {
|
||||||
|
uv_once(&once, uv__random_devurandom_init);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return uv__random_readpath("/dev/urandom", buf, buflen);
|
||||||
|
}
|
||||||
57
src/unix/random-getentropy.c
Normal file
57
src/unix/random-getentropy.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* Copyright libuv contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uv.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
typedef int (*uv__getentropy_cb)(void *, size_t);
|
||||||
|
|
||||||
|
static uv__getentropy_cb uv__getentropy;
|
||||||
|
static uv_once_t once = UV_ONCE_INIT;
|
||||||
|
|
||||||
|
|
||||||
|
static void uv__random_getentropy_init(void) {
|
||||||
|
uv__getentropy = (uv__getentropy_cb) dlsym(RTLD_DEFAULT, "getentropy");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int uv__random_getentropy(void* buf, size_t buflen) {
|
||||||
|
size_t pos;
|
||||||
|
size_t stride;
|
||||||
|
|
||||||
|
uv_once(&once, uv__random_getentropy_init);
|
||||||
|
|
||||||
|
if (uv__getentropy == NULL)
|
||||||
|
return UV_ENOSYS;
|
||||||
|
|
||||||
|
/* getentropy() returns an error for requests > 256 bytes. */
|
||||||
|
for (pos = 0, stride = 256; pos + stride < buflen; pos += stride)
|
||||||
|
if (uv__getentropy((char *) buf + pos, stride))
|
||||||
|
return UV__ERR(errno);
|
||||||
|
|
||||||
|
if (uv__getentropy((char *) buf + pos, buflen - pos))
|
||||||
|
return UV__ERR(errno);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
88
src/unix/random-getrandom.c
Normal file
88
src/unix/random-getrandom.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* Copyright libuv contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uv.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
#include "linux-syscalls.h"
|
||||||
|
|
||||||
|
#define uv__random_getrandom_init() 0
|
||||||
|
|
||||||
|
#else /* !__linux__ */
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
typedef ssize_t (*uv__getrandom_cb)(void *, size_t, unsigned);
|
||||||
|
|
||||||
|
static uv__getrandom_cb uv__getrandom;
|
||||||
|
static uv_once_t once = UV_ONCE_INIT;
|
||||||
|
|
||||||
|
static void uv__random_getrandom_init_once(void) {
|
||||||
|
uv__getrandom = (uv__getrandom_cb) dlsym(RTLD_DEFAULT, "getrandom");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int uv__random_getrandom_init(void) {
|
||||||
|
uv_once(&once, uv__random_getrandom_init_once);
|
||||||
|
|
||||||
|
if (uv__getrandom == NULL)
|
||||||
|
return UV_ENOSYS;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !__linux__ */
|
||||||
|
|
||||||
|
int uv__random_getrandom(void* buf, size_t buflen) {
|
||||||
|
ssize_t n;
|
||||||
|
size_t pos;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = uv__random_getrandom_init();
|
||||||
|
if (rc != 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
for (pos = 0; pos != buflen; pos += n) {
|
||||||
|
do {
|
||||||
|
n = buflen - pos;
|
||||||
|
|
||||||
|
/* Most getrandom() implementations promise that reads <= 256 bytes
|
||||||
|
* will always succeed and won't be interrupted by signals.
|
||||||
|
* It's therefore useful to split it up in smaller reads because
|
||||||
|
* one big read may, in theory, continuously fail with EINTR.
|
||||||
|
*/
|
||||||
|
if (n > 256)
|
||||||
|
n = 256;
|
||||||
|
|
||||||
|
n = uv__getrandom((char *) buf + pos, n, 0);
|
||||||
|
} while (n == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
if (n == -1)
|
||||||
|
return UV__ERR(errno);
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return UV_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
91
src/unix/random-sysctl.c
Normal file
91
src/unix/random-sysctl.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/* Copyright libuv contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uv.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct uv__sysctl_args {
|
||||||
|
int* name;
|
||||||
|
int nlen;
|
||||||
|
void* oldval;
|
||||||
|
size_t* oldlenp;
|
||||||
|
void* newval;
|
||||||
|
size_t newlen;
|
||||||
|
unsigned long unused[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO(bnoordhuis) Use {CTL_KERN, KERN_ARND} on FreeBSD (and NetBSD?) */
|
||||||
|
int uv__random_sysctl(void* buf, size_t buflen) {
|
||||||
|
static int name[] = {1 /*CTL_KERN*/, 40 /*KERN_RANDOM*/, 6 /*RANDOM_UUID*/};
|
||||||
|
struct uv__sysctl_args args;
|
||||||
|
char uuid[16];
|
||||||
|
char* p;
|
||||||
|
char* pe;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
pe = p + buflen;
|
||||||
|
|
||||||
|
while (p < pe) {
|
||||||
|
memset(&args, 0, sizeof(args));
|
||||||
|
|
||||||
|
args.name = name;
|
||||||
|
args.nlen = ARRAY_SIZE(name);
|
||||||
|
args.oldval = uuid;
|
||||||
|
args.oldlenp = &n;
|
||||||
|
n = sizeof(uuid);
|
||||||
|
|
||||||
|
/* Emits a deprecation warning with some kernels but that seems like
|
||||||
|
* an okay trade-off for the fallback of the fallback: this function is
|
||||||
|
* only called when neither getrandom(2) nor /dev/urandom are available.
|
||||||
|
* Fails with ENOSYS on kernels configured without CONFIG_SYSCTL_SYSCALL.
|
||||||
|
*/
|
||||||
|
if (syscall(SYS__sysctl, &args) == -1)
|
||||||
|
return UV__ERR(errno);
|
||||||
|
|
||||||
|
if (n != sizeof(uuid))
|
||||||
|
return UV_EIO; /* Can't happen. */
|
||||||
|
|
||||||
|
/* uuid[] is now a type 4 UUID. Bytes 6 and 8 (counting from zero) contain
|
||||||
|
* 4 and 5 bits of entropy, respectively. For ease of use, we skip those
|
||||||
|
* and only use 14 of the 16 bytes.
|
||||||
|
*/
|
||||||
|
uuid[6] = uuid[14];
|
||||||
|
uuid[8] = uuid[15];
|
||||||
|
|
||||||
|
n = pe - p;
|
||||||
|
if (n > 14)
|
||||||
|
n = 14;
|
||||||
|
|
||||||
|
memcpy(p, uuid, n);
|
||||||
|
p += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -280,6 +280,8 @@ int uv__getsockpeername(const uv_handle_t* handle,
|
|||||||
int* namelen,
|
int* namelen,
|
||||||
int delayed_error);
|
int delayed_error);
|
||||||
|
|
||||||
|
int uv__random_rtlgenrandom(void* buf, size_t buflen);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process stdio handles.
|
* Process stdio handles.
|
||||||
|
|||||||
@ -1860,3 +1860,16 @@ int uv_gettimeofday(uv_timeval64_t* tv) {
|
|||||||
tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10);
|
tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uv__random_rtlgenrandom(void* buf, size_t buflen) {
|
||||||
|
if (pRtlGenRandom == NULL)
|
||||||
|
return UV_ENOSYS;
|
||||||
|
|
||||||
|
if (buflen == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (pRtlGenRandom(buf, buflen) == FALSE)
|
||||||
|
return UV_EIO;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -36,6 +36,9 @@ sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
|||||||
sNtQuerySystemInformation pNtQuerySystemInformation;
|
sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||||
sNtQueryInformationProcess pNtQueryInformationProcess;
|
sNtQueryInformationProcess pNtQueryInformationProcess;
|
||||||
|
|
||||||
|
/* Advapi32 function pointers */
|
||||||
|
sRtlGenRandom pRtlGenRandom;
|
||||||
|
|
||||||
/* Kernel32 function pointers */
|
/* Kernel32 function pointers */
|
||||||
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||||
|
|
||||||
@ -51,6 +54,7 @@ void uv_winapi_init(void) {
|
|||||||
HMODULE powrprof_module;
|
HMODULE powrprof_module;
|
||||||
HMODULE user32_module;
|
HMODULE user32_module;
|
||||||
HMODULE kernel32_module;
|
HMODULE kernel32_module;
|
||||||
|
HMODULE advapi32_module;
|
||||||
|
|
||||||
ntdll_module = GetModuleHandleA("ntdll.dll");
|
ntdll_module = GetModuleHandleA("ntdll.dll");
|
||||||
if (ntdll_module == NULL) {
|
if (ntdll_module == NULL) {
|
||||||
@ -135,4 +139,11 @@ void uv_winapi_init(void) {
|
|||||||
GetProcAddress(user32_module, "SetWinEventHook");
|
GetProcAddress(user32_module, "SetWinEventHook");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
advapi32_module = GetModuleHandleA("advapi32.dll");
|
||||||
|
if (advapi32_module == NULL) {
|
||||||
|
uv_fatal_error(GetLastError(), "GetModuleHandleA");
|
||||||
|
}
|
||||||
|
|
||||||
|
pRtlGenRandom =
|
||||||
|
(sRtlGenRandom) GetProcAddress(advapi32_module, "SystemFunction036");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4589,6 +4589,11 @@ typedef NTSTATUS (NTAPI *sNtQueryInformationProcess)
|
|||||||
ULONG Length,
|
ULONG Length,
|
||||||
PULONG ReturnLength);
|
PULONG ReturnLength);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Advapi32 headers
|
||||||
|
*/
|
||||||
|
typedef BOOLEAN (WINAPI *sRtlGenRandom)(PVOID Buffer, ULONG BufferLength);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel32 headers
|
* Kernel32 headers
|
||||||
*/
|
*/
|
||||||
@ -4731,6 +4736,9 @@ extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
|
|||||||
extern sNtQuerySystemInformation pNtQuerySystemInformation;
|
extern sNtQuerySystemInformation pNtQuerySystemInformation;
|
||||||
extern sNtQueryInformationProcess pNtQueryInformationProcess;
|
extern sNtQueryInformationProcess pNtQueryInformationProcess;
|
||||||
|
|
||||||
|
/* Advapi32 function pointers */
|
||||||
|
extern sRtlGenRandom pRtlGenRandom;
|
||||||
|
|
||||||
/* Kernel32 function pointers */
|
/* Kernel32 function pointers */
|
||||||
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
|
||||||
|
|
||||||
|
|||||||
@ -395,6 +395,7 @@ TEST_DECLARE (threadpool_queue_work_einval)
|
|||||||
TEST_DECLARE (threadpool_multiple_event_loops)
|
TEST_DECLARE (threadpool_multiple_event_loops)
|
||||||
TEST_DECLARE (threadpool_cancel_getaddrinfo)
|
TEST_DECLARE (threadpool_cancel_getaddrinfo)
|
||||||
TEST_DECLARE (threadpool_cancel_getnameinfo)
|
TEST_DECLARE (threadpool_cancel_getnameinfo)
|
||||||
|
TEST_DECLARE (threadpool_cancel_random)
|
||||||
TEST_DECLARE (threadpool_cancel_work)
|
TEST_DECLARE (threadpool_cancel_work)
|
||||||
TEST_DECLARE (threadpool_cancel_fs)
|
TEST_DECLARE (threadpool_cancel_fs)
|
||||||
TEST_DECLARE (threadpool_cancel_single)
|
TEST_DECLARE (threadpool_cancel_single)
|
||||||
@ -464,6 +465,9 @@ HELPER_DECLARE (pipe_echo_server)
|
|||||||
|
|
||||||
TEST_DECLARE (queue_foreach_delete)
|
TEST_DECLARE (queue_foreach_delete)
|
||||||
|
|
||||||
|
TEST_DECLARE (random_async)
|
||||||
|
TEST_DECLARE (random_sync)
|
||||||
|
|
||||||
TEST_DECLARE (handle_type_name)
|
TEST_DECLARE (handle_type_name)
|
||||||
TEST_DECLARE (req_type_name)
|
TEST_DECLARE (req_type_name)
|
||||||
TEST_DECLARE (getters_setters)
|
TEST_DECLARE (getters_setters)
|
||||||
@ -1000,6 +1004,7 @@ TASK_LIST_START
|
|||||||
TEST_ENTRY_CUSTOM (threadpool_multiple_event_loops, 0, 0, 60000)
|
TEST_ENTRY_CUSTOM (threadpool_multiple_event_loops, 0, 0, 60000)
|
||||||
TEST_ENTRY (threadpool_cancel_getaddrinfo)
|
TEST_ENTRY (threadpool_cancel_getaddrinfo)
|
||||||
TEST_ENTRY (threadpool_cancel_getnameinfo)
|
TEST_ENTRY (threadpool_cancel_getnameinfo)
|
||||||
|
TEST_ENTRY (threadpool_cancel_random)
|
||||||
TEST_ENTRY (threadpool_cancel_work)
|
TEST_ENTRY (threadpool_cancel_work)
|
||||||
TEST_ENTRY (threadpool_cancel_fs)
|
TEST_ENTRY (threadpool_cancel_fs)
|
||||||
TEST_ENTRY (threadpool_cancel_single)
|
TEST_ENTRY (threadpool_cancel_single)
|
||||||
@ -1018,6 +1023,9 @@ TASK_LIST_START
|
|||||||
|
|
||||||
TEST_ENTRY (queue_foreach_delete)
|
TEST_ENTRY (queue_foreach_delete)
|
||||||
|
|
||||||
|
TEST_ENTRY (random_async)
|
||||||
|
TEST_ENTRY (random_sync)
|
||||||
|
|
||||||
TEST_ENTRY (handle_type_name)
|
TEST_ENTRY (handle_type_name)
|
||||||
TEST_ENTRY (req_type_name)
|
TEST_ENTRY (req_type_name)
|
||||||
TEST_ENTRY (getters_setters)
|
TEST_ENTRY (getters_setters)
|
||||||
|
|||||||
94
test/test-random.c
Normal file
94
test/test-random.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/* Copyright libuv contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "uv.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static char scratch[256];
|
||||||
|
static int random_cb_called;
|
||||||
|
|
||||||
|
|
||||||
|
static void random_cb(uv_random_t* req, int status, void* buf, size_t buflen) {
|
||||||
|
char zero[sizeof(scratch)];
|
||||||
|
|
||||||
|
memset(zero, 0, sizeof(zero));
|
||||||
|
|
||||||
|
ASSERT(0 == status);
|
||||||
|
ASSERT(buf == (void*) scratch);
|
||||||
|
|
||||||
|
if (random_cb_called == 0) {
|
||||||
|
ASSERT(buflen == 0);
|
||||||
|
ASSERT(0 == memcmp(scratch, zero, sizeof(zero)));
|
||||||
|
} else {
|
||||||
|
ASSERT(buflen == sizeof(scratch));
|
||||||
|
/* Buy a lottery ticket if you manage to trip this assertion. */
|
||||||
|
ASSERT(0 != memcmp(scratch, zero, sizeof(zero)));
|
||||||
|
}
|
||||||
|
|
||||||
|
random_cb_called++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(random_async) {
|
||||||
|
uv_random_t req;
|
||||||
|
uv_loop_t* loop;
|
||||||
|
|
||||||
|
loop = uv_default_loop();
|
||||||
|
ASSERT(UV_EINVAL == uv_random(loop, &req, scratch, sizeof(scratch), -1,
|
||||||
|
random_cb));
|
||||||
|
ASSERT(UV_E2BIG == uv_random(loop, &req, scratch, -1, -1, random_cb));
|
||||||
|
|
||||||
|
ASSERT(0 == uv_random(loop, &req, scratch, 0, 0, random_cb));
|
||||||
|
ASSERT(0 == random_cb_called);
|
||||||
|
|
||||||
|
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||||
|
ASSERT(1 == random_cb_called);
|
||||||
|
|
||||||
|
ASSERT(0 == uv_random(loop, &req, scratch, sizeof(scratch), 0, random_cb));
|
||||||
|
ASSERT(1 == random_cb_called);
|
||||||
|
|
||||||
|
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||||
|
ASSERT(2 == random_cb_called);
|
||||||
|
|
||||||
|
MAKE_VALGRIND_HAPPY();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(random_sync) {
|
||||||
|
char zero[256];
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
ASSERT(UV_EINVAL == uv_random(NULL, NULL, buf, sizeof(buf), -1, NULL));
|
||||||
|
ASSERT(UV_E2BIG == uv_random(NULL, NULL, buf, -1, -1, NULL));
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
ASSERT(0 == uv_random(NULL, NULL, buf, sizeof(buf), 0, NULL));
|
||||||
|
|
||||||
|
/* Buy a lottery ticket if you manage to trip this assertion. */
|
||||||
|
memset(zero, 0, sizeof(zero));
|
||||||
|
ASSERT(0 != memcmp(buf, zero, sizeof(zero)));
|
||||||
|
|
||||||
|
MAKE_VALGRIND_HAPPY();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -37,6 +37,11 @@ struct cancel_info {
|
|||||||
uv_timer_t timer_handle;
|
uv_timer_t timer_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct random_info {
|
||||||
|
uv_random_t random_req;
|
||||||
|
char buf[1];
|
||||||
|
};
|
||||||
|
|
||||||
static unsigned fs_cb_called;
|
static unsigned fs_cb_called;
|
||||||
static unsigned done_cb_called;
|
static unsigned done_cb_called;
|
||||||
static unsigned done2_cb_called;
|
static unsigned done2_cb_called;
|
||||||
@ -143,6 +148,19 @@ static void nop_done_cb(uv_work_t* req, int status) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void nop_random_cb(uv_random_t* req, int status, void* buf, size_t len) {
|
||||||
|
struct random_info* ri;
|
||||||
|
|
||||||
|
ri = container_of(req, struct random_info, random_req);
|
||||||
|
|
||||||
|
ASSERT(status == UV_ECANCELED);
|
||||||
|
ASSERT(buf == (void*) ri->buf);
|
||||||
|
ASSERT(len == sizeof(ri->buf));
|
||||||
|
|
||||||
|
done_cb_called++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_IMPL(threadpool_cancel_getaddrinfo) {
|
TEST_IMPL(threadpool_cancel_getaddrinfo) {
|
||||||
uv_getaddrinfo_t reqs[4];
|
uv_getaddrinfo_t reqs[4];
|
||||||
struct cancel_info ci;
|
struct cancel_info ci;
|
||||||
@ -212,6 +230,29 @@ TEST_IMPL(threadpool_cancel_getnameinfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_IMPL(threadpool_cancel_random) {
|
||||||
|
struct random_info req;
|
||||||
|
uv_loop_t* loop;
|
||||||
|
|
||||||
|
saturate_threadpool();
|
||||||
|
loop = uv_default_loop();
|
||||||
|
ASSERT(0 == uv_random(loop,
|
||||||
|
&req.random_req,
|
||||||
|
&req.buf,
|
||||||
|
sizeof(req.buf),
|
||||||
|
0,
|
||||||
|
nop_random_cb));
|
||||||
|
ASSERT(0 == uv_cancel((uv_req_t*) &req));
|
||||||
|
ASSERT(0 == done_cb_called);
|
||||||
|
unblock_threadpool();
|
||||||
|
ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
|
||||||
|
ASSERT(1 == done_cb_called);
|
||||||
|
|
||||||
|
MAKE_VALGRIND_HAPPY();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_IMPL(threadpool_cancel_work) {
|
TEST_IMPL(threadpool_cancel_work) {
|
||||||
struct cancel_info ci;
|
struct cancel_info ci;
|
||||||
uv_work_t reqs[16];
|
uv_work_t reqs[16];
|
||||||
|
|||||||
@ -90,6 +90,7 @@
|
|||||||
'test-process-title.c',
|
'test-process-title.c',
|
||||||
'test-process-title-threadsafe.c',
|
'test-process-title-threadsafe.c',
|
||||||
'test-queue-foreach-delete.c',
|
'test-queue-foreach-delete.c',
|
||||||
|
'test-random.c',
|
||||||
'test-ref.c',
|
'test-ref.c',
|
||||||
'test-run-nowait.c',
|
'test-run-nowait.c',
|
||||||
'test-run-once.c',
|
'test-run-once.c',
|
||||||
|
|||||||
15
uv.gyp
15
uv.gyp
@ -75,6 +75,7 @@
|
|||||||
'src/idna.h',
|
'src/idna.h',
|
||||||
'src/inet.c',
|
'src/inet.c',
|
||||||
'src/queue.h',
|
'src/queue.h',
|
||||||
|
'src/random.c',
|
||||||
'src/strscpy.c',
|
'src/strscpy.c',
|
||||||
'src/strscpy.h',
|
'src/strscpy.h',
|
||||||
'src/threadpool.c',
|
'src/threadpool.c',
|
||||||
@ -167,6 +168,7 @@
|
|||||||
'src/unix/pipe.c',
|
'src/unix/pipe.c',
|
||||||
'src/unix/poll.c',
|
'src/unix/poll.c',
|
||||||
'src/unix/process.c',
|
'src/unix/process.c',
|
||||||
|
'src/unix/random-devurandom.c',
|
||||||
'src/unix/signal.c',
|
'src/unix/signal.c',
|
||||||
'src/unix/spinlock.h',
|
'src/unix/spinlock.h',
|
||||||
'src/unix/stream.c',
|
'src/unix/stream.c',
|
||||||
@ -226,7 +228,8 @@
|
|||||||
'sources': [
|
'sources': [
|
||||||
'src/unix/darwin.c',
|
'src/unix/darwin.c',
|
||||||
'src/unix/fsevents.c',
|
'src/unix/fsevents.c',
|
||||||
'src/unix/darwin-proctitle.c'
|
'src/unix/darwin-proctitle.c',
|
||||||
|
'src/unix/random-getentropy.c',
|
||||||
],
|
],
|
||||||
'defines': [
|
'defines': [
|
||||||
'_DARWIN_USE_64_BIT_INODE=1',
|
'_DARWIN_USE_64_BIT_INODE=1',
|
||||||
@ -241,6 +244,8 @@
|
|||||||
'src/unix/linux-syscalls.c',
|
'src/unix/linux-syscalls.c',
|
||||||
'src/unix/linux-syscalls.h',
|
'src/unix/linux-syscalls.h',
|
||||||
'src/unix/procfs-exepath.c',
|
'src/unix/procfs-exepath.c',
|
||||||
|
'src/unix/random-getrandom.c',
|
||||||
|
'src/unix/random-sysctl.c',
|
||||||
'src/unix/sysinfo-loadavg.c',
|
'src/unix/sysinfo-loadavg.c',
|
||||||
],
|
],
|
||||||
'link_settings': {
|
'link_settings': {
|
||||||
@ -320,8 +325,14 @@
|
|||||||
[ 'OS=="freebsd" or OS=="dragonflybsd"', {
|
[ 'OS=="freebsd" or OS=="dragonflybsd"', {
|
||||||
'sources': [ 'src/unix/freebsd.c' ],
|
'sources': [ 'src/unix/freebsd.c' ],
|
||||||
}],
|
}],
|
||||||
|
[ 'OS=="freebsd"', {
|
||||||
|
'sources': [ 'src/unix/random-getrandom.c' ],
|
||||||
|
}],
|
||||||
[ 'OS=="openbsd"', {
|
[ 'OS=="openbsd"', {
|
||||||
'sources': [ 'src/unix/openbsd.c' ],
|
'sources': [
|
||||||
|
'src/unix/openbsd.c',
|
||||||
|
'src/unix/random-getentropy.c',
|
||||||
|
],
|
||||||
}],
|
}],
|
||||||
[ 'OS=="netbsd"', {
|
[ 'OS=="netbsd"', {
|
||||||
'link_settings': {
|
'link_settings': {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user