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