// R0 is command (label or query) // R1 is buf_start // R2 is length // R3 is offset (not currently implemented, managed in pirate_utils) // R4 is the label integer void arm_hypercall_callback(CPUState *env){ target_ulong buf_start = env->regs[1]; target_ulong buf_len = env->regs[2]; long label = env->regs[4]; if (env->regs[0] == 7 || env->regs[0] == 8){ if (!taintEnabled){ printf("Taint plugin: Label operation detected\n"); printf("Enabling taint processing\n"); __taint_enable_taint(); } TaintOpBuffer *tempBuf = tob_new( buf_len * sizeof(TaintOp)); if (env->regs[0] == 7){ // Standard buffer label add_taint_ram_single_label(env, shadow, tempBuf, (uint64_t)buf_start, (int)buf_len, label); } else if (env->regs[0] == 8){ // Positional buffer label add_taint_ram_pos(env, shadow, tempBuf, (uint64_t)buf_start, (int)buf_len); } tob_delete(tempBuf); } else if (env->regs[0] == 9){ //Query taint on label if (taintEnabled){ printf("Taint plugin: Query operation detected\n"); Addr a = make_maddr(buf_start); bufplot(env, shadow, &a, (int)buf_len); } //printf("Disabling taint processing\n"); //taintEnabled = false; //taintJustDisabled = true; //printf("Label occurrences on HD: %d\n", shad_dir_occ_64(shadow->hd)); } else if (env->regs[0] == 10){ // Guest util done - reset positional label counter taint_pos_count = 0; } }
// Called whenever the taint state changes. void taint_state_changed(FastShad *fast_shad, uint64_t shad_addr) { Addr addr; if (fast_shad == shadow->llv) { addr = make_laddr(shad_addr / MAXREGSIZE, shad_addr % MAXREGSIZE); } else if (fast_shad == shadow->ram) { addr = make_maddr(shad_addr); } else if (fast_shad == shadow->grv) { addr = make_greg(shad_addr / sizeof(target_ulong), shad_addr % sizeof(target_ulong)); } else if (fast_shad == shadow->gsv) { addr.typ = GSPEC; addr.val.gs = shad_addr; addr.off = 0; addr.flag = (AddrFlag)0; } else if (fast_shad == shadow->ret) { addr.typ = RET; addr.val.ret = 0; addr.off = shad_addr; addr.flag = (AddrFlag)0; } else return; PPP_RUN_CB(on_taint_change, addr); }
// hypercall-initiated taint query of some src-level extent void lava_taint_query (Panda__SrcInfoPri *si, target_ulong buf, target_ulong buf_len) { extern CPUState *cpu_single_env; CPUState *env = cpu_single_env; //if (pandalog && taintEnabled && (taint2_num_labels_applied() > 0)){ if (pandalog && taint2_enabled() && (taint2_num_labels_applied() > 0)){ // okay, taint is on and some labels have actually been applied // is there *any* taint on this extent uint32_t num_tainted = 0; bool is_strnlen = false; //bool is_strnlen = ((int) phs.len == -1); uint32_t offset=0; while (true) { // for (uint32_t offset=0; offset<phs.len; offset++) { uint32_t va = buf + offset; //uint32_t va = phs.buf + offset; uint32_t pa = panda_virt_to_phys(env, va); if (is_strnlen) { uint8_t c; panda_virtual_memory_rw(env, pa, &c, 1, false); // null terminator if (c==0) break; } if ((int) pa != -1) { Addr a = make_maddr(pa); if (taint2_query(a)) { num_tainted ++; } } offset ++; // end of query by length or max string length if (!is_strnlen && offset == buf_len) break; //if (!is_strnlen && offset == phs.len) break; if (is_strnlen && (offset == LAVA_TAINT_QUERY_MAX_LEN)) break; } uint32_t len = offset; if (num_tainted) { printf("logging lava query\n"); // ok at least one byte in the extent is tainted // 1. write the pandalog entry that tells us something was tainted on this extent Panda__TaintQueryPri *tqh = (Panda__TaintQueryPri *) malloc (sizeof (Panda__TaintQueryPri)); *tqh = PANDA__TAINT_QUERY_PRI__INIT; tqh->buf = buf; //tqh->buf = phs.buf; tqh->len = len; tqh->num_tainted = num_tainted; // obtain the actual data out of memory // NOTE: first X bytes only! uint32_t data[LAVA_TAINT_QUERY_MAX_LEN]; uint32_t n = len; // grab at most X bytes from memory to pandalog // this is just a snippet. we dont want to write 1M buffer if (LAVA_TAINT_QUERY_MAX_LEN < len) n = LAVA_TAINT_QUERY_MAX_LEN; for (uint32_t i=0; i<n; i++) { data[i] = 0; uint8_t c; panda_virtual_memory_rw(env, buf+i, &c, 1, false); //panda_virtual_memory_rw(env, phs.buf+i, &c, 1, false); data[i] = c; } tqh->n_data = n; tqh->data = data; // 2. write out src-level info //Panda__SrcInfoPri *si = pandalog_src_info_create(phs); tqh->src_info = si; // 3. write out callstack info Panda__CallStack *cs = pandalog_callstack_create(); tqh->call_stack = cs; // 4. iterate over the bytes in the extent and pandalog detailed info about taint std::vector<Panda__TaintQuery *> tq; for (uint32_t offset=0; offset<len; offset++) { uint32_t va = buf + offset; //uint32_t va = phs.buf + offset; uint32_t pa = panda_virt_to_phys(env, va); if ((int) pa != -1) { Addr a = make_maddr(pa); if (taint2_query(a)) { tq.push_back(taint2_query_pandalog(a, offset)); } } } tqh->n_taint_query = tq.size(); tqh->taint_query = (Panda__TaintQuery **) malloc(sizeof(Panda__TaintQuery *) * tqh->n_taint_query); for (uint32_t i=0; i<tqh->n_taint_query; i++) { tqh->taint_query[i] = tq[i]; } Panda__LogEntry ple = PANDA__LOG_ENTRY__INIT; ple.taint_query_pri = tqh; printf("about to write out taint query entry\n"); pandalog_write_entry(&ple); free(tqh->src_info); pandalog_callstack_free(tqh->call_stack); for (uint32_t i=0; i<tqh->n_taint_query; i++) { pandalog_taint_query_free(tqh->taint_query[i]); } free(tqh); } } }
// hypercall-initiated taint query of some src-level extent void lava_taint_query (PandaHypercallStruct phs) { extern CPUState *cpu_single_env; CPUState *env = cpu_single_env; if (pandalog && taintEnabled && (taint2_num_labels_applied() > 0)){ // okay, taint is on and some labels have actually been applied // is there *any* taint on this extent uint32_t num_tainted = 0; for (uint32_t offset=0; offset<phs.len; offset++) { uint32_t va = phs.buf + offset; uint32_t pa = panda_virt_to_phys(env, va); if ((int) pa != -1) { Addr a = make_maddr(pa); if (taint2_query(a)) { num_tainted ++; } } } if (num_tainted) { // ok at least one byte in the extent is tainted // 1. write the pandalog entry that tells us something was tainted on this extent Panda__TaintQueryHypercall *tqh = (Panda__TaintQueryHypercall *) malloc (sizeof (Panda__TaintQueryHypercall)); *tqh = PANDA__TAINT_QUERY_HYPERCALL__INIT; tqh->buf = phs.buf; tqh->len = phs.len; tqh->num_tainted = num_tainted; // obtain the actual data out of memory // NOTE: first 32 bytes only! uint32_t data[32]; uint32_t n = phs.len; // grab at most 32 bytes from memory to pandalog // this is just a snippet. we dont want to write 1M buffer if (32 < phs.len) n = 32; for (uint32_t i=0; i<n; i++) { data[i] = 0; uint8_t c; panda_virtual_memory_rw(env, phs.buf+i, &c, 1, false); data[i] = c; } tqh->n_data = n; tqh->data = data; // 2. write out src-level info Panda__SrcInfo *si = pandalog_src_info_create(phs); tqh->src_info = si; // 3. write out callstack info Panda__CallStack *cs = pandalog_callstack_create(); tqh->call_stack = cs; // 4. iterate over the bytes in the extent and pandalog detailed info about taint std::vector<Panda__TaintQuery *> tq; for (uint32_t offset=0; offset<phs.len; offset++) { uint32_t va = phs.buf + offset; uint32_t pa = panda_virt_to_phys(env, va); if ((int) pa != -1) { Addr a = make_maddr(pa); if (taint2_query(a)) { tq.push_back(__taint2_query_pandalog(a, offset)); } } } tqh->n_taint_query = tq.size(); tqh->taint_query = (Panda__TaintQuery **) malloc(sizeof(Panda__TaintQuery *) * tqh->n_taint_query); for (uint32_t i=0; i<tqh->n_taint_query; i++) { tqh->taint_query[i] = tq[i]; } Panda__LogEntry ple = PANDA__LOG_ENTRY__INIT; ple.taint_query_hypercall = tqh; pandalog_write_entry(&ple); free(tqh->src_info); pandalog_callstack_free(tqh->call_stack); for (uint32_t i=0; i<tqh->n_taint_query; i++) { __pandalog_taint_query_free(tqh->taint_query[i]); } free(tqh); } } }
// this is for much of the hd taint transfers. // this gets called from rr_log.c, rr_replay_skipped_calls, RR_CALL_HD_TRANSFER // case. int cb_replay_hd_transfer_taint(CPUState *env, uint32_t type, uint64_t src_addr, uint64_t dest_addr, uint32_t num_bytes) { // Replay hd transfer as taint transfer if (taintEnabled) { TaintOp top; top.typ = BULKCOPYOP; top.val.bulkcopy.l = num_bytes; switch (type) { case HD_TRANSFER_HD_TO_IOB: #ifdef TAINTDEBUG printf("replay_hd_transfer HD_TRANSFER_HD_TO_IOB\n"); #endif top.val.bulkcopy.a = make_haddr(src_addr); top.val.bulkcopy.b = make_iaddr(dest_addr); break; case HD_TRANSFER_IOB_TO_HD: #ifdef TAINTDEBUG printf("replay_hd_transfer HD_TRANSFER_IOB_TO_HD\n"); #endif top.val.bulkcopy.a = make_iaddr(src_addr); top.val.bulkcopy.b = make_haddr(dest_addr); break; case HD_TRANSFER_PORT_TO_IOB: #ifdef TAINTDEBUG printf("replay_hd_transfer HD_TRANSFER_PORT_TO_IOB\n"); #endif top.val.bulkcopy.a = make_paddr(src_addr); top.val.bulkcopy.b = make_iaddr(dest_addr); break; case HD_TRANSFER_IOB_TO_PORT: #ifdef TAINTDEBUG printf("replay_hd_transfer HD_TRANSFER_IOB_TO_PORT\n"); #endif top.val.bulkcopy.a = make_iaddr(src_addr); top.val.bulkcopy.b = make_paddr(dest_addr); break; case HD_TRANSFER_HD_TO_RAM: #ifdef TAINTDEBUG printf("replay_hd_transfer HD_TRANSFER_HD_TO_RAM\n"); printf("\tSource: 0x%lx, Dest: 0x%lx, Len: %d\n", src_addr, dest_addr, num_bytes); #endif top.val.bulkcopy.a = make_haddr(src_addr); top.val.bulkcopy.b = make_maddr(dest_addr); break; case HD_TRANSFER_RAM_TO_HD: #ifdef TAINTDEBUG printf("replay_hd_transfer HD_TRANSFER_RAM_TO_HD\n"); printf("\tSource: 0x%lx, Dest: 0x%lx, Len: %d\n", src_addr, dest_addr, num_bytes); #endif top.val.bulkcopy.a = make_maddr(src_addr); top.val.bulkcopy.b = make_haddr(dest_addr); break; default: printf ("Impossible hd transfer type: %d\n", type); assert (1==0); } // make the taint op buffer bigger if necessary tob_resize(&tob_io_thread); // add bulk copy corresponding to this hd transfer to buffer // of taint ops for io thread. tob_op_write(tob_io_thread, &top); } return 0; }
/** * @brief Hypercall-initiated taint query of some src-level extent. */ void taint_query_hypercall(PandaHypercallStruct phs) { CPUState *cpu = first_cpu; if (pandalog && taintEnabled && (taint2_num_labels_applied() > 0)) { // okay, taint is on and some labels have actually been applied // is there *any* taint on this extent uint32_t num_tainted = 0; bool is_strnlen = ((int) phs.len == -1); uint32_t offset=0; while (true) { uint32_t va = phs.buf + offset; uint32_t pa = panda_virt_to_phys(cpu, va); if (is_strnlen) { uint8_t c; panda_virtual_memory_rw(cpu, pa, &c, 1, false); // null terminator if (c==0) break; } if ((int) pa != -1) { Addr a = make_maddr(pa); if (taint2_query(a)) { num_tainted ++; } } offset ++; // end of query by length or max string length if (!is_strnlen && offset == phs.len) break; if (is_strnlen && (offset == QUERY_HYPERCALL_MAX_LEN)) break; } uint32_t len = offset; if (num_tainted) { // ok at least one byte in the extent is tainted // 1. write the pandalog entry that tells us something was tainted on this extent Panda__TaintQueryHypercall *tqh = (Panda__TaintQueryHypercall *) malloc (sizeof (Panda__TaintQueryHypercall)); *tqh = PANDA__TAINT_QUERY_HYPERCALL__INIT; tqh->buf = phs.buf; tqh->len = len; tqh->num_tainted = num_tainted; // obtain the actual data out of memory // NOTE: first X bytes only! uint32_t data[QUERY_HYPERCALL_MAX_LEN]; uint32_t n = len; // grab at most X bytes from memory to pandalog // this is just a snippet. we dont want to write 1M buffer if (QUERY_HYPERCALL_MAX_LEN < len) n = QUERY_HYPERCALL_MAX_LEN; for (uint32_t i=0; i<n; i++) { data[i] = 0; uint8_t c; panda_virtual_memory_rw(cpu, phs.buf+i, &c, 1, false); data[i] = c; } tqh->n_data = n; tqh->data = data; // 2. write out src-level info Panda__SrcInfo *si = pandalog_src_info_create(phs); tqh->src_info = si; // 3. write out callstack info Panda__CallStack *cs = pandalog_callstack_create(); tqh->call_stack = cs; std::vector<Panda__TaintQuery *> tq; for (uint32_t offset=0; offset<len; offset++) { uint32_t va = phs.buf + offset; uint32_t pa = panda_virt_to_phys(cpu, va); if ((int) pa != -1) { Addr a = make_maddr(pa); if (taint2_query(a)) { tq.push_back(taint2_query_pandalog(a, offset)); } } } tqh->n_taint_query = tq.size(); tqh->taint_query = (Panda__TaintQuery **) malloc(sizeof(Panda__TaintQuery *) * tqh->n_taint_query); for (uint32_t i=0; i<tqh->n_taint_query; i++) { tqh->taint_query[i] = tq[i]; } Panda__LogEntry ple = PANDA__LOG_ENTRY__INIT; ple.taint_query_hypercall = tqh; pandalog_write_entry(&ple); free(tqh->src_info); pandalog_callstack_free(tqh->call_stack); for (uint32_t i=0; i<tqh->n_taint_query; i++) { pandalog_taint_query_free(tqh->taint_query[i]); } free(tqh); } } }