Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib min_heap: improve type safety in min_heap macros by using container_of

Patch series "lib min_heap: Improve min_heap safety, testing, and
documentation".

Improve the min heap implementation by enhancing type safety with
container_of, reducing the attack vector by replacing test function calls
with inline variants, and adding a brief API introduction in min_heap.h.
It also includes author information in
Documentation/core-api/min_heap.rst.


This patch (of 4):

The current implementation of min_heap macros uses explicit casting to
min_heap_char *, which prevents the compiler from detecting incorrect
pointer types. This can lead to errors if non-min_heap pointers are
passed inadvertently.

To enhance safety, replace all explicit casts to min_heap_char * with the
use of container_of(&(_heap)->nr, min_heap_char, nr). This approach
ensures that the _heap parameter is indeed a min_heap_char-compatible
structure, allowing the compiler to catch improper usages.

Link: https://lkml.kernel.org/r/20241129181222.646855-1-visitorckw@gmail.com
Link: https://lore.kernel.org/lkml/CAMuHMdVO5DPuD9HYWBFqKDHphx7+0BEhreUxtVC40A=8p6VAhQ@mail.gmail.com
Link: https://lkml.kernel.org/r/20241129181222.646855-2-visitorckw@gmail.com
Signed-off-by: Kuan-Wei Chiu <visitorckw@gmail.com>
Suggested-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Ching-Chun (Jim) Huang <jserv@ccns.ncku.edu.tw>
Cc: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Kuan-Wei Chiu and committed by
Andrew Morton
ec01e9d0 cd6313be

