Skip to content

Commit

Permalink
net: lwm2m: Make LwM2M message allocation thread safe
Browse files Browse the repository at this point in the history
The LwM2M message allocation was not thread safe, i. e. the message was
acquired by setting the ctx pointer, and it was freed by clearing the
entire message structure.

If preemptive threads were enabled, and memset() clearing the message
content was preempted, the message structure being currently zeroed
migh've been allocated and initialized by some other thread. If the
thread releasing the message resumed work, it would continue clearing
the freshly allocated and initialized message structure.

In order to prevent this, introduce a new global mutex for the lwm2m
engine global variables. The mutex is used when LwM2M message is
allocated/deallocated. This will prevent reallocating the message
during the release process.

Signed-off-by: Robert Lubos <[email protected]>
  • Loading branch information
rlubos committed Oct 15, 2024
1 parent 6300e1b commit 3bd83be
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
12 changes: 12 additions & 0 deletions subsys/net/lib/lwm2m/lwm2m_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ static sys_slist_t engine_service_list;
static K_KERNEL_STACK_DEFINE(engine_thread_stack, CONFIG_LWM2M_ENGINE_STACK_SIZE);
static struct k_thread engine_thread_data;

static K_MUTEX_DEFINE(engine_lock);

#define MAX_POLL_FD CONFIG_ZVFS_POLL_MAX

/* Resources */
Expand Down Expand Up @@ -1285,6 +1287,16 @@ int lwm2m_engine_resume(void)
return 0;
}

void lwm2m_engine_lock(void)
{
(void)k_mutex_lock(&engine_lock, K_FOREVER);
}

void lwm2m_engine_unlock(void)
{
k_mutex_unlock(&engine_lock);
}

static int lwm2m_engine_init(void)
{
for (int i = 0; i < LWM2M_ENGINE_MAX_OBSERVER_PATH; i++) {
Expand Down
10 changes: 10 additions & 0 deletions subsys/net/lib/lwm2m/lwm2m_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,14 @@ int lwm2m_sock_nfds(void);
*/
void lwm2m_engine_wake_up(void);

/**
* @brief Locks the access to shared LwM2M engine variables.
*/
void lwm2m_engine_lock(void);

/**
* @brief Unlocks the access to shared LwM2M engine variables.
*/
void lwm2m_engine_unlock(void);

#endif /* LWM2M_ENGINE_H */
13 changes: 11 additions & 2 deletions subsys/net/lib/lwm2m/lwm2m_message_handling.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,18 +517,25 @@ struct lwm2m_message *find_msg(struct coap_pending *pending, struct coap_reply *
return NULL;
}


struct lwm2m_message *lwm2m_get_message(struct lwm2m_ctx *client_ctx)
{
struct lwm2m_message *msg = NULL;
size_t i;

lwm2m_engine_lock();

for (i = 0; i < CONFIG_LWM2M_ENGINE_MAX_MESSAGES; i++) {
if (!messages[i].ctx) {
messages[i].ctx = client_ctx;
return &messages[i];
msg = &messages[i];
break;
}
}

return NULL;
lwm2m_engine_unlock();

return msg;
}

void lm2m_message_clear_allocations(struct lwm2m_message *msg)
Expand Down Expand Up @@ -561,11 +568,13 @@ void lwm2m_reset_message(struct lwm2m_message *msg, bool release)
}

if (release) {
lwm2m_engine_lock();
#if defined(CONFIG_LWM2M_COAP_BLOCK_TRANSFER)
release_output_block_ctx(&msg->out.block_ctx);
release_body_encode_buffer(&msg->body_encode_buffer.data);
#endif
(void)memset(msg, 0, sizeof(*msg));
lwm2m_engine_unlock();
} else {
msg->message_timeout_cb = NULL;
(void)memset(&msg->cpkt, 0, sizeof(msg->cpkt));
Expand Down

0 comments on commit 3bd83be

Please sign in to comment.