@@ -81,7 +81,13 @@ void fpages_init(void)
8181 */
8282static void insert_fpage_chain_to_as (as_t * as , fpage_t * first , fpage_t * last )
8383{
84- fpage_t * fp = as -> first ;
84+ fpage_t * fp ;
85+
86+ /* NULL chain is a no-op */
87+ if (!first || !last )
88+ return ;
89+
90+ fp = as -> first ;
8591
8692 if (!fp ) {
8793 /* First chain in AS */
@@ -149,14 +155,13 @@ static fpage_t *create_fpage(memptr_t base, size_t shift, int mpid)
149155 dbg_printf (DL_KDB ,
150156 "FPAGE: alloc failed! count=%d base=%p shift=%d mpid=%d\n" ,
151157 fpage_alloc_count , base , shift , mpid );
152- } else {
153- fpage_alloc_count ++ ;
154- if ((fpage_alloc_count % 50 ) == 0 )
155- dbg_printf (DL_KDB , "FPAGE: allocated %d fpages\n" ,
156- fpage_alloc_count );
158+ return NULL ;
157159 }
158160
159- assert ((intptr_t ) fpage );
161+ fpage_alloc_count ++ ;
162+ if ((fpage_alloc_count % 50 ) == 0 )
163+ dbg_printf (DL_KDB , "FPAGE: allocated %d fpages\n" ,
164+ fpage_alloc_count );
160165
161166 fpage -> as_next = NULL ;
162167 fpage -> map_next = fpage ; /* That is first fpage in mapping */
@@ -179,11 +184,26 @@ void destroy_fpage(fpage_t *fpage)
179184 ktable_free (& fpage_table , fpage );
180185}
181186
187+ /**
188+ * Free a chain of fpages
189+ * @param first - first fpage in chain (may be NULL)
190+ */
191+ static void free_fpage_chain (fpage_t * first )
192+ {
193+ fpage_t * fp , * next ;
194+
195+ for (fp = first ; fp ; fp = next ) {
196+ next = fp -> as_next ;
197+ ktable_free (& fpage_table , fp );
198+ }
199+ }
200+
182201static void create_fpage_chain (memptr_t base , size_t size , int mpid ,
183202 fpage_t * * pfirst , fpage_t * * plast )
184203{
185204 int shift , sshift , bshift ;
186205 fpage_t * fpage = NULL ;
206+ fpage_t * newfp ;
187207
188208 while (size ) {
189209 /* Select minimum of base alignment and largest fitting size.
@@ -195,29 +215,40 @@ static void create_fpage_chain(memptr_t base, size_t size, int mpid,
195215
196216 shift = (bshift < sshift ) ? bshift : sshift ;
197217
218+ newfp = create_fpage (base , shift , mpid );
219+ if (!newfp ) {
220+ /* Allocation failed - leave chain incomplete */
221+ dbg_printf (DL_KDB ,
222+ "FPAGE: chain alloc failed at base=%p\n" , base );
223+ return ;
224+ }
225+
198226 if (!* pfirst ) {
199227 /* Create first page */
200- fpage = create_fpage ( base , shift , mpid ) ;
228+ fpage = newfp ;
201229 * pfirst = fpage ;
202230 * plast = fpage ;
203231 } else {
204232 /* Build chain */
205- fpage -> as_next = create_fpage ( base , shift , mpid ) ;
233+ fpage -> as_next = newfp ;
206234 fpage = fpage -> as_next ;
207235 * plast = fpage ;
208236 }
209237
210- size -= (1 << shift );
211- base += (1 << shift );
238+ size -= (( memptr_t ) 1 << shift );
239+ base += (( memptr_t ) 1 << shift );
212240 }
213241}
214242
215243fpage_t * split_fpage (as_t * as , fpage_t * fpage , memptr_t split , int rl )
216244{
217245 memptr_t base = fpage -> fpage .base ,
218- end = fpage -> fpage .base + (1 << fpage -> fpage .shift );
246+ end = fpage -> fpage .base + (( memptr_t ) 1 << fpage -> fpage .shift );
219247 fpage_t * lfirst = NULL , * llast = NULL , * rfirst = NULL , * rlast = NULL ;
220248
249+ if (!as || !fpage )
250+ return NULL ;
251+
221252 /* For rl=1 (right side), round DOWN to include the split point.
222253 * For rl=0 (left side), round UP to exclude past the split point.
223254 */
@@ -226,11 +257,10 @@ fpage_t *split_fpage(as_t *as, fpage_t *fpage, memptr_t split, int rl)
226257 else
227258 split = mempool_align (fpage -> fpage .mpid , split );
228259
229- if (!as )
230- return NULL ;
231-
232- /* Check if we can split something */
233- if (split == base || split == end ) {
260+ /* Check if split point is valid after alignment.
261+ * Must be strictly between base and end.
262+ */
263+ if (split <= base || split >= end ) {
234264 return fpage ;
235265 }
236266
@@ -246,6 +276,26 @@ fpage_t *split_fpage(as_t *as, fpage_t *fpage, memptr_t split, int rl)
246276 create_fpage_chain (split , (end - split ),
247277 fpage -> fpage .mpid , & rfirst , & rlast );
248278
279+ /* Check if both chains were created successfully.
280+ * If either failed, keep the original fpage intact.
281+ */
282+ if (!lfirst || !llast || !rfirst || !rlast ) {
283+ /* Free any partially created chains */
284+ fpage_t * fp , * next ;
285+ for (fp = lfirst ; fp ; fp = next ) {
286+ next = fp -> as_next ;
287+ ktable_free (& fpage_table , fp );
288+ }
289+ for (fp = rfirst ; fp ; fp = next ) {
290+ next = fp -> as_next ;
291+ ktable_free (& fpage_table , fp );
292+ }
293+ dbg_printf (DL_KDB ,
294+ "FPAGE: split failed, keeping original (base=%p split=%p)\n" ,
295+ base , split );
296+ return NULL ;
297+ }
298+
249299 remove_fpage_from_as (as , fpage );
250300 ktable_free (& fpage_table , fpage );
251301
@@ -283,6 +333,14 @@ int assign_fpages_ext(int mpid, as_t *as, memptr_t base, size_t size,
283333
284334 end = base + size ;
285335
336+ /* Overflow check: end must be greater than base */
337+ if (end < base ) {
338+ dbg_printf (DL_KDB ,
339+ "FPAGE: overflow in assign_fpages_ext base=%p size=%p\n" ,
340+ base , size );
341+ return -1 ;
342+ }
343+
286344 if (as ) {
287345 /* find unmapped space */
288346 fp = & as -> first ;
@@ -315,8 +373,10 @@ int assign_fpages_ext(int mpid, as_t *as, memptr_t base, size_t size,
315373 }
316374
317375 /* NULL guard: create_fpage_chain may fail */
318- if (!first || !last )
376+ if (!first || !last ) {
377+ free_fpage_chain (first );
319378 return -1 ;
379+ }
320380
321381 last -> as_next = * fp ;
322382 * fp = first ;
@@ -382,6 +442,14 @@ int assign_fpages_ext(int mpid, as_t *as, memptr_t base, size_t size,
382442 return -1 ;
383443
384444 create_fpage_chain (abase , aend - abase , mpid , pfirst , plast );
445+
446+ /* Check if chain creation failed */
447+ if (!* pfirst || !* plast ) {
448+ free_fpage_chain (* pfirst );
449+ * pfirst = NULL ;
450+ * plast = NULL ;
451+ return -1 ;
452+ }
385453 }
386454 }
387455
@@ -397,9 +465,24 @@ int assign_fpages(as_t *as, memptr_t base, size_t size)
397465
398466int map_fpage (as_t * src , as_t * dst , fpage_t * fpage , map_action_t action )
399467{
400- fpage_t * fpmap = (fpage_t * ) ktable_alloc (& fpage_table );
468+ fpage_t * fpmap ;
469+
470+ /* NULL fpage or dst is a programming error - fail gracefully */
471+ if (!fpage || !dst ) {
472+ dbg_printf (DL_KDB ,
473+ "FPAGE: map_fpage NULL arg! fpage=%p dst=%p\n" ,
474+ fpage , dst );
475+ return -1 ;
476+ }
477+
478+ fpmap = (fpage_t * ) ktable_alloc (& fpage_table );
479+
480+ if (!fpmap ) {
481+ dbg_printf (DL_KDB ,
482+ "FPAGE: map alloc failed! src=%p dst=%p\n" , src , dst );
483+ return -1 ;
484+ }
401485
402- /* FIXME: check for fpmap == NULL */
403486 fpmap -> as_next = NULL ;
404487 fpmap -> mpu_next = NULL ;
405488
@@ -438,8 +521,18 @@ int unmap_fpage(as_t *as, fpage_t *fpage)
438521 if (!(fpage -> fpage .flags & FPAGE_CLONE ))
439522 return -1 ;
440523
441- while (fpprev -> map_next != fpage )
442- fpprev = fpprev -> map_next ;
524+ /* Find previous fpage in circular map list with cycle guard */
525+ {
526+ int guard = CONFIG_MAX_FPAGES ;
527+ while (fpprev -> map_next != fpage && -- guard > 0 )
528+ fpprev = fpprev -> map_next ;
529+
530+ if (guard <= 0 ) {
531+ dbg_printf (DL_KDB ,
532+ "FPAGE: cycle detected in unmap_fpage %p\n" , fpage );
533+ return -1 ;
534+ }
535+ }
443536
444537 /* Clear flags */
445538 fpprev -> fpage .flags &= ~FPAGE_MAPPED ;
0 commit comments