/** @brief put the message received in the registers of recvmsg syscall */ void sys_build_recvmsg(process_descriptor_t * proc, syscall_arg_u * sysarg) { pid_t pid = proc->pid; recvmsg_arg_t arg = &(sysarg->recvmsg); ptrace_restore_syscall(pid, SYS_recvmsg, arg->ret); int length = arg->ret; int global_size = 0; int i; for (i = 0; i < arg->msg.msg_iovlen; ++i) { if (length < 0) break; struct iovec temp; ptrace_cpy(pid, &temp, arg->msg.msg_iov + i * sizeof(struct iovec), sizeof(struct iovec), "recvmsg"); if (length < temp.iov_len) temp.iov_len = length; ptrace_poke(pid, arg->msg.msg_iov + i * sizeof(struct iovec), &temp, sizeof(struct iovec)); ptrace_poke(pid, temp.iov_base, (char *) arg->data + global_size, temp.iov_len); } free(arg->data); }
/** @brief put the arguments we want in the registers of select syscall */ void sys_build_select(process_descriptor_t * proc, syscall_arg_u * sysarg, int match) { //TODO use unified union syscall_arg_u pid_t pid = proc->pid; ptrace_restore_syscall(pid, SYS_select, match); reg_s r; ptrace_get_register(pid, &r); select_arg_t arg = &(sysarg->select); if (arg->fd_state & SELECT_FDRD_SET) { ptrace_poke(pid, (void *) r.arg2, &(arg->fd_read), sizeof(fd_set)); } if (arg->fd_state & SELECT_FDWR_SET) { ptrace_poke(pid, (void *) r.arg3, &(arg->fd_write), sizeof(fd_set)); } if (arg->fd_state & SELECT_FDEX_SET) { ptrace_poke(pid, (void *) r.arg4, &(arg->fd_except), sizeof(fd_set)); } }
/** @brief translate the port and address of the entering connect syscall * * We take the arguments in the registers, which correspond to global * simulated address and port. We translate them to real local ones, * and put the result back in the registers to actually get the * connect syscall performed by the kernel. */ void sys_translate_connect_in(process_descriptor_t * proc, syscall_arg_u * sysarg) { connect_arg_t arg = &(sysarg->connect); pid_t pid = proc->pid; reg_s reg; ptrace_get_register(pid, ®); arg->sai.sin_port = htons(get_real_port(proc, arg->sai.sin_addr.s_addr, ntohs(arg->sai.sin_port))); arg->sai.sin_addr.s_addr = inet_addr("127.0.0.1"); XBT_DEBUG("Try to connect on 127.0.0.1:%d", arg->sai.sin_port); ptrace_poke(pid, (void *) reg.arg2, &(arg->sai), sizeof(struct sockaddr_in)); }
/** @brief put the arguments we want in the registers of poll syscall */ void sys_build_poll(process_descriptor_t * proc, syscall_arg_u * sysarg, int match) { pid_t pid = proc->pid; ptrace_restore_syscall(pid, SYS_poll, match); reg_s r; ptrace_get_register(pid, &r); poll_arg_t arg = &(sysarg->poll); arg->ret = match; if (r.arg1 != 0) { ptrace_poke(pid, (void *) r.arg1, arg->fd_list, sizeof(struct pollfd) * arg->nbfd); } }
/** @brief translate the port and address of the exiting connect syscall * * We take the arguments in the registers, which correspond to the real * local address and port we established the connection on. We translate * them into global simulated ones and put the result back in the registers, * so that the application gets wronged. */ void sys_translate_connect_out(process_descriptor_t * proc, syscall_arg_u * sysarg) { connect_arg_t arg = &(sysarg->connect); pid_t pid = proc->pid; reg_s reg; ptrace_get_register(pid, ®); translate_desc_t *td = get_translation(ntohs(arg->sai.sin_port)); arg->sai.sin_port = htons(td->port_num); arg->sai.sin_addr.s_addr = td->ip; XBT_DEBUG("Restore %s:%d", inet_ntoa(arg->sai.sin_addr), td->port_num); ptrace_poke(pid, (void *) reg.arg2, &(arg->sai), sizeof(struct sockaddr_in)); }
/** @brief translate the port and address of the exiting recvfrom syscall * * We take the arguments in the registers, which correspond to the real * local address and port we received the message from. We translate them * into global simulated ones and put the result back in the registers, so * that the application gets wronged. */ void sys_translate_recvfrom_out(process_descriptor_t * proc, syscall_arg_u * sysarg) { recvfrom_arg_t arg = &(sysarg->recvfrom); pid_t pid = proc->pid; reg_s reg; ptrace_get_register(pid, ®); if (reg.arg5 == 0) return; translate_desc_t *td = get_translation(ntohs(arg->sai.sin_port)); arg->sai.sin_port = htons(td->port_num); arg->sai.sin_addr.s_addr = td->ip; ptrace_poke(pid, (void *) reg.arg5, &(arg->sai), sizeof(struct sockaddr_in)); }
/** @brief translate the port and address of the entering recvfrom syscall * * We take the arguments in the registers, which correspond to the global * simulated address and port the application wants to receive the message * from. We translate them to real local ones and put the result back in the * registers to actually get the recvfrom syscall performed by the kernel. */ void sys_translate_recvfrom_in(process_descriptor_t * proc, syscall_arg_u * sysarg) { recvfrom_arg_t arg = &(sysarg->recvfrom); pid_t pid = proc->pid; reg_s reg; ptrace_get_register(pid, ®); if (reg.arg5 == 0) return; struct sockaddr_in temp = arg->sai; int port = get_real_port(proc, temp.sin_addr.s_addr, ntohs(temp.sin_port)); temp.sin_addr.s_addr = inet_addr("127.0.0.1"); temp.sin_port = htons(port); ptrace_poke(pid, (void *) reg.arg5, &temp, sizeof(struct sockaddr_in)); arg->sai = temp; XBT_DEBUG("Using 127.0.0.1:%d", port); }
/** @brief translate the port and address of the entering sendto syscall * * We take the arguments in the registers, which correspond to the global * simulated address and port the application wants to send the message to. * We translate them to real local ones and put the result back in the * registers to actually get the sendto syscall performed by the kernel. */ void sys_translate_sendto_in(process_descriptor_t * proc, syscall_arg_u * sysarg) { sendto_arg_t arg = &(sysarg->sendto); pid_t pid = proc->pid; reg_s reg; ptrace_get_register(pid, ®); if (reg.arg5 == 0) return; struct in_addr in = { arg->sai.sin_addr.s_addr }; XBT_DEBUG("Translate address %s:%d", inet_ntoa(in), ntohs(arg->sai.sin_port)); struct sockaddr_in temp = arg->sai; int port = get_real_port(proc, temp.sin_addr.s_addr, ntohs(temp.sin_port)); temp.sin_addr.s_addr = inet_addr("127.0.0.1"); temp.sin_port = htons(port); ptrace_poke(pid, (void *) reg.arg5, &temp, sizeof(struct sockaddr_in)); XBT_DEBUG("Using 127.0.0.1:%d", port); }
/** @brief translate the port and address of the exiting accept syscall * * We take the arguments in the registers, which correspond to the * real local address and port we obtained. We translate them into * global simulated ones and put the result back in the registers, so * that the application gets wronged. */ void sys_translate_accept_out(process_descriptor_t * proc, syscall_arg_u * sysarg) { accept_arg_t arg = &(sysarg->accept); pid_t pid = proc->pid; reg_s reg; ptrace_get_register(pid, ®); int port = ntohs(arg->sai.sin_port); struct infos_socket *is = get_infos_socket(proc, arg->sockfd); comm_get_ip_port_accept(is, &(arg->sai)); msg_host_t host; if (arg->sai.sin_addr.s_addr == inet_addr("127.0.0.1")) host = proc->host; else host = get_host_by_ip(arg->sai.sin_addr.s_addr); set_real_port(host, ntohs(arg->sai.sin_port), port); add_new_translation(port, ntohs(arg->sai.sin_port), arg->sai.sin_addr.s_addr); ptrace_poke(pid, (void *) reg.arg2, &(arg->sai), sizeof(struct sockaddr_in)); }
static VALUE ptrace_pokeuser(VALUE self, VALUE addr, VALUE data) { return ptrace_poke(self, PT_WRITE_U, addr, data); }
static VALUE ptrace_poketext(VALUE self, VALUE addr, VALUE data) { return ptrace_poke(self, PT_WRITE_I, addr, data); }