+35 -26
+35 -26
include/linux/min_heap.h
··· 218 218 } 219 219 220 220 #define min_heap_init_inline(_heap, _data, _size) \ 221 - __min_heap_init_inline((min_heap_char *)_heap, _data, _size) 221 + __min_heap_init_inline(container_of(&(_heap)->nr, min_heap_char, nr), _data, _size) 222 222 223 223 /* Get the minimum element from the heap. */ 224 224 static __always_inline ··· 228 228 } 229 229 230 230 #define min_heap_peek_inline(_heap) \ 231 - (__minheap_cast(_heap) __min_heap_peek_inline((min_heap_char *)_heap)) 231 + (__minheap_cast(_heap) \ 232 + __min_heap_peek_inline(container_of(&(_heap)->nr, min_heap_char, nr))) 232 233 233 234 /* Check if the heap is full. */ 234 235 static __always_inline ··· 239 238 } 240 239 241 240 #define min_heap_full_inline(_heap) \ 242 - __min_heap_full_inline((min_heap_char *)_heap) 241 + __min_heap_full_inline(container_of(&(_heap)->nr, min_heap_char, nr)) 243 242 244 243 /* Sift the element at pos down the heap. */ 245 244 static __always_inline ··· 278 277 } 279 278 280 279 #define min_heap_sift_down_inline(_heap, _pos, _func, _args) \ 281 - __min_heap_sift_down_inline((min_heap_char *)_heap, _pos, __minheap_obj_size(_heap), \ 282 - _func, _args) 280 + __min_heap_sift_down_inline(container_of(&(_heap)->nr, min_heap_char, nr), _pos, \ 281 + __minheap_obj_size(_heap), _func, _args) 283 282 284 283 /* Sift up ith element from the heap, O(log2(nr)). */ 285 284 static __always_inline ··· 305 304 } 306 305 307 306 #define min_heap_sift_up_inline(_heap, _idx, _func, _args) \ 308 - __min_heap_sift_up_inline((min_heap_char *)_heap, __minheap_obj_size(_heap), _idx, \ 309 - _func, _args) 307 + __min_heap_sift_up_inline(container_of(&(_heap)->nr, min_heap_char, nr), \ 308 + __minheap_obj_size(_heap), _idx, _func, _args) 310 309 311 310 /* Floyd's approach to heapification that is O(nr). */ 312 311 static __always_inline ··· 320 319 } 321 320 322 321 #define min_heapify_all_inline(_heap, _func, _args) \ 323 - __min_heapify_all_inline((min_heap_char *)_heap, __minheap_obj_size(_heap), _func, _args) 322 + __min_heapify_all_inline(container_of(&(_heap)->nr, min_heap_char, nr), \ 323 + __minheap_obj_size(_heap), _func, _args) 324 324 325 325 /* Remove minimum element from the heap, O(log2(nr)). */ 326 326 static __always_inline ··· 342 340 } 343 341 344 342 #define min_heap_pop_inline(_heap, _func, _args) \ 345 - __min_heap_pop_inline((min_heap_char *)_heap, __minheap_obj_size(_heap), _func, _args) 343 + __min_heap_pop_inline(container_of(&(_heap)->nr, min_heap_char, nr), \ 344 + __minheap_obj_size(_heap), _func, _args) 346 345 347 346 /* 348 347 * Remove the minimum element and then push the given element. The ··· 359 356 } 360 357 361 358 #define min_heap_pop_push_inline(_heap, _element, _func, _args) \ 362 - __min_heap_pop_push_inline((min_heap_char *)_heap, _element, __minheap_obj_size(_heap), \ 363 - _func, _args) 359 + __min_heap_pop_push_inline(container_of(&(_heap)->nr, min_heap_char, nr), _element, \ 360 + __minheap_obj_size(_heap), _func, _args) 364 361 365 362 /* Push an element on to the heap, O(log2(nr)). */ 366 363 static __always_inline ··· 385 382 } 386 383 387 384 #define min_heap_push_inline(_heap, _element, _func, _args) \ 388 - __min_heap_push_inline((min_heap_char *)_heap, _element, __minheap_obj_size(_heap), \ 389 - _func, _args) 385 + __min_heap_push_inline(container_of(&(_heap)->nr, min_heap_char, nr), _element, \ 386 + __minheap_obj_size(_heap), _func, _args) 390 387 391 388 /* Remove ith element from the heap, O(log2(nr)). */ 392 389 static __always_inline ··· 414 411 } 415 412 416 413 #define min_heap_del_inline(_heap, _idx, _func, _args) \ 417 - __min_heap_del_inline((min_heap_char *)_heap, __minheap_obj_size(_heap), _idx, \ 418 - _func, _args) 414 + __min_heap_del_inline(container_of(&(_heap)->nr, min_heap_char, nr), \ 415 + __minheap_obj_size(_heap), _idx, _func, _args) 419 416 420 417 void __min_heap_init(min_heap_char *heap, void *data, int size); 421 418 void *__min_heap_peek(struct min_heap_char *heap); ··· 436 433 const struct min_heap_callbacks *func, void *args); 437 434 438 435 #define min_heap_init(_heap, _data, _size) \ 439 - __min_heap_init((min_heap_char *)_heap, _data, _size) 436 + __min_heap_init(container_of(&(_heap)->nr, min_heap_char, nr), _data, _size) 440 437 #define min_heap_peek(_heap) \ 441 - (__minheap_cast(_heap) __min_heap_peek((min_heap_char *)_heap)) 438 + (__minheap_cast(_heap) __min_heap_peek(container_of(&(_heap)->nr, min_heap_char, nr))) 442 439 #define min_heap_full(_heap) \ 443 - __min_heap_full((min_heap_char *)_heap) 440 + __min_heap_full(container_of(&(_heap)->nr, min_heap_char, nr)) 444 441 #define min_heap_sift_down(_heap, _pos, _func, _args) \ 445 - __min_heap_sift_down((min_heap_char *)_heap, _pos, __minheap_obj_size(_heap), _func, _args) 442 + __min_heap_sift_down(container_of(&(_heap)->nr, min_heap_char, nr), _pos, \ 443 + __minheap_obj_size(_heap), _func, _args) 446 444 #define min_heap_sift_up(_heap, _idx, _func, _args) \ 447 - __min_heap_sift_up((min_heap_char *)_heap, __minheap_obj_size(_heap), _idx, _func, _args) 445 + __min_heap_sift_up(container_of(&(_heap)->nr, min_heap_char, nr), \ 446 + __minheap_obj_size(_heap), _idx, _func, _args) 448 447 #define min_heapify_all(_heap, _func, _args) \ 449 - __min_heapify_all((min_heap_char *)_heap, __minheap_obj_size(_heap), _func, _args) 448 + __min_heapify_all(container_of(&(_heap)->nr, min_heap_char, nr), \ 449 + __minheap_obj_size(_heap), _func, _args) 450 450 #define min_heap_pop(_heap, _func, _args) \ 451 - __min_heap_pop((min_heap_char *)_heap, __minheap_obj_size(_heap), _func, _args) 451 + __min_heap_pop(container_of(&(_heap)->nr, min_heap_char, nr), \ 452 + __minheap_obj_size(_heap), _func, _args) 452 453 #define min_heap_pop_push(_heap, _element, _func, _args) \ 453 - __min_heap_pop_push((min_heap_char *)_heap, _element, __minheap_obj_size(_heap), \ 454 - _func, _args) 454 + __min_heap_pop_push(container_of(&(_heap)->nr, min_heap_char, nr), _element, \ 455 + __minheap_obj_size(_heap), _func, _args) 455 456 #define min_heap_push(_heap, _element, _func, _args) \ 456 - __min_heap_push((min_heap_char *)_heap, _element, __minheap_obj_size(_heap), _func, _args) 457 + __min_heap_push(container_of(&(_heap)->nr, min_heap_char, nr), _element, \ 458 + __minheap_obj_size(_heap), _func, _args) 457 459 #define min_heap_del(_heap, _idx, _func, _args) \ 458 - __min_heap_del((min_heap_char *)_heap, __minheap_obj_size(_heap), _idx, _func, _args) 460 + __min_heap_del(container_of(&(_heap)->nr, min_heap_char, nr), \ 461 + __minheap_obj_size(_heap), _idx, _func, _args) 459 462 460 463 #endif /* _LINUX_MIN_HEAP_H */