In the Linux kernel, the following vulnerability has been resolved:
bpf: Free dynamically allocated bits in bpfiterbits_destroy()
bpfiterbitsdestroy() uses "kit->nrbits <= 64" to check whether the bits are dynamically allocated. However, the check is incorrect and may cause a kmemleak as shown below:
unreferenced object 0xffff88812628c8c0 (size 32): comm "swapper/0", pid 1, jiffies 4294727320 hex dump (first 32 bytes): b0 c1 55 f5 81 88 ff ff f0 f0 f0 f0 f0 f0 f0 f0 ..U........... f0 f0 f0 f0 f0 f0 f0 f0 00 00 00 00 00 00 00 00 .............. backtrace (crc 781e32cc): [<00000000c452b4ab>] kmemleakalloc+0x4b/0x80 [<0000000004e09f80>] _kmallocnodenoprof+0x480/0x5c0 [<00000000597124d6>] _alloc.isra.0+0x89/0xb0 [<000000004ebfffcd>] allocbulk+0x2af/0x720 [<00000000d9c10145>] prefillmemcache+0x7f/0xb0 [<00000000ff9738ff>] bpfmemallocinit+0x3e2/0x610 [<000000008b616eac>] bpfglobalmainit+0x19/0x30 [<00000000fc473efc>] dooneinitcall+0xd3/0x3c0 [<00000000ec81498c>] kernelinitfreeable+0x66a/0x940 [<00000000b119f72f>] kernelinit+0x20/0x160 [<00000000f11ac9a7>] retfromfork+0x3c/0x70 [<0000000004671da4>] retfromforkasm+0x1a/0x30
That is because nrbits will be set as zero in bpfiterbitsnext() after all bits have been iterated.
Fix the issue by setting kit->bit to kit->nrbits instead of setting kit->nrbits to zero when the iteration completes in bpfiterbitsnext(). In addition, use "!nrbits || bits >= nrbits" to check whether the iteration is complete and still use "nrbits > 64" to indicate whether bits are dynamically allocated. The "!nrbits" check is necessary because bpfiterbitsnew() may fail before setting kit->nr_bits, and this condition will stop the iteration early instead of accessing the zeroed or freed kit->bits.
Considering the initial value of kit->bits is -1 and the type of kit->nrbits is unsigned int, change the type of kit->nrbits to int. The potential overflow problem will be handled in the following patch.
[
{
"digest": {
"function_hash": "60933200274522304445943686602773246764",
"length": 362.0
},
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@9cee266fafaf79fd465314546f637f9a3c215830",
"deprecated": false,
"signature_version": "v1",
"signature_type": "Function",
"id": "CVE-2024-50254-25c05375",
"target": {
"file": "kernel/bpf/helpers.c",
"function": "bpf_iter_bits_next"
}
},
{
"digest": {
"threshold": 0.9,
"line_hashes": [
"129269740370332305957372249052872648787",
"99691454899558958530571214824505723246",
"91044329306659103701990412283833682682",
"256238608405734731785627162673237943256",
"244021978025107730422264863561591411581",
"310707339290618109255475048430504631816",
"308160536647772449160466565735727625123",
"219634085375267842589288771758810812438",
"177531644197721480748251951288225730186",
"3860586354034554702731031563433531167",
"155975081552122592627794014747056696425",
"27395429823457194956151095410227097917",
"188466315562705348043159261176902439327",
"316067058690581326999293257015057990054",
"236343075137919802936316987978645724296",
"34221286616454412663590509367835276182"
]
},
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@101ccfbabf4738041273ce64e2b116cf440dea13",
"deprecated": false,
"signature_version": "v1",
"signature_type": "Line",
"id": "CVE-2024-50254-586692f2",
"target": {
"file": "kernel/bpf/helpers.c"
}
},
{
"digest": {
"function_hash": "60933200274522304445943686602773246764",
"length": 362.0
},
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@101ccfbabf4738041273ce64e2b116cf440dea13",
"deprecated": false,
"signature_version": "v1",
"signature_type": "Function",
"id": "CVE-2024-50254-c99c80e7",
"target": {
"file": "kernel/bpf/helpers.c",
"function": "bpf_iter_bits_next"
}
},
{
"digest": {
"threshold": 0.9,
"line_hashes": [
"129269740370332305957372249052872648787",
"99691454899558958530571214824505723246",
"91044329306659103701990412283833682682",
"256238608405734731785627162673237943256",
"244021978025107730422264863561591411581",
"310707339290618109255475048430504631816",
"308160536647772449160466565735727625123",
"219634085375267842589288771758810812438",
"177531644197721480748251951288225730186",
"3860586354034554702731031563433531167",
"155975081552122592627794014747056696425",
"27395429823457194956151095410227097917",
"188466315562705348043159261176902439327",
"316067058690581326999293257015057990054",
"236343075137919802936316987978645724296",
"34221286616454412663590509367835276182"
]
},
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@9cee266fafaf79fd465314546f637f9a3c215830",
"deprecated": false,
"signature_version": "v1",
"signature_type": "Line",
"id": "CVE-2024-50254-f355aa9b",
"target": {
"file": "kernel/bpf/helpers.c"
}
}
]