BUG/MEDIUM: ssl/fd: unexpected fd close using async engine

Before 2.3, after an async crypto processing or on session close, the engine
async file's descriptors were removed from the fdtab but not closed because
it is the engine which has created the file descriptor, and it is responsible
for closing it. In 2.3 the fd_remove() call was replaced by fd_stop_both()
which stops the polling but does not remove the fd from the fdtab and the
fd remains indefinitively in the fdtab.

A simple replacement by fd_delete() is not a valid fix because fd_delete()
removes the fd from the fdtab but also closes the fd. And the fd will be
closed twice: by the haproxy's core and by the engine itself.

Instead, let's set FD_DISOWN on the FD before calling fd_delete() which will
take care of not closing it.

This patch must be backported on branches >= 2.3, and it relies on this
previous patch:

   MINOR: fd: add a new FD_DISOWN flag to prevent from closing a deleted FD

As mentioned in the patch above, a different flag will be needed in 2.3.
This commit is contained in:
Emeric Brun 2022-07-01 17:36:50 +02:00 committed by Willy Tarreau
parent f41a3f6762
commit 7d392a592d

View File

@ -776,8 +776,14 @@ void ssl_async_fd_free(int fd)
}
SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
for (i=0 ; i < num_all_fds ; i++)
fd_stop_both(all_fd[i]);
for (i=0 ; i < num_all_fds ; i++) {
/* We want to remove the fd from the fdtab
* but we flag it to disown because the
* close is performed by the engine itself
*/
fdtab[all_fd[i]].state |= FD_DISOWN;
fd_delete(all_fd[i]);
}
/* Now we can safely call SSL_free, no more pending job in engines */
SSL_free(ssl);
@ -807,8 +813,14 @@ static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
/* We remove unused fds from the fdtab */
for (i=0 ; i < num_del_fds ; i++)
fd_stop_both(del_fd[i]);
for (i=0 ; i < num_del_fds ; i++) {
/* We want to remove the fd from the fdtab
* but we flag it to disown because the
* close is performed by the engine itself
*/
fdtab[del_fd[i]].state |= FD_DISOWN;
fd_delete(del_fd[i]);
}
/* We add new fds to the fdtab */
for (i=0 ; i < num_add_fds ; i++) {
@ -6796,8 +6808,14 @@ void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
* because the fd is owned by the engine.
* the engine is responsible to close
*/
for (i=0 ; i < num_all_fds ; i++)
fd_stop_both(all_fd[i]);
for (i=0 ; i < num_all_fds ; i++) {
/* We want to remove the fd from the fdtab
* but we flag it to disown because the
* close is performed by the engine itself
*/
fdtab[all_fd[i]].state |= FD_DISOWN;
fd_delete(all_fd[i]);
}
}
#endif
SSL_free(ctx->ssl);