On Thu, May 02, 2019 at 03:34:22PM +0100, Robert Allen1 wrote:
> Hi,
>  
> I spent some time digging into the FD leak and I've pinpointed it: it's an 
> interaction between HAProxy re-exec and a change to keep the random 
> devices open by default in OpenSSL 1.1.1 -- specifically 
> https://github.com/openssl/openssl/commit/c7504aeb640a88949dfe3146f7e0f275f517464c
>  
> Since a lot of different RAND_* family functions cause initialisation, 
> that explains why hacking out ssl_initialize_random didn't work for us; 
> some other part of reloading just ended up opening the random devices and 
> then leaking the handles on the next exec().
>  
> Anyway, from experimentation, we can close the leak with a patch like (but 
> obviously better abstracted than) this one against 1.9.6:
>  
> diff --git a/src/haproxy.c b/src/haproxy.c
> index 1cb10391..d3482f46 100644
> --- a/src/haproxy.c
> +++ b/src/haproxy.c
> @@ -737,6 +737,10 @@ void mworker_reload()
>                 ptdf->fct();
>         if (fdtab)
>                 deinit_pollers();
> +       /* Close OpenSSL random devices, if open */
> +       /* Note: If not already initialised, this may cause OpenSSL 
> rand_lib initialisation... */
> +       void RAND_keep_random_devices_open(int keep);
> +       RAND_keep_random_devices_open(0);
>         /* restore the initial FD limits */
>         limit.rlim_cur = rlim_fd_cur_at_boot;
>  
> From reading in the OpenSSL code, I assume that the use of O_RDONLY 
> without O_CLOEXEC or a fcntl is intentional so that it doesn't have to 
> re-open the devices on fork().
>  
> So it looks like the best place to solve this is around there ^^, although 
> it needs to be wrapped up in ssl_sock.c with appropriate version guards on 
> the OpenSSL version.
>  
> Any thoughts on the above and how to proceed?
>  
> Rob
> 

Hi Robert,

I think that the right thing to do, we should probably just call
RAND_keep_random_devices_open(0); in the mworker_reload function.

You just need to check the SSL macros for the build and the minimum openssl
version (1.1.1), so probably something like this:

#if defined(USE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10101000L)
    RAND_keep_random_devices_open(0);
#endif

I don't think we need anything in ssl_sock.c though.

Regards,

-- 
William Lallemand

Reply via email to