From 5a257c9bfcaf9ba1face528c40d17c1728125d92 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 17 Jul 2025 17:46:53 +0200 Subject: [PATCH 1/3] Revert "tlshd: Add a SIGINT handler" This reverts commit bdc1bdb69715d9eb15086102989fa2c58296066e. Neither free() nor exit() are safe to call in a signal handler. Signed-off-by: Ben Hutchings --- src/tlshd/main.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/tlshd/main.c b/src/tlshd/main.c index f0f2aa7..649fe3f 100644 --- a/src/tlshd/main.c +++ b/src/tlshd/main.c @@ -61,17 +61,6 @@ static void usage(char *progname) fprintf(stderr, "usage: %s [-chsv]\n", progname); } -static void tlshd_sigint(int signum) -{ - if (signum == SIGINT) { - tlshd_gnutls_priority_deinit(); - tlshd_config_shutdown(); - tlshd_log_shutdown(); - tlshd_log_close(); - exit(EXIT_SUCCESS); - } -} - int main(int argc, char **argv) { static gchar config_file[PATH_MAX + 1] = "/etc/tlshd.conf"; @@ -124,8 +113,6 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - signal(SIGINT, tlshd_sigint); - tlshd_genl_dispatch(); tlshd_gnutls_priority_deinit(); From 853d14c65c676a5b0ec3d74d0f04760b2a311fc3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 17 Jul 2025 17:47:02 +0200 Subject: [PATCH 2/3] netlink: Introduce event loop and use signalfd to catch signals Currently we use a blocking netlink socket, which is not compatible with handling signals gracefully. To handle SIGINT properly: - Set the netlink socket to be non-blocking - Block SIGINT and create a signalfd() to receive it - Poll the netlink socket and signal fd in a loop Signed-off-by: Ben Hutchings --- src/tlshd/netlink.c | 52 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/src/tlshd/netlink.c b/src/tlshd/netlink.c index f716232..2fccbde 100644 --- a/src/tlshd/netlink.c +++ b/src/tlshd/netlink.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,9 @@ tlshd_accept_nl_policy[HANDSHAKE_A_ACCEPT_MAX + 1] = { static struct nl_sock *tlshd_notification_nls; +static sigset_t tlshd_sig_poll_mask; +static int tlshd_sig_poll_fd; + static int tlshd_genl_event_handler(struct nl_msg *msg, __attribute__ ((unused)) void *arg) { @@ -127,6 +131,9 @@ static int tlshd_genl_event_handler(struct nl_msg *msg, if (!fork()) { /* child */ + close(tlshd_sig_poll_fd); + sigprocmask(SIG_UNBLOCK, &tlshd_sig_poll_mask, NULL); + nlmsg_free(msg); tlshd_genl_sock_close(tlshd_notification_nls); @@ -146,8 +153,13 @@ static int tlshd_genl_event_handler(struct nl_msg *msg, */ void tlshd_genl_dispatch(void) { + struct pollfd poll_fds[2]; int err, mcgrp; + /* Initialise signal poll mask */ + sigemptyset(&tlshd_sig_poll_mask); + sigaddset(&tlshd_sig_poll_mask, SIGINT); + err = tlshd_genl_sock_open(&tlshd_notification_nls); if (err) return; @@ -174,14 +186,46 @@ void tlshd_genl_dispatch(void) } nl_socket_disable_seq_check(tlshd_notification_nls); - while (true) { - err = nl_recvmsgs_default(tlshd_notification_nls); - if (err < 0) { - tlshd_log_nl_error("nl_recvmsgs", err); + + err = nl_socket_set_nonblocking(tlshd_notification_nls); + if (err != NLE_SUCCESS) { + tlshd_log_nl_error("nl_socket_set_nonblocking", err); + goto out_close; + } + + if (sigprocmask(SIG_BLOCK, &tlshd_sig_poll_mask, NULL)) { + tlshd_log_perror("sigprocmask"); + goto out_close; + } + + tlshd_sig_poll_fd = signalfd(-1, &tlshd_sig_poll_mask, + SFD_NONBLOCK | SFD_CLOEXEC); + if (tlshd_sig_poll_fd < 0) { + tlshd_log_perror("signalfd"); + goto out_close; + } + + poll_fds[0].fd = nl_socket_get_fd(tlshd_notification_nls); + poll_fds[0].events = POLLIN; + poll_fds[1].fd = tlshd_sig_poll_fd; + poll_fds[1].events = POLLIN; + + while (poll(poll_fds, ARRAY_SIZE(poll_fds), -1) >= 0) { + if (poll_fds[1].revents) + /* exit signal received */ break; + + if (poll_fds[0].revents) { + err = nl_recvmsgs_default(tlshd_notification_nls); + if (err < 0) { + tlshd_log_nl_error("nl_recvmsgs", err); + break; + } } }; + close(tlshd_sig_poll_fd); + out_close: tlshd_genl_sock_close(tlshd_notification_nls); } From a75ad796c18e1e34afecf54e699d248835e7ad80 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 17 Jul 2025 18:32:06 +0200 Subject: [PATCH 3/3] netlink: Handle SIGTERM like SIGINT systemd's default stop signal and the kill command's default signal are SIGTERM. Catch this as well as SIGINT. Signed-off-by: Ben Hutchings --- src/tlshd/netlink.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tlshd/netlink.c b/src/tlshd/netlink.c index 2fccbde..c08e5e5 100644 --- a/src/tlshd/netlink.c +++ b/src/tlshd/netlink.c @@ -159,6 +159,7 @@ void tlshd_genl_dispatch(void) /* Initialise signal poll mask */ sigemptyset(&tlshd_sig_poll_mask); sigaddset(&tlshd_sig_poll_mask, SIGINT); + sigaddset(&tlshd_sig_poll_mask, SIGTERM); err = tlshd_genl_sock_open(&tlshd_notification_nls); if (err)