• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "Python.h"
2 #include "pycore_fileutils.h"     // _Py_fstat_noraise()
3 #include "pycore_initconfig.h"
4 #include "pycore_pylifecycle.h"   // _PyOS_URandomNonblock()
5 #include "pycore_runtime.h"       // _PyRuntime
6 
7 #ifdef HAVE_UNISTD_H
8 #  include <unistd.h>             // close()
9 #endif
10 #ifdef MS_WINDOWS
11 #  include <windows.h>
12 #  include <bcrypt.h>
13 #else
14 #  include <fcntl.h>              // O_RDONLY
15 #  ifdef HAVE_SYS_STAT_H
16 #    include <sys/stat.h>
17 #  endif
18 #  ifdef HAVE_LINUX_RANDOM_H
19 #    include <linux/random.h>     // GRND_NONBLOCK
20 #  endif
21 #  if defined(HAVE_SYS_RANDOM_H) && (defined(HAVE_GETRANDOM) || defined(HAVE_GETENTROPY))
22 #    include <sys/random.h>       // getrandom()
23 #  endif
24 #  if !defined(HAVE_GETRANDOM) && defined(HAVE_GETRANDOM_SYSCALL)
25 #    include <sys/syscall.h>      // SYS_getrandom
26 #  endif
27 #endif
28 
29 #ifdef _Py_MEMORY_SANITIZER
30 #  include <sanitizer/msan_interface.h>
31 #endif
32 
33 #if defined(__APPLE__) && defined(__has_builtin)
34 #  if __has_builtin(__builtin_available)
35 #    define HAVE_GETENTRYPY_GETRANDOM_RUNTIME __builtin_available(macOS 10.12, iOS 10.10, tvOS 10.0, watchOS 3.0, *)
36 #  endif
37 #endif
38 #ifndef HAVE_GETENTRYPY_GETRANDOM_RUNTIME
39 #  define HAVE_GETENTRYPY_GETRANDOM_RUNTIME 1
40 #endif
41 
42 
43 #ifdef Py_DEBUG
44 int _Py_HashSecret_Initialized = 0;
45 #else
46 static int _Py_HashSecret_Initialized = 0;
47 #endif
48 
49 #ifdef MS_WINDOWS
50 
51 /* Fill buffer with size pseudo-random bytes generated by the Windows CryptoGen
52    API. Return 0 on success, or raise an exception and return -1 on error. */
53 static int
win32_urandom(unsigned char * buffer,Py_ssize_t size,int raise)54 win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
55 {
56     while (size > 0)
57     {
58         DWORD chunk = (DWORD)Py_MIN(size, PY_DWORD_MAX);
59         NTSTATUS status = BCryptGenRandom(NULL, buffer, chunk, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
60         if (!BCRYPT_SUCCESS(status)) {
61             /* BCryptGenRandom() failed */
62             if (raise) {
63                 PyErr_SetFromWindowsErr(0);
64             }
65             return -1;
66         }
67         buffer += chunk;
68         size -= chunk;
69     }
70     return 0;
71 }
72 
73 #else /* !MS_WINDOWS */
74 
75 #if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
76 #define PY_GETRANDOM 1
77 
78 /* Call getrandom() to get random bytes:
79 
80    - Return 1 on success
81    - Return 0 if getrandom() is not available (failed with ENOSYS or EPERM),
82      or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not
83      initialized yet) and raise=0.
84    - Raise an exception (if raise is non-zero) and return -1 on error:
85      if getrandom() failed with EINTR, raise is non-zero and the Python signal
86      handler raised an exception, or if getrandom() failed with a different
87      error.
88 
89    getrandom() is retried if it failed with EINTR: interrupted by a signal. */
90 static int
py_getrandom(void * buffer,Py_ssize_t size,int blocking,int raise)91 py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
92 {
93     /* Is getrandom() supported by the running kernel? Set to 0 if getrandom()
94        failed with ENOSYS or EPERM. Need Linux kernel 3.17 or newer, or Solaris
95        11.3 or newer */
96     static int getrandom_works = 1;
97     int flags;
98     char *dest;
99     long n;
100 
101     if (!getrandom_works) {
102         return 0;
103     }
104 
105     flags = blocking ? 0 : GRND_NONBLOCK;
106     dest = buffer;
107     while (0 < size) {
108 #if defined(__sun) && defined(__SVR4)
109         /* Issue #26735: On Solaris, getrandom() is limited to returning up
110            to 1024 bytes. Call it multiple times if more bytes are
111            requested. */
112         n = Py_MIN(size, 1024);
113 #else
114         n = Py_MIN(size, LONG_MAX);
115 #endif
116 
117         errno = 0;
118 #ifdef HAVE_GETRANDOM
119         if (raise) {
120             Py_BEGIN_ALLOW_THREADS
121             n = getrandom(dest, n, flags);
122             Py_END_ALLOW_THREADS
123         }
124         else {
125             n = getrandom(dest, n, flags);
126         }
127 #else
128         /* On Linux, use the syscall() function because the GNU libc doesn't
129            expose the Linux getrandom() syscall yet. See:
130            https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */
131         if (raise) {
132             Py_BEGIN_ALLOW_THREADS
133             n = syscall(SYS_getrandom, dest, n, flags);
134             Py_END_ALLOW_THREADS
135         }
136         else {
137             n = syscall(SYS_getrandom, dest, n, flags);
138         }
139 #  ifdef _Py_MEMORY_SANITIZER
140         if (n > 0) {
141              __msan_unpoison(dest, n);
142         }
143 #  endif
144 #endif
145 
146         if (n < 0) {
147             /* ENOSYS: the syscall is not supported by the kernel.
148                EPERM: the syscall is blocked by a security policy (ex: SECCOMP)
149                or something else. */
150             if (errno == ENOSYS || errno == EPERM) {
151                 getrandom_works = 0;
152                 return 0;
153             }
154 
155             /* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system urandom
156                is not initialized yet. For _PyRandom_Init(), we ignore the
157                error and fall back on reading /dev/urandom which never blocks,
158                even if the system urandom is not initialized yet:
159                see the PEP 524. */
160             if (errno == EAGAIN && !raise && !blocking) {
161                 return 0;
162             }
163 
164             if (errno == EINTR) {
165                 if (raise) {
166                     if (PyErr_CheckSignals()) {
167                         return -1;
168                     }
169                 }
170 
171                 /* retry getrandom() if it was interrupted by a signal */
172                 continue;
173             }
174 
175             if (raise) {
176                 PyErr_SetFromErrno(PyExc_OSError);
177             }
178             return -1;
179         }
180 
181         dest += n;
182         size -= n;
183     }
184     return 1;
185 }
186 
187 #elif defined(HAVE_GETENTROPY)
188 #define PY_GETENTROPY 1
189 
190 /* Fill buffer with size pseudo-random bytes generated by getentropy():
191 
192    - Return 1 on success
193    - Return 0 if getentropy() syscall is not available (failed with ENOSYS or
194      EPERM).
195    - Raise an exception (if raise is non-zero) and return -1 on error:
196      if getentropy() failed with EINTR, raise is non-zero and the Python signal
197      handler raised an exception, or if getentropy() failed with a different
198      error.
199 
200    getentropy() is retried if it failed with EINTR: interrupted by a signal. */
201 
202 #if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)
203 static int
204 py_getentropy(char *buffer, Py_ssize_t size, int raise)
205         __attribute__((availability(macos,introduced=10.12)))
206         __attribute__((availability(ios,introduced=10.0)))
207         __attribute__((availability(tvos,introduced=10.0)))
208         __attribute__((availability(watchos,introduced=3.0)));
209 #endif
210 
211 static int
py_getentropy(char * buffer,Py_ssize_t size,int raise)212 py_getentropy(char *buffer, Py_ssize_t size, int raise)
213 {
214     /* Is getentropy() supported by the running kernel? Set to 0 if
215        getentropy() failed with ENOSYS or EPERM. */
216     static int getentropy_works = 1;
217 
218     if (!getentropy_works) {
219         return 0;
220     }
221 
222     while (size > 0) {
223         /* getentropy() is limited to returning up to 256 bytes. Call it
224            multiple times if more bytes are requested. */
225         Py_ssize_t len = Py_MIN(size, 256);
226         int res;
227 
228         if (raise) {
229             Py_BEGIN_ALLOW_THREADS
230             res = getentropy(buffer, len);
231             Py_END_ALLOW_THREADS
232         }
233         else {
234             res = getentropy(buffer, len);
235         }
236 
237         if (res < 0) {
238             /* ENOSYS: the syscall is not supported by the running kernel.
239                EPERM: the syscall is blocked by a security policy (ex: SECCOMP)
240                or something else. */
241             if (errno == ENOSYS || errno == EPERM) {
242                 getentropy_works = 0;
243                 return 0;
244             }
245 
246             if (errno == EINTR) {
247                 if (raise) {
248                     if (PyErr_CheckSignals()) {
249                         return -1;
250                     }
251                 }
252 
253                 /* retry getentropy() if it was interrupted by a signal */
254                 continue;
255             }
256 
257             if (raise) {
258                 PyErr_SetFromErrno(PyExc_OSError);
259             }
260             return -1;
261         }
262 
263         buffer += len;
264         size -= len;
265     }
266     return 1;
267 }
268 #endif /* defined(HAVE_GETENTROPY) && !(defined(__sun) && defined(__SVR4)) */
269 
270 
271 #define urandom_cache (_PyRuntime.pyhash_state.urandom_cache)
272 
273 /* Read random bytes from the /dev/urandom device:
274 
275    - Return 0 on success
276    - Raise an exception (if raise is non-zero) and return -1 on error
277 
278    Possible causes of errors:
279 
280    - open() failed with ENOENT, ENXIO, ENODEV, EACCES: the /dev/urandom device
281      was not found. For example, it was removed manually or not exposed in a
282      chroot or container.
283    - open() failed with a different error
284    - fstat() failed
285    - read() failed or returned 0
286 
287    read() is retried if it failed with EINTR: interrupted by a signal.
288 
289    The file descriptor of the device is kept open between calls to avoid using
290    many file descriptors when run in parallel from multiple threads:
291    see the issue #18756.
292 
293    st_dev and st_ino fields of the file descriptor (from fstat()) are cached to
294    check if the file descriptor was replaced by a different file (which is
295    likely a bug in the application): see the issue #21207.
296 
297    If the file descriptor was closed or replaced, open a new file descriptor
298    but don't close the old file descriptor: it probably points to something
299    important for some third-party code. */
300 static int
dev_urandom(char * buffer,Py_ssize_t size,int raise)301 dev_urandom(char *buffer, Py_ssize_t size, int raise)
302 {
303     int fd;
304     Py_ssize_t n;
305 
306     if (raise) {
307         struct _Py_stat_struct st;
308         int fstat_result;
309 
310         if (urandom_cache.fd >= 0) {
311             Py_BEGIN_ALLOW_THREADS
312             fstat_result = _Py_fstat_noraise(urandom_cache.fd, &st);
313             Py_END_ALLOW_THREADS
314 
315             /* Does the fd point to the same thing as before? (issue #21207) */
316             if (fstat_result
317                 || st.st_dev != urandom_cache.st_dev
318                 || st.st_ino != urandom_cache.st_ino) {
319                 /* Something changed: forget the cached fd (but don't close it,
320                    since it probably points to something important for some
321                    third-party code). */
322                 urandom_cache.fd = -1;
323             }
324         }
325         if (urandom_cache.fd >= 0)
326             fd = urandom_cache.fd;
327         else {
328             fd = _Py_open("/dev/urandom", O_RDONLY);
329             if (fd < 0) {
330                 if (errno == ENOENT || errno == ENXIO ||
331                     errno == ENODEV || errno == EACCES) {
332                     PyErr_SetString(PyExc_NotImplementedError,
333                                     "/dev/urandom (or equivalent) not found");
334                 }
335                 /* otherwise, keep the OSError exception raised by _Py_open() */
336                 return -1;
337             }
338             if (urandom_cache.fd >= 0) {
339                 /* urandom_fd was initialized by another thread while we were
340                    not holding the GIL, keep it. */
341                 close(fd);
342                 fd = urandom_cache.fd;
343             }
344             else {
345                 if (_Py_fstat(fd, &st)) {
346                     close(fd);
347                     return -1;
348                 }
349                 else {
350                     urandom_cache.fd = fd;
351                     urandom_cache.st_dev = st.st_dev;
352                     urandom_cache.st_ino = st.st_ino;
353                 }
354             }
355         }
356 
357         do {
358             n = _Py_read(fd, buffer, (size_t)size);
359             if (n == -1)
360                 return -1;
361             if (n == 0) {
362                 PyErr_Format(PyExc_RuntimeError,
363                         "Failed to read %zi bytes from /dev/urandom",
364                         size);
365                 return -1;
366             }
367 
368             buffer += n;
369             size -= n;
370         } while (0 < size);
371     }
372     else {
373         fd = _Py_open_noraise("/dev/urandom", O_RDONLY);
374         if (fd < 0) {
375             return -1;
376         }
377 
378         while (0 < size)
379         {
380             do {
381                 n = read(fd, buffer, (size_t)size);
382             } while (n < 0 && errno == EINTR);
383 
384             if (n <= 0) {
385                 /* stop on error or if read(size) returned 0 */
386                 close(fd);
387                 return -1;
388             }
389 
390             buffer += n;
391             size -= n;
392         }
393         close(fd);
394     }
395     return 0;
396 }
397 
398 static void
dev_urandom_close(void)399 dev_urandom_close(void)
400 {
401     if (urandom_cache.fd >= 0) {
402         close(urandom_cache.fd);
403         urandom_cache.fd = -1;
404     }
405 }
406 
407 #undef urandom_cache
408 
409 #endif /* !MS_WINDOWS */
410 
411 
412 /* Fill buffer with pseudo-random bytes generated by a linear congruent
413    generator (LCG):
414 
415        x(n+1) = (x(n) * 214013 + 2531011) % 2^32
416 
417    Use bits 23..16 of x(n) to generate a byte. */
418 static void
lcg_urandom(unsigned int x0,unsigned char * buffer,size_t size)419 lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size)
420 {
421     size_t index;
422     unsigned int x;
423 
424     x = x0;
425     for (index=0; index < size; index++) {
426         x *= 214013;
427         x += 2531011;
428         /* modulo 2 ^ (8 * sizeof(int)) */
429         buffer[index] = (x >> 16) & 0xff;
430     }
431 }
432 
433 /* Read random bytes:
434 
435    - Return 0 on success
436    - Raise an exception (if raise is non-zero) and return -1 on error
437 
438    Used sources of entropy ordered by preference, preferred source first:
439 
440    - BCryptGenRandom() on Windows
441    - getrandom() function (ex: Linux and Solaris): call py_getrandom()
442    - getentropy() function (ex: OpenBSD): call py_getentropy()
443    - /dev/urandom device
444 
445    Read from the /dev/urandom device if getrandom() or getentropy() function
446    is not available or does not work.
447 
448    Prefer getrandom() over getentropy() because getrandom() supports blocking
449    and non-blocking mode: see the PEP 524. Python requires non-blocking RNG at
450    startup to initialize its hash secret, but os.urandom() must block until the
451    system urandom is initialized (at least on Linux 3.17 and newer).
452 
453    Prefer getrandom() and getentropy() over reading directly /dev/urandom
454    because these functions don't need file descriptors and so avoid ENFILE or
455    EMFILE errors (too many open files): see the issue #18756.
456 
457    Only the getrandom() function supports non-blocking mode.
458 
459    Only use RNG running in the kernel. They are more secure because it is
460    harder to get the internal state of a RNG running in the kernel land than a
461    RNG running in the user land. The kernel has a direct access to the hardware
462    and has access to hardware RNG, they are used as entropy sources.
463 
464    Note: the OpenSSL RAND_pseudo_bytes() function does not automatically reseed
465    its RNG on fork(), two child processes (with the same pid) generate the same
466    random numbers: see issue #18747. Kernel RNGs don't have this issue,
467    they have access to good quality entropy sources.
468 
469    If raise is zero:
470 
471    - Don't raise an exception on error
472    - Don't call the Python signal handler (don't call PyErr_CheckSignals()) if
473      a function fails with EINTR: retry directly the interrupted function
474    - Don't release the GIL to call functions.
475 */
476 static int
pyurandom(void * buffer,Py_ssize_t size,int blocking,int raise)477 pyurandom(void *buffer, Py_ssize_t size, int blocking, int raise)
478 {
479 #if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
480     int res;
481 #endif
482 
483     if (size < 0) {
484         if (raise) {
485             PyErr_Format(PyExc_ValueError,
486                          "negative argument not allowed");
487         }
488         return -1;
489     }
490 
491     if (size == 0) {
492         return 0;
493     }
494 
495 #ifdef MS_WINDOWS
496     return win32_urandom((unsigned char *)buffer, size, raise);
497 #else
498 
499 #if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
500     if (HAVE_GETENTRYPY_GETRANDOM_RUNTIME) {
501 #ifdef PY_GETRANDOM
502         res = py_getrandom(buffer, size, blocking, raise);
503 #else
504         res = py_getentropy(buffer, size, raise);
505 #endif
506         if (res < 0) {
507             return -1;
508         }
509         if (res == 1) {
510             return 0;
511         }
512         /* getrandom() or getentropy() function is not available: failed with
513            ENOSYS or EPERM. Fall back on reading from /dev/urandom. */
514         } /* end of availability block */
515 #endif
516 
517     return dev_urandom(buffer, size, raise);
518 #endif
519 }
520 
521 /* Fill buffer with size pseudo-random bytes from the operating system random
522    number generator (RNG). It is suitable for most cryptographic purposes
523    except long living private keys for asymmetric encryption.
524 
525    On Linux 3.17 and newer, the getrandom() syscall is used in blocking mode:
526    block until the system urandom entropy pool is initialized (128 bits are
527    collected by the kernel).
528 
529    Return 0 on success. Raise an exception and return -1 on error. */
530 int
_PyOS_URandom(void * buffer,Py_ssize_t size)531 _PyOS_URandom(void *buffer, Py_ssize_t size)
532 {
533     return pyurandom(buffer, size, 1, 1);
534 }
535 
536 /* Fill buffer with size pseudo-random bytes from the operating system random
537    number generator (RNG). It is not suitable for cryptographic purpose.
538 
539    On Linux 3.17 and newer (when getrandom() syscall is used), if the system
540    urandom is not initialized yet, the function returns "weak" entropy read
541    from /dev/urandom.
542 
543    Return 0 on success. Raise an exception and return -1 on error. */
544 int
_PyOS_URandomNonblock(void * buffer,Py_ssize_t size)545 _PyOS_URandomNonblock(void *buffer, Py_ssize_t size)
546 {
547     return pyurandom(buffer, size, 0, 1);
548 }
549 
550 
551 PyStatus
_Py_HashRandomization_Init(const PyConfig * config)552 _Py_HashRandomization_Init(const PyConfig *config)
553 {
554     void *secret = &_Py_HashSecret;
555     Py_ssize_t secret_size = sizeof(_Py_HashSecret_t);
556 
557     if (_Py_HashSecret_Initialized) {
558         return _PyStatus_OK();
559     }
560     _Py_HashSecret_Initialized = 1;
561 
562     if (config->use_hash_seed) {
563         if (config->hash_seed == 0) {
564             /* disable the randomized hash */
565             memset(secret, 0, secret_size);
566         }
567         else {
568             /* use the specified hash seed */
569             lcg_urandom(config->hash_seed, secret, secret_size);
570         }
571     }
572     else {
573         /* use a random hash seed */
574         int res;
575 
576         /* _PyRandom_Init() is called very early in the Python initialization
577            and so exceptions cannot be used (use raise=0).
578 
579            _PyRandom_Init() must not block Python initialization: call
580            pyurandom() is non-blocking mode (blocking=0): see the PEP 524. */
581         res = pyurandom(secret, secret_size, 0, 0);
582         if (res < 0) {
583             return _PyStatus_ERR("failed to get random numbers "
584                                  "to initialize Python");
585         }
586     }
587     return _PyStatus_OK();
588 }
589 
590 
591 void
_Py_HashRandomization_Fini(void)592 _Py_HashRandomization_Fini(void)
593 {
594 #ifndef MS_WINDOWS
595     dev_urandom_close();
596 #endif
597 }
598