shell: Add synchronization for prompt-string access in shell
Resolved a data race in shell.c by copying the user-provided prompt-string into a private buffer within the shell, ensuring proper synchronization with the shell-thread. Fixes: #64972 Signed-off-by: Jakub Rzeszutko <jakub.rzeszutko@verkada.com>
This commit is contained in:
parent
7a8d454e22
commit
f8263e8293
3 changed files with 55 additions and 4 deletions
|
@ -26,6 +26,10 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_SHELL_PROMPT_BUFF_SIZE
|
||||||
|
#define CONFIG_SHELL_PROMPT_BUFF_SIZE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_SHELL_CMD_BUFF_SIZE
|
#ifndef CONFIG_SHELL_CMD_BUFF_SIZE
|
||||||
#define CONFIG_SHELL_CMD_BUFF_SIZE 0
|
#define CONFIG_SHELL_CMD_BUFF_SIZE 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -779,7 +783,11 @@ enum shell_signal {
|
||||||
* @brief Shell instance context.
|
* @brief Shell instance context.
|
||||||
*/
|
*/
|
||||||
struct shell_ctx {
|
struct shell_ctx {
|
||||||
const char *prompt; /*!< shell current prompt. */
|
#if defined(CONFIG_SHELL_PROMPT_CHANGE) && CONFIG_SHELL_PROMPT_CHANGE
|
||||||
|
char prompt[CONFIG_SHELL_PROMPT_BUFF_SIZE]; /*!< shell current prompt. */
|
||||||
|
#else
|
||||||
|
const char *prompt;
|
||||||
|
#endif
|
||||||
|
|
||||||
enum shell_state state; /*!< Internal module state.*/
|
enum shell_state state; /*!< Internal module state.*/
|
||||||
enum shell_receive_state receive_state;/*!< Escape sequence indicator.*/
|
enum shell_receive_state receive_state;/*!< Escape sequence indicator.*/
|
||||||
|
|
|
@ -55,6 +55,24 @@ config SHELL_BACKSPACE_MODE_DELETE
|
||||||
Some terminals send code: 0x08 (backspace) other 0x7F (delete). When
|
Some terminals send code: 0x08 (backspace) other 0x7F (delete). When
|
||||||
this option is set shell will expect 0x7F for backspace key.
|
this option is set shell will expect 0x7F for backspace key.
|
||||||
|
|
||||||
|
config SHELL_PROMPT_CHANGE
|
||||||
|
bool "Allow prompt change in runtime"
|
||||||
|
default y if !SHELL_MINIMAL
|
||||||
|
help
|
||||||
|
Allow for the modification of the shell prompt at runtime.
|
||||||
|
Enabling this will allocate additional RAM memory where
|
||||||
|
the string of the prompt will be stored.
|
||||||
|
|
||||||
|
config SHELL_PROMPT_BUFF_SIZE
|
||||||
|
int "Shell prompt buffer size"
|
||||||
|
depends on SHELL_PROMPT_CHANGE
|
||||||
|
range 2 40
|
||||||
|
default 10 if SHELL_MINIMAL
|
||||||
|
default 20
|
||||||
|
help
|
||||||
|
Maximum prompt size in bytes. One byte is reserved for the string
|
||||||
|
terminator character.
|
||||||
|
|
||||||
config SHELL_CMD_BUFF_SIZE
|
config SHELL_CMD_BUFF_SIZE
|
||||||
int "Shell command buffer size"
|
int "Shell command buffer size"
|
||||||
default 128 if SHELL_MINIMAL
|
default 128 if SHELL_MINIMAL
|
||||||
|
|
|
@ -1208,7 +1208,6 @@ static int instance_init(const struct shell *sh,
|
||||||
(sh->shell_flag == SHELL_FLAG_OLF_CRLF));
|
(sh->shell_flag == SHELL_FLAG_OLF_CRLF));
|
||||||
|
|
||||||
memset(sh->ctx, 0, sizeof(*sh->ctx));
|
memset(sh->ctx, 0, sizeof(*sh->ctx));
|
||||||
sh->ctx->prompt = sh->default_prompt;
|
|
||||||
if (CONFIG_SHELL_CMD_ROOT[0]) {
|
if (CONFIG_SHELL_CMD_ROOT[0]) {
|
||||||
sh->ctx->selected_cmd = root_cmd_find(CONFIG_SHELL_CMD_ROOT);
|
sh->ctx->selected_cmd = root_cmd_find(CONFIG_SHELL_CMD_ROOT);
|
||||||
}
|
}
|
||||||
|
@ -1235,7 +1234,13 @@ static int instance_init(const struct shell *sh,
|
||||||
CONFIG_SHELL_DEFAULT_TERMINAL_WIDTH;
|
CONFIG_SHELL_DEFAULT_TERMINAL_WIDTH;
|
||||||
sh->ctx->vt100_ctx.cons.terminal_hei =
|
sh->ctx->vt100_ctx.cons.terminal_hei =
|
||||||
CONFIG_SHELL_DEFAULT_TERMINAL_HEIGHT;
|
CONFIG_SHELL_DEFAULT_TERMINAL_HEIGHT;
|
||||||
|
|
||||||
|
#if defined(CONFIG_SHELL_PROMPT_CHANGE) && CONFIG_SHELL_PROMPT_CHANGE
|
||||||
|
shell_prompt_change(sh, sh->default_prompt);
|
||||||
|
#else
|
||||||
|
sh->ctx->prompt = sh->default_prompt;
|
||||||
sh->ctx->vt100_ctx.cons.name_len = z_shell_strlen(sh->ctx->prompt);
|
sh->ctx->vt100_ctx.cons.name_len = z_shell_strlen(sh->ctx->prompt);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Configure backend according to enabled shell features and backend
|
/* Configure backend according to enabled shell features and backend
|
||||||
* specific settings.
|
* specific settings.
|
||||||
|
@ -1614,15 +1619,35 @@ void shell_hexdump(const struct shell *sh, const uint8_t *data, size_t len)
|
||||||
|
|
||||||
int shell_prompt_change(const struct shell *sh, const char *prompt)
|
int shell_prompt_change(const struct shell *sh, const char *prompt)
|
||||||
{
|
{
|
||||||
|
#if defined(CONFIG_SHELL_PROMPT_CHANGE) && CONFIG_SHELL_PROMPT_CHANGE
|
||||||
__ASSERT_NO_MSG(sh);
|
__ASSERT_NO_MSG(sh);
|
||||||
|
|
||||||
if (prompt == NULL) {
|
if (prompt == NULL) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
sh->ctx->prompt = prompt;
|
|
||||||
sh->ctx->vt100_ctx.cons.name_len = z_shell_strlen(prompt);
|
static const size_t mtx_timeout_ms = 20;
|
||||||
|
size_t prompt_length = z_shell_strlen(prompt);
|
||||||
|
|
||||||
|
if (k_mutex_lock(&sh->ctx->wr_mtx, K_MSEC(mtx_timeout_ms))) {
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((prompt_length + 1 > CONFIG_SHELL_PROMPT_BUFF_SIZE) || (prompt_length == 0)) {
|
||||||
|
k_mutex_unlock(&sh->ctx->wr_mtx);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(sh->ctx->prompt, prompt);
|
||||||
|
|
||||||
|
sh->ctx->vt100_ctx.cons.name_len = prompt_length;
|
||||||
|
|
||||||
|
k_mutex_unlock(&sh->ctx->wr_mtx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
return -EPERM;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void shell_help(const struct shell *sh)
|
void shell_help(const struct shell *sh)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue