3737#if CONFIG_LLEXT
3838#include <zephyr/llext/llext.h>
3939#endif
40+ #include <zephyr/sys/math_extras.h>
4041
4142#if CONFIG_LIBRARY_AUTH_SUPPORT
4243#include <auth/intel_auth_api.h>
@@ -129,7 +130,7 @@ static int lib_manager_auth_proc(const void *buffer_data, size_t buffer_size,
129130
130131#define PAGE_SZ CONFIG_MM_DRV_PAGE_SIZE
131132
132- static int lib_manager_load_data_from_storage (void __sparse_cache * vma , void * s_addr , uint32_t size ,
133+ static int lib_manager_load_data_from_storage (void __sparse_cache * vma , void * s_addr , size_t size ,
133134 uint32_t flags )
134135{
135136 /* Region must be first mapped as writable in order to initialize its contents. */
@@ -147,16 +148,26 @@ static int lib_manager_load_data_from_storage(void __sparse_cache *vma, void *s_
147148 return sys_mm_drv_update_region_flags ((__sparse_force void * )vma , size , flags );
148149}
149150
150- static int lib_manager_load_module (const uint32_t module_id , const struct sof_man_module * const mod )
151+ static int lib_manager_load_module (const struct sof_man_fw_desc * const desc ,
152+ const uint32_t module_id , const struct sof_man_module * const mod )
151153{
152154 struct lib_manager_mod_ctx * ctx = lib_manager_get_mod_ctx (module_id );
153155 const uintptr_t load_offset = POINTER_TO_UINT (ctx -> base_addr );
156+ size_t lib_size ;
157+ size_t file_offset ;
154158 void * src ;
155159 void __sparse_cache * va_base ;
156160 size_t size ;
157161 uint32_t flags ;
158162 int ret , idx ;
159163
164+ /*
165+ * ELF file segment offsets and sizes come from library files, so they
166+ * have to be validated.
167+ */
168+ if (size_mul_overflow (desc -> header .preload_page_count , PAGE_SZ , & lib_size ))
169+ return - EOVERFLOW ;
170+
160171 for (idx = 0 ; idx < ARRAY_SIZE (mod -> segment ); ++ idx ) {
161172 if (!mod -> segment [idx ].flags .r .load )
162173 continue ;
@@ -168,9 +179,23 @@ static int lib_manager_load_module(const uint32_t module_id, const struct sof_ma
168179 else if (!mod -> segment [idx ].flags .r .readonly )
169180 flags = SYS_MM_MEM_PERM_RW ;
170181
171- src = UINT_TO_POINTER (mod -> segment [idx ].file_offset + load_offset );
182+ file_offset = mod -> segment [idx ].file_offset ;
183+ if (size_mul_overflow (mod -> segment [idx ].flags .r .length , PAGE_SZ , & size )) {
184+ ret = - EOVERFLOW ;
185+ goto err ;
186+ }
187+
188+ /* Reject segments that would read outside the loaded library image. */
189+ if (file_offset > lib_size || size > lib_size - file_offset ) {
190+ tr_err (& lib_manager_tr ,
191+ "segment %d out of bounds: file_offset %#zx, size %#zx, total %#zx" ,
192+ idx , file_offset , size , lib_size );
193+ ret = - ENOSPC ;
194+ goto err ;
195+ }
196+
197+ src = UINT_TO_POINTER (file_offset + load_offset );
172198 va_base = (void __sparse_cache * )UINT_TO_POINTER (mod -> segment [idx ].v_base_addr );
173- size = mod -> segment [idx ].flags .r .length * PAGE_SZ ;
174199 ret = lib_manager_load_data_from_storage (va_base , src , size , flags );
175200 if (ret < 0 )
176201 goto err ;
@@ -230,7 +255,8 @@ static int lib_manager_load_libcode_modules(const uint32_t module_id)
230255
231256 for (idx = 0 ; idx < desc -> header .num_module_entries ; ++ idx , ++ module_entry ) {
232257 if (module_entry -> type .lib_code ) {
233- ret = lib_manager_load_module (lib_id << LIB_MANAGER_LIB_ID_SHIFT | idx ,
258+ ret = lib_manager_load_module (desc ,
259+ lib_id << LIB_MANAGER_LIB_ID_SHIFT | idx ,
234260 module_entry );
235261 if (ret < 0 )
236262 goto err ;
@@ -338,7 +364,8 @@ static int lib_manager_free_module_instance(uint32_t instance_id, const struct s
338364 *
339365 * Function is responsible to allocate module in available free memory and assigning proper address.
340366 */
341- static uintptr_t lib_manager_allocate_module (const struct sof_man_module * mod ,
367+ static uintptr_t lib_manager_allocate_module (const struct sof_man_fw_desc * const desc ,
368+ const struct sof_man_module * mod ,
342369 const struct comp_ipc_config * ipc_config ,
343370 const void * ipc_specific_config )
344371{
@@ -351,7 +378,7 @@ static uintptr_t lib_manager_allocate_module(const struct sof_man_module *mod,
351378 if (module_is_llext (mod ))
352379 return llext_manager_allocate_module (ipc_config , ipc_specific_config );
353380
354- ret = lib_manager_load_module (module_id , mod );
381+ ret = lib_manager_load_module (desc , module_id , mod );
355382 if (ret < 0 )
356383 return 0 ;
357384
@@ -424,7 +451,8 @@ static int lib_manager_free_module(const uint32_t component_id)
424451
425452#define PAGE_SZ 4096 /* equals to MAN_PAGE_SIZE used by rimage */
426453
427- static uintptr_t lib_manager_allocate_module (const struct comp_ipc_config * ipc_config ,
454+ static uintptr_t lib_manager_allocate_module (const struct sof_man_fw_desc * const desc ,
455+ const struct comp_ipc_config * ipc_config ,
428456 const void * ipc_specific_config , const void * * buildinfo )
429457{
430458 tr_err (& lib_manager_tr , "Dynamic module allocation is not supported" );
@@ -644,7 +672,8 @@ static struct comp_dev *lib_manager_module_create(const struct comp_driver *drv,
644672 mod = (const struct sof_man_module * )
645673 ((const uint8_t * )desc + SOF_MAN_MODULE_OFFSET (entry_index ));
646674
647- const uintptr_t module_entry_point = lib_manager_allocate_module (mod , config , args -> data );
675+ const uintptr_t module_entry_point = lib_manager_allocate_module (desc , mod , config ,
676+ args -> data );
648677
649678 if (!module_entry_point ) {
650679 tr_err (& lib_manager_tr , "lib_manager_allocate_module() failed!" );
0 commit comments