|
54 | 54 | #include "zend.h"
|
55 | 55 | #include "zend_alloc.h"
|
56 | 56 | #include "zend_globals.h"
|
| 57 | +#include "zend_hrtime.h" |
57 | 58 | #include "zend_operators.h"
|
58 | 59 | #include "zend_multiply.h"
|
59 | 60 | #include "zend_bitset.h"
|
60 | 61 | #include "zend_mmap.h"
|
61 | 62 | #include "zend_portability.h"
|
62 |
| -#include "ext/random/php_random_csprng.h" |
63 |
| -#include "ext/random/php_random.h" |
| 63 | +#include "zend_random.h" |
64 | 64 | #include <signal.h>
|
65 | 65 |
|
66 | 66 | #ifdef HAVE_UNISTD_H
|
@@ -246,6 +246,10 @@ typedef struct _zend_mm_huge_list zend_mm_huge_list;
|
246 | 246 |
|
247 | 247 | static bool zend_mm_use_huge_pages = false;
|
248 | 248 |
|
| 249 | +typedef struct _zend_mm_rand_state { |
| 250 | + uint32_t state[4]; |
| 251 | +} zend_mm_rand_state; |
| 252 | + |
249 | 253 | /*
|
250 | 254 | * Memory is retrieved from OS by chunks of fixed size 2MB.
|
251 | 255 | * Inside chunk it's managed by pages of fixed size 4096B.
|
@@ -321,7 +325,7 @@ struct _zend_mm_heap {
|
321 | 325 | HashTable *tracked_allocs;
|
322 | 326 | #endif
|
323 | 327 | pid_t pid;
|
324 |
| - php_random_status_state_xoshiro256starstar random_state; |
| 328 | + zend_mm_rand_state rand_state; |
325 | 329 | };
|
326 | 330 |
|
327 | 331 | struct _zend_mm_chunk {
|
@@ -2016,30 +2020,102 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE
|
2016 | 2020 | #endif
|
2017 | 2021 | }
|
2018 | 2022 |
|
| 2023 | +/********/ |
| 2024 | +/* Rand */ |
| 2025 | +/********/ |
| 2026 | + |
| 2027 | +/* Xoshiro256** PRNG based on implementation from Go Kudo in |
| 2028 | + * ext/random/engine_xoshiro256starstar.c, based on code from David Blackman, |
| 2029 | + * Sebastiano Vigna. */ |
| 2030 | + |
| 2031 | +static inline uint64_t splitmix64(uint64_t *seed) |
| 2032 | +{ |
| 2033 | + uint64_t r; |
| 2034 | + |
| 2035 | + r = (*seed += 0x9e3779b97f4a7c15ULL); |
| 2036 | + r = (r ^ (r >> 30)) * 0xbf58476d1ce4e5b9ULL; |
| 2037 | + r = (r ^ (r >> 27)) * 0x94d049bb133111ebULL; |
| 2038 | + return (r ^ (r >> 31)); |
| 2039 | +} |
| 2040 | + |
| 2041 | +ZEND_ATTRIBUTE_CONST static inline uint64_t rotl(const uint64_t x, int k) |
| 2042 | +{ |
| 2043 | + return (x << k) | (x >> (64 - k)); |
| 2044 | +} |
| 2045 | + |
| 2046 | +static inline uint64_t zend_mm_rand_generate(zend_mm_rand_state *s) |
| 2047 | +{ |
| 2048 | + const uint64_t r = rotl(s->state[1] * 5, 7) * 9; |
| 2049 | + const uint64_t t = s->state[1] << 17; |
| 2050 | + |
| 2051 | + s->state[2] ^= s->state[0]; |
| 2052 | + s->state[3] ^= s->state[1]; |
| 2053 | + s->state[1] ^= s->state[2]; |
| 2054 | + s->state[0] ^= s->state[3]; |
| 2055 | + |
| 2056 | + s->state[2] ^= t; |
| 2057 | + |
| 2058 | + s->state[3] = rotl(s->state[3], 45); |
| 2059 | + |
| 2060 | + return r; |
| 2061 | +} |
| 2062 | + |
| 2063 | +static inline void zend_mm_rand_seed256(zend_mm_rand_state *state, uint64_t s0, uint64_t s1, uint64_t s2, uint64_t s3) |
| 2064 | +{ |
| 2065 | + state->state[0] = s0; |
| 2066 | + state->state[1] = s1; |
| 2067 | + state->state[2] = s2; |
| 2068 | + state->state[3] = s3; |
| 2069 | +} |
| 2070 | + |
| 2071 | +static inline void zend_mm_rand_seed64(zend_mm_rand_state *state, uint64_t seed) |
| 2072 | +{ |
| 2073 | + uint64_t s[4]; |
| 2074 | + |
| 2075 | + s[0] = splitmix64(&seed); |
| 2076 | + s[1] = splitmix64(&seed); |
| 2077 | + s[2] = splitmix64(&seed); |
| 2078 | + s[3] = splitmix64(&seed); |
| 2079 | + |
| 2080 | + zend_mm_rand_seed256(state, s[0], s[1], s[2], s[3]); |
| 2081 | +} |
| 2082 | + |
2019 | 2083 | /******************/
|
2020 | 2084 | /* Initialization */
|
2021 | 2085 | /******************/
|
2022 | 2086 |
|
2023 | 2087 | static zend_result zend_mm_refresh_key(zend_mm_heap *heap)
|
2024 | 2088 | {
|
2025 |
| - php_random_result result = php_random_algo_xoshiro256starstar.generate(&heap->random_state); |
2026 |
| - ZEND_ASSERT(result.size == sizeof(uint64_t)); |
2027 |
| - heap->shadow_key = (uintptr_t) result.result; |
| 2089 | + heap->shadow_key = (uintptr_t) zend_mm_rand_generate(&heap->rand_state); |
| 2090 | + |
2028 | 2091 | return SUCCESS;
|
2029 | 2092 | }
|
2030 | 2093 |
|
2031 | 2094 | static zend_result zend_mm_init_key(zend_mm_heap *heap)
|
2032 | 2095 | {
|
2033 | 2096 | uint64_t seed[4];
|
2034 |
| - if (php_random_bytes_silent(&seed, sizeof(seed)) != SUCCESS) { |
2035 |
| - for (int i = 0; i < sizeof(seed)/sizeof(seed[0]); i++) { |
2036 |
| - seed[i] = php_random_generate_fallback_seed(); |
2037 |
| - } |
| 2097 | + char errstr[128]; |
| 2098 | + if (zend_get_os_random_bytes_ex(&seed, sizeof(seed), errstr, sizeof(errstr)) == SUCCESS) { |
| 2099 | + zend_mm_rand_seed256(&heap->rand_state, |
| 2100 | + seed[0], seed[1], seed[2], seed[3]); |
| 2101 | + } else { |
| 2102 | + /* Fallback to weak seed generation */ |
| 2103 | +#if ZEND_MM_ERROR |
| 2104 | + fprintf(stderr, "Could not generate secure random seed: %s\n", errstr); |
| 2105 | +#endif |
| 2106 | + zend_hrtime_t nanotime = zend_hrtime(); |
| 2107 | + uint64_t v = 0; |
| 2108 | + v ^= (uint64_t) nanotime; |
| 2109 | + splitmix64(&v); |
| 2110 | + v ^= (uint64_t) getpid(); |
| 2111 | + splitmix64(&v); |
| 2112 | +#ifdef ZTS |
| 2113 | + v ^= tsrm_thread_id(); |
| 2114 | + splitmix64(&v); |
| 2115 | +#endif |
| 2116 | + zend_mm_rand_seed64(&heap->rand_state, v); |
2038 | 2117 | }
|
2039 | 2118 |
|
2040 |
| - php_random_xoshiro256starstar_seed256(&heap->random_state, |
2041 |
| - seed[0], seed[1], seed[2], seed[3]); |
2042 |
| - |
2043 | 2119 | return zend_mm_refresh_key(heap);
|
2044 | 2120 | }
|
2045 | 2121 |
|
|
0 commit comments