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.
{ "vanir_signatures": [ { "target": { "file": "kernel/bpf/helpers.c", "function": "bpf_iter_bits_next" }, "digest": { "length": 362.0, "function_hash": "60933200274522304445943686602773246764" }, "signature_version": "v1", "id": "CVE-2024-50254-25c05375", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@9cee266fafaf79fd465314546f637f9a3c215830", "signature_type": "Function" }, { "target": { "file": "kernel/bpf/helpers.c" }, "digest": { "threshold": 0.9, "line_hashes": [ "129269740370332305957372249052872648787", "99691454899558958530571214824505723246", "91044329306659103701990412283833682682", "256238608405734731785627162673237943256", "244021978025107730422264863561591411581", "310707339290618109255475048430504631816", "308160536647772449160466565735727625123", "219634085375267842589288771758810812438", "177531644197721480748251951288225730186", "3860586354034554702731031563433531167", "155975081552122592627794014747056696425", "27395429823457194956151095410227097917", "188466315562705348043159261176902439327", "316067058690581326999293257015057990054", "236343075137919802936316987978645724296", "34221286616454412663590509367835276182" ] }, "signature_version": "v1", "id": "CVE-2024-50254-586692f2", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@101ccfbabf4738041273ce64e2b116cf440dea13", "signature_type": "Line" }, { "target": { "file": "kernel/bpf/helpers.c", "function": "bpf_iter_bits_next" }, "digest": { "length": 362.0, "function_hash": "60933200274522304445943686602773246764" }, "signature_version": "v1", "id": "CVE-2024-50254-c99c80e7", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@101ccfbabf4738041273ce64e2b116cf440dea13", "signature_type": "Function" }, { "target": { "file": "kernel/bpf/helpers.c" }, "digest": { "threshold": 0.9, "line_hashes": [ "129269740370332305957372249052872648787", "99691454899558958530571214824505723246", "91044329306659103701990412283833682682", "256238608405734731785627162673237943256", "244021978025107730422264863561591411581", "310707339290618109255475048430504631816", "308160536647772449160466565735727625123", "219634085375267842589288771758810812438", "177531644197721480748251951288225730186", "3860586354034554702731031563433531167", "155975081552122592627794014747056696425", "27395429823457194956151095410227097917", "188466315562705348043159261176902439327", "316067058690581326999293257015057990054", "236343075137919802936316987978645724296", "34221286616454412663590509367835276182" ] }, "signature_version": "v1", "id": "CVE-2024-50254-f355aa9b", "deprecated": false, "source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@9cee266fafaf79fd465314546f637f9a3c215830", "signature_type": "Line" } ] }