Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CVE-2021-30883: AppleCLCD, iOS 15.0.1 to 15.0.2

This repeats the patch diff in Saar Amar: Bindiff and POC for the IOMFB vulnerability. IOMFB::TableCompensator::BilerpGainTable::new_from_data computed the size of a table in 32 bits, as 12 * v15 * v14 + 4 * (v14 + a3), and allocated that much. The fix computes it in 64 bits, puts upper limits on the counts, and checks the allocation for NULL.

An iPhone 11 is used: the A14 and later run this code on the DCP instead.

Get the binaries

$ ipsw download ipsw --device iPhone12,1 --build 19A348 --kernel --output 15.0.1
$ ipsw download ipsw --device iPhone12,1 --build 19A404 --kernel --output 15.0.2

The kernelcache of iOS 15 on an A13 is no fileset, but one image with every kext linked in, so it is compared whole.

Compare

$ hereticus --format markdown 15.0.1/*/kernelcache.release.iPhone12,1 15.0.2/*/kernelcache.release.iPhone12,1
FUNCTIONCHANGESCORE+/-/~TOUCHEDMATCHED BY
sub_fffffff009c0b13c -> sub_fffffff009c0b178changed0.7228/16/53 branch, 4 call, 3 jump, 8 memsimilar
sub_fffffff009c0a39cchanged0.4010/14/21 branch, 2 call, 1 jump, 4 memsame callers
sub_fffffff009c0aedc -> sub_fffffff009c0aef8changed0.8914/5/42 branch, 1 call, 1 memsimilar
…

114843 matched (114507 unchanged, 336 changed), 1 gone, 2 new

6 changed only a constant, hidden. Use –show-retouched to list them.

The first row is the function from the report, out of 336 changed in the whole kernel. It adds the most instructions.

Read the fix

$ hereticus --diff sub_fffffff009c0b13c 15.0.1/*/kernelcache.release.iPhone12,1 15.0.2/*/kernelcache.release.iPhone12,1
...
- cmp w25, #0x0
- csinc w9, w25, wzr, ne
- mul w9, w8, w9
- mov w22, #0xc
- mul w9, w9, w22
- add w8, w8, w25
- add w0, w9, w8, lsl #2
  bl $-0xdcc
+ cbz w0, $+0x54
...
  ldr w8, [x19, #0x20]
+ cmp w8, #0x64
+ b.hi $+0x10
  ldr w9, [x19, #0x10]
+ cmp w9, #0x3e9
+ b.lo $+0x70
...

The size 12 * v15 * v14 + 4 * (v14 + a3) in 32-bit registers is gone. A call computes it now, a zero result leaves through the new error path, and the two counts are limited to 100 and 1000: the upper limits the report names.