diff --git a/src/modules/module-avb/maap.c b/src/modules/module-avb/maap.c index c57477e41..2a78b30ba 100644 --- a/src/modules/module-avb/maap.c +++ b/src/modules/module-avb/maap.c @@ -400,10 +400,8 @@ struct avb_maap *avb_maap_register(struct server *server) maap->server = server; pw_log_info("0x%"PRIx64" %d", server->entity_id, server->ifindex); - if (pw_getrandom(maap->xsubi, sizeof(maap->xsubi), 0) != sizeof(maap->xsubi)) { - res = -errno; - goto error_free; - } + pw_random(maap->xsubi, sizeof(maap->xsubi)); + load_state(maap); maap->source = pw_loop_add_io(server->impl->loop, fd, SPA_IO_IN, true, on_socket_data, maap); diff --git a/src/pipewire/impl-core.c b/src/pipewire/impl-core.c index d3689c110..71cc8ed62 100644 --- a/src/pipewire/impl-core.c +++ b/src/pipewire/impl-core.c @@ -413,17 +413,7 @@ struct pw_impl_core *pw_context_create_core(struct pw_context *context, this->info.user_name = pw_get_user_name(); this->info.host_name = pw_get_host_name(); this->info.version = pw_get_library_version(); - do { - res = pw_getrandom(&this->info.cookie, - sizeof(this->info.cookie), 0); - } while ((res == -1) && (errno == EINTR)); - if (res == -1) { - res = -errno; - goto error_exit; - } else if (res != sizeof(this->info.cookie)) { - res = -ENODATA; - goto error_exit; - } + this->info.cookie = pw_rand32(); this->info.name = name; spa_hook_list_init(&this->listener_list); diff --git a/src/pipewire/pipewire.c b/src/pipewire/pipewire.c index 9d5c8eb77..e13c8a461 100644 --- a/src/pipewire/pipewire.c +++ b/src/pipewire/pipewire.c @@ -569,6 +569,8 @@ void pw_init(int *argc, char **argv[]) if (support->init_count > 0) goto done; + pw_random_init(); + pthread_mutex_lock(&support_lock); support->in_valgrind = RUNNING_ON_VALGRIND; diff --git a/src/pipewire/private.h b/src/pipewire/private.h index b9ce1870d..1aa02611d 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -1276,6 +1276,8 @@ bool pw_log_is_default(void); void pw_log_init(void); void pw_log_deinit(void); +void pw_random_init(); + void pw_settings_init(struct pw_context *context); int pw_settings_expose(struct pw_context *context); void pw_settings_clean(struct pw_context *context); diff --git a/src/pipewire/utils.c b/src/pipewire/utils.c index 9462158f9..7af984ee8 100644 --- a/src/pipewire/utils.c +++ b/src/pipewire/utils.c @@ -11,6 +11,7 @@ #include #endif #include +#include #include #include @@ -153,16 +154,7 @@ char *pw_strip(char *str, const char *whitespace) return str; } -/** Fill a buffer with random data - * \param buf a buffer to fill - * \param buflen the number of bytes to fill - * \param flags optional flags - * \return the number of bytes filled - * - * Fill \a buf with \a buflen random bytes. - */ -SPA_EXPORT -ssize_t pw_getrandom(void *buf, size_t buflen, unsigned int flags) +static inline ssize_t make_random(void *buf, size_t buflen, unsigned int flags) { ssize_t bytes; int read_errno; @@ -183,6 +175,63 @@ ssize_t pw_getrandom(void *buf, size_t buflen, unsigned int flags) return bytes; } +/** Fill a buffer with random data + * \param buf a buffer to fill + * \param buflen the number of bytes to fill + * \param flags optional flags + * \return the number of bytes filled + * + * Fill \a buf with \a buflen random bytes. + */ +SPA_EXPORT +ssize_t pw_getrandom(void *buf, size_t buflen, unsigned int flags) +{ + ssize_t res; + do { + res = make_random(buf, buflen, flags); + } while ((res == -1) && (errno == EINTR)); + if (res == -1) + return -errno; + if ((size_t)res != buflen) + return -ENODATA; + return res; +} + +static char statebuf[256]; +static struct random_data random_state; + +/** Fill a buffer with random data + * \param buf a buffer to fill + * \param buflen the number of bytes to fill + * + * Fill \a buf with \a buflen random bytes. This functions uses + * pw_getrandom() but falls back to a pseudo random number + * generator in case of failure. + */ +SPA_EXPORT +void pw_random(void *buf, size_t buflen) +{ + if (pw_getrandom(buf, buflen, 0) < 0) { + uint8_t *p = buf; + while (buflen-- > 0) { + int32_t val; + random_r(&random_state, &val); + *p++ = (uint8_t) val;; + } + } +} + +void pw_random_init() +{ + unsigned int seed; + if (pw_getrandom(&seed, sizeof(seed), 0) < 0) { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + seed = (unsigned int) SPA_TIMESPEC_TO_NSEC(&ts); + } + initstate_r(seed, statebuf, sizeof(statebuf), &random_state); +} + SPA_EXPORT void* pw_reallocarray(void *ptr, size_t nmemb, size_t size) { diff --git a/src/pipewire/utils.h b/src/pipewire/utils.h index 46190dfae..d5aa6c228 100644 --- a/src/pipewire/utils.h +++ b/src/pipewire/utils.h @@ -72,6 +72,10 @@ pw_strip(char *str, const char *whitespace); SPA_WARN_UNUSED_RESULT ssize_t pw_getrandom(void *buf, size_t buflen, unsigned int flags); +void pw_random(void *buf, size_t buflen); + +#define pw_rand32() ({ uint32_t val; pw_random(&val, sizeof(val)); val; }) + void* pw_reallocarray(void *ptr, size_t nmemb, size_t size); #ifdef PW_ENABLE_DEPRECATED