mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 11:49:12 +00:00 
			
		
		
		
	Issue #18747: Use a parent atfork handler instead of a child atfork handler.
fork() is suppose to be async-signal safe but the handler calls unsafe functions. A parent handler mitigates the issue.
This commit is contained in:
		
							parent
							
								
									00ae435dee
								
							
						
					
					
						commit
						80c5de93f9
					
				
					 1 changed files with 9 additions and 12 deletions
				
			
		| 
						 | 
					@ -2585,23 +2585,25 @@ fails or if it does not provide enough data to seed PRNG.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Seed OpenSSL's PRNG at fork(), http://bugs.python.org/issue18747
 | 
					/* Seed OpenSSL's PRNG at fork(), http://bugs.python.org/issue18747
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * The child handler seeds the PRNG from pseudo-random data like pid, the
 | 
					 * The parent handler seeds the PRNG from pseudo-random data like pid, the
 | 
				
			||||||
 * current time (nanoseconds, miliseconds or seconds) and an uninitialized
 | 
					 * current time (miliseconds or seconds) and an uninitialized arry.
 | 
				
			||||||
 * array. The array contains stack variables that are impossible to predict
 | 
					 * The array contains stack variables that are impossible to predict
 | 
				
			||||||
 * on most systems, e.g. function return address (subject to ASLR), the
 | 
					 * on most systems, e.g. function return address (subject to ASLR), the
 | 
				
			||||||
 * stack protection canary and automatic variables.
 | 
					 * stack protection canary and automatic variables.
 | 
				
			||||||
 * The code is inspired by Apache's ssl_rand_seed() function.
 | 
					 * The code is inspired by Apache's ssl_rand_seed() function.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Note:
 | 
					 * Note:
 | 
				
			||||||
 * The code uses pthread_atfork() until Python has a proper atfork API. The
 | 
					 * The code uses pthread_atfork() until Python has a proper atfork API. The
 | 
				
			||||||
 * handlers are not removed from the child process.
 | 
					 * handlers are not removed from the child process. A parent handler is used
 | 
				
			||||||
 | 
					 * instead of a child handler because fork() is suppose to be async-signal
 | 
				
			||||||
 | 
					 * safe but the handler calls unsafe functions.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(HAVE_PTHREAD_ATFORK) && defined(WITH_THREAD)
 | 
					#if defined(HAVE_PTHREAD_ATFORK) && defined(WITH_THREAD)
 | 
				
			||||||
#define PYSSL_RAND_ATFORK 1
 | 
					#define PYSSL_RAND_ATFORK 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
PySSL_RAND_atfork_child(void)
 | 
					PySSL_RAND_atfork_parent(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        char stack[128];    /* uninitialized (!) stack data, 128 is an
 | 
					        char stack[128];    /* uninitialized (!) stack data, 128 is an
 | 
				
			||||||
| 
						 | 
					@ -2615,11 +2617,6 @@ PySSL_RAND_atfork_child(void)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    seed.pid = getpid();
 | 
					    seed.pid = getpid();
 | 
				
			||||||
    _PyTime_gettimeofday(&(seed.tp));
 | 
					    _PyTime_gettimeofday(&(seed.tp));
 | 
				
			||||||
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
    fprintf(stderr, "PySSL_RAND_atfork_child() seeds %i bytes in pid %i\n",
 | 
					 | 
				
			||||||
            (int)sizeof(seed), seed.pid);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
    RAND_add((unsigned char *)&seed, sizeof(seed), 0.0);
 | 
					    RAND_add((unsigned char *)&seed, sizeof(seed), 0.0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2633,8 +2630,8 @@ PySSL_RAND_atfork(void)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    retval = pthread_atfork(NULL,                     /* prepare */
 | 
					    retval = pthread_atfork(NULL,                     /* prepare */
 | 
				
			||||||
                            NULL,                     /* parent */
 | 
					                            PySSL_RAND_atfork_parent, /* parent */
 | 
				
			||||||
                            PySSL_RAND_atfork_child); /* child */
 | 
					                            NULL);                    /* child */
 | 
				
			||||||
    if (retval != 0) {
 | 
					    if (retval != 0) {
 | 
				
			||||||
        PyErr_SetFromErrno(PyExc_OSError);
 | 
					        PyErr_SetFromErrno(PyExc_OSError);
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue