Skip to content

Commit c30f99e

Browse files
committed
app: Add runtime safety checks for AT host
Various functions like: * check_idle_timer() * in_at_mode_*() * is_idle_*() * is_open_*() are designed to tolerate NULL for either context or pipe pointer. This is because sm_at_host_get_current(), sm_at_host_get_pipe() and sm_at_host_get_current_pipe() are designed to return NULL when there is no context or pipe to point to. However, few of those mentioned were not properly handling the NULL, especially the internal check_idle_timer() caused NULL pointer dereference if context was destroyed just before URC message was send to that pipe. Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
1 parent cc886f7 commit c30f99e

1 file changed

Lines changed: 20 additions & 9 deletions

File tree

app/src/sm_at_host.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,9 @@ struct sm_at_host_ctx *sm_at_host_get_urc_ctx(void)
335335

336336
struct modem_pipe *sm_at_host_get_pipe(struct sm_at_host_ctx *ctx)
337337
{
338+
if (!sm_at_ctx_check(ctx)) {
339+
return NULL;
340+
}
338341
return ctx ? atomic_ptr_get(&ctx->pipe) : NULL;
339342
}
340343

@@ -385,6 +388,9 @@ static bool sm_at_ctx_check(struct sm_at_host_ctx *ctx)
385388

386389
static void check_idle_timer(struct sm_at_host_ctx *ctx, bool reschedule)
387390
{
391+
if (!ctx) {
392+
return;
393+
}
388394
if (reschedule || k_timer_remaining_ticks(&ctx->idle_timer) == 0) {
389395
k_timeout_t delay = ctx->echo_enabled && (reschedule || ctx->at_cmd_len != 0)
390396
? K_MSEC(CONFIG_SM_URC_DELAY_WITH_INCOMPLETE_ECHO_MS)
@@ -573,6 +579,9 @@ void sm_at_host_release(struct sm_at_host_ctx *ctx)
573579

574580
void sm_at_host_attach(struct modem_pipe *pipe)
575581
{
582+
if (!pipe) {
583+
return;
584+
}
576585
modem_pipe_attach(pipe, null_pipe_handler, NULL);
577586
if (sm_pipe_is_open(pipe)) {
578587
sm_at_pipe_opened(NULL, pipe);
@@ -1016,11 +1025,13 @@ static int sm_at_send_internal(struct sm_at_host_ctx *ctx, const uint8_t *data,
10161025
sys_slist_append(&ctx->buffered_urcs, &msg->node);
10171026
}
10181027
}
1019-
if (!is_idle(ctx)) {
1020-
LOG_DBG("AT command in progress, delaying URC processing");
1021-
check_idle_timer(ctx, false);
1022-
} else {
1023-
sm_at_host_event_notify(ctx, SM_EVENT_URC);
1028+
if (ctx) {
1029+
if (!is_idle(ctx)) {
1030+
LOG_DBG("AT command in progress, delaying URC processing");
1031+
check_idle_timer(ctx, false);
1032+
} else {
1033+
sm_at_host_event_notify(ctx, SM_EVENT_URC);
1034+
}
10241035
}
10251036
return 0;
10261037
}
@@ -1506,20 +1517,20 @@ bool in_at_mode_pipe(struct modem_pipe *pipe)
15061517
{
15071518
struct sm_at_host_ctx *ctx = sm_at_host_get_ctx_from(pipe);
15081519

1509-
return in_at_mode_ctx(ctx);
1520+
return ctx ? in_at_mode_ctx(ctx) : false;
15101521
}
15111522

15121523
bool is_idle_ctx(struct sm_at_host_ctx *ctx)
15131524
{
1514-
return (in_at_mode_ctx(ctx) &&
1525+
return (sm_at_ctx_check(ctx) && in_at_mode_ctx(ctx) &&
15151526
k_timer_remaining_ticks(&ctx->idle_timer) == 0);
15161527
}
15171528

15181529
bool is_idle_pipe(struct modem_pipe *pipe)
15191530
{
15201531
struct sm_at_host_ctx *ctx = sm_at_host_get_ctx_from(pipe);
15211532

1522-
return is_idle_ctx(ctx);
1533+
return ctx ? is_idle_ctx(ctx) : false;
15231534
}
15241535

15251536
bool is_open_pipe(struct modem_pipe *pipe)
@@ -1529,7 +1540,7 @@ bool is_open_pipe(struct modem_pipe *pipe)
15291540

15301541
bool is_open_ctx(struct sm_at_host_ctx *ctx)
15311542
{
1532-
return sm_at_host_get_pipe(ctx);
1543+
return ctx ? is_open_pipe(sm_at_host_get_pipe(ctx)) : false;
15331544
}
15341545

15351546
void exit_datamode_handler(int result)

0 commit comments

Comments
 (0)