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 <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2021-04-08 16:33:47 +02:00 committed by Anas Nashif
commit 1a69317eea
2 changed files with 9 additions and 4 deletions

View file

@ -46,6 +46,7 @@ struct shell_telnet {
* to send the shell prompt for instance. * to send the shell prompt for instance.
*/ */
struct k_work_delayable send_work; struct k_work_delayable send_work;
struct k_work_sync work_sync;
/** If set, no output is sent to the TELNET client. */ /** If set, no output is sent to the TELNET client. */
bool output_lock; bool output_lock;

View file

@ -43,7 +43,8 @@ static void telnet_end_client_connection(void)
sh_telnet->client_ctx = NULL; sh_telnet->client_ctx = NULL;
sh_telnet->output_lock = false; 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 */ /* Flush the RX FIFO */
while ((pkt = k_fifo_get(&sh_telnet->rx_fifo, K_NO_WAIT)) != NULL) { 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 */ /* OK, no output then */
sh_telnet->output_lock = true; sh_telnet->output_lock = true;
sh_telnet->line_out.len = 0; 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; break;
case NVT_CMD_AYT: case NVT_CMD_AYT:
telnet_reply_ay_command(); telnet_reply_ay_command();
@ -373,6 +375,7 @@ static int write(const struct shell_transport *transport,
size_t copy_len; size_t copy_len;
int err; int err;
uint32_t timeout; uint32_t timeout;
bool was_running;
if (sh_telnet == NULL) { if (sh_telnet == NULL) {
*cnt = 0; *cnt = 0;
@ -391,7 +394,8 @@ static int write(const struct shell_transport *transport,
*/ */
timeout = k_ticks_to_ms_ceil32( timeout = k_ticks_to_ms_ceil32(
k_work_delayable_remaining_get(&sh_telnet->send_work)); 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 { do {
if (lb->len + length - *cnt > TELNET_LINE_SIZE) { if (lb->len + length - *cnt > TELNET_LINE_SIZE) {
@ -421,7 +425,7 @@ static int write(const struct shell_transport *transport,
if (lb->len > 0) { if (lb->len > 0) {
/* Check if the timer was already running, initialize otherwise. /* 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)); k_work_reschedule(&sh_telnet->send_work, K_MSEC(timeout));
} }