From 1a69317eea47830444f088e9cce128d01af5df8c Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 8 Apr 2021 16:33:47 +0200 Subject: [PATCH] shell: telnet: Make sure the delayed work becomes idle after canceling Replace k_work_cancel_delayable() with k_work_cancel_delayable_sync() to make sure that the submitted work becomes idle before accessing sensitive data. Signed-off-by: Robert Lubos --- include/shell/shell_telnet.h | 1 + subsys/shell/shell_telnet.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/shell/shell_telnet.h b/include/shell/shell_telnet.h index b183c0694d6..b1a1189b017 100644 --- a/include/shell/shell_telnet.h +++ b/include/shell/shell_telnet.h @@ -46,6 +46,7 @@ struct shell_telnet { * to send the shell prompt for instance. */ struct k_work_delayable send_work; + struct k_work_sync work_sync; /** If set, no output is sent to the TELNET client. */ bool output_lock; diff --git a/subsys/shell/shell_telnet.c b/subsys/shell/shell_telnet.c index d9f9dcf3c2b..6d38e09d98e 100644 --- a/subsys/shell/shell_telnet.c +++ b/subsys/shell/shell_telnet.c @@ -43,7 +43,8 @@ static void telnet_end_client_connection(void) sh_telnet->client_ctx = NULL; sh_telnet->output_lock = false; - k_work_cancel_delayable(&sh_telnet->send_work); + k_work_cancel_delayable_sync(&sh_telnet->send_work, + &sh_telnet->work_sync); /* Flush the RX FIFO */ while ((pkt = k_fifo_get(&sh_telnet->rx_fifo, K_NO_WAIT)) != NULL) { @@ -109,7 +110,8 @@ static void telnet_reply_command(struct telnet_simple_command *cmd) /* OK, no output then */ sh_telnet->output_lock = true; sh_telnet->line_out.len = 0; - k_work_cancel_delayable(&sh_telnet->send_work); + k_work_cancel_delayable_sync(&sh_telnet->send_work, + &sh_telnet->work_sync); break; case NVT_CMD_AYT: telnet_reply_ay_command(); @@ -373,6 +375,7 @@ static int write(const struct shell_transport *transport, size_t copy_len; int err; uint32_t timeout; + bool was_running; if (sh_telnet == NULL) { *cnt = 0; @@ -391,7 +394,8 @@ static int write(const struct shell_transport *transport, */ timeout = k_ticks_to_ms_ceil32( k_work_delayable_remaining_get(&sh_telnet->send_work)); - k_work_cancel_delayable(&sh_telnet->send_work); + was_running = k_work_cancel_delayable_sync(&sh_telnet->send_work, + &sh_telnet->work_sync); do { if (lb->len + length - *cnt > TELNET_LINE_SIZE) { @@ -421,7 +425,7 @@ static int write(const struct shell_transport *transport, if (lb->len > 0) { /* Check if the timer was already running, initialize otherwise. */ - timeout = (timeout == 0) ? TELNET_TIMEOUT : timeout; + timeout = was_running ? timeout : TELNET_TIMEOUT; k_work_reschedule(&sh_telnet->send_work, K_MSEC(timeout)); }