Skip to content

Commit 681c7da

Browse files
pillo79kartben
authored andcommitted
llext: fix fixed-length name buffer usage
This was inspired by the detection of 2 instances of the warning: warning: 'strncpy' specified bound 16 equals destination size [-Wstringop-truncation] The current code is already safe with regards to overflows, because fixed-length string functions are used in the call tree. However, when given a name 16 chars or larger, the current compare in llext_by_name() will not work as expected because the stored extension name is truncated to a max of 15. Define a global LLEXT_MAX_NAME_LEN constant to simplify all this logic and also implement name checks in the shell before calling llext_load(). Finally, using strlen() instead of strnlen() gets the real length of the hex string passed as a parameter, which is important for the next safety check. Signed-off-by: Luca Burelli <[email protected]>
1 parent d2c4954 commit 681c7da

File tree

3 files changed

+17
-11
lines changed

3 files changed

+17
-11
lines changed

include/zephyr/llext/llext.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ enum llext_mem {
6565
struct llext_loader;
6666
/** @endcond */
6767

68-
/* Maximim number of dependency LLEXTs */
68+
/** Maximum length of an extension name */
69+
#define LLEXT_MAX_NAME_LEN 15
70+
71+
/** Maximum number of dependency LLEXTs */
6972
#define LLEXT_MAX_DEPENDENCIES 8
7073

7174
/**
@@ -86,7 +89,7 @@ struct llext {
8689
/** @endcond */
8790

8891
/** Name of the llext */
89-
char name[16];
92+
char name[LLEXT_MAX_NAME_LEN + 1];
9093

9194
/** Lookup table of memory regions */
9295
void *mem[LLEXT_MEM_COUNT];

subsys/llext/llext.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ struct llext *llext_by_name(const char *name)
9595
node = sys_slist_peek_next(node)) {
9696
struct llext *ext = CONTAINER_OF(node, struct llext, _llext_list);
9797

98-
if (strncmp(ext->name, name, sizeof(ext->name)) == 0) {
98+
if (strncmp(ext->name, name, LLEXT_MAX_NAME_LEN) == 0) {
9999
k_mutex_unlock(&llext_lock);
100100
return ext;
101101
}
@@ -193,8 +193,9 @@ int llext_load(struct llext_loader *ldr, const char *name, struct llext **ext,
193193
goto out;
194194
}
195195

196-
strncpy((*ext)->name, name, sizeof((*ext)->name));
197-
(*ext)->name[sizeof((*ext)->name) - 1] = '\0';
196+
/* The (*ext)->name array is LLEXT_MAX_NAME_LEN + 1 bytes long */
197+
strncpy((*ext)->name, name, LLEXT_MAX_NAME_LEN);
198+
(*ext)->name[LLEXT_MAX_NAME_LEN] = '\0';
198199
(*ext)->use_count++;
199200

200201
sys_slist_append(&_llext_list, &(*ext)->_llext_list);

subsys/llext/shell.c

+8-6
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,20 @@ static uint8_t llext_buf[CONFIG_LLEXT_SHELL_MAX_SIZE] __aligned(Z_KERNEL_STACK_O
128128

129129
static int cmd_llext_load_hex(const struct shell *sh, size_t argc, char *argv[])
130130
{
131-
char name[16];
132-
size_t hex_len = strnlen(argv[2], CONFIG_LLEXT_SHELL_MAX_SIZE*2+1);
133-
size_t bin_len = hex_len/2;
131+
char *name = argv[1];
132+
size_t hex_len = strlen(argv[2]);
134133

135-
if (bin_len > CONFIG_LLEXT_SHELL_MAX_SIZE) {
134+
if (strlen(name) > LLEXT_MAX_NAME_LEN) {
135+
shell_print(sh, "Extension name too long, max %d chars\n", LLEXT_MAX_NAME_LEN);
136+
return -EINVAL;
137+
}
138+
139+
if (hex_len > CONFIG_LLEXT_SHELL_MAX_SIZE*2) {
136140
shell_print(sh, "Extension %d bytes too large to load, max %d bytes\n", hex_len/2,
137141
CONFIG_LLEXT_SHELL_MAX_SIZE);
138142
return -ENOMEM;
139143
}
140144

141-
strncpy(name, argv[1], sizeof(name));
142-
143145
size_t llext_buf_len = hex2bin(argv[2], hex_len, llext_buf, CONFIG_LLEXT_SHELL_MAX_SIZE);
144146
struct llext_buf_loader buf_loader = LLEXT_BUF_LOADER(llext_buf, llext_buf_len);
145147
struct llext_loader *ldr = &buf_loader.loader;

0 commit comments

Comments
 (0)