static long dune_clone(struct dune_tf *tf) { unsigned long fs; int rc; unsigned long pc; rdmsrl(MSR_GS_BASE, pc); if (ARG1(tf) != 0) return dune_pthread_create(tf); fs = dune_get_user_fs(); rc = syscall(SYS_clone, ARG0(tf), ARG1(tf), ARG2(tf), ARG3(tf), ARG4(tf)); if (rc < 0) return -errno; if (rc == 0) { dune_enter(); dune_set_user_fs(fs); } return rc; }
LONG rxsupp_delay(struct Library *RexxSupportBase, struct RexxMsg *msg, UBYTE **argstring) { int pos, len; char *arg = ARG1(msg); len = strlen(arg); if (len == 0) { *argstring = NULL; return ERR10_018; } for (pos = 0; pos < len; pos++) { if (!isdigit(arg[pos])) { *argstring = NULL; return ERR10_018; } } Delay(atoi(arg)); *argstring = CreateArgstring("0", 1); return RC_OK; }
LONG rxsupp_rename(struct Library *RexxSupportBase, struct RexxMsg *msg, UBYTE **argstring) { BOOL ok; ok = Rename(ARG1(msg), ARG2(msg)); *argstring = CreateArgstring(ok ? "1" : "0", 1); return RC_OK; }
/* ARG1 = fd de salida. * ARG2 = puntero (en espacio de usuario). * ARG3 = tamaño. */ int sys_write( struct registers *r ) { int i; const char *str = (const char *) ARG2(r); if ( ARG1(r) != 1 ) return -1; /* if ( chequear_direccion(r->ecx, r->edx) == MALA ) return -1; */ for ( i = 0; i < ARG3(r); i++ ) kputc( str[i] ); return ARG3(r); }
void *pthread_entry(void *arg) { struct thread_arg *a = arg; struct dune_tf *tf = a->ta_tf; struct dune_tf child_tf; int *tidp = NULL; pid_t tid; int flags = ARG0(tf); if (!a->dune_started) dune_enter(); tid = syscall(SYS_gettid); /* XXX validate */ /* set up tls */ if (flags & CLONE_SETTLS) dune_set_user_fs(ARG4(tf)); if (flags & CLONE_PARENT_SETTID) { tidp = (int *) ARG2(tf); *tidp = tid; } if (flags & CLONE_CHILD_CLEARTID) { tidp = (int *) ARG3(tf); syscall(SYS_set_tid_address, tidp); } /* enter thread */ memcpy(&child_tf, tf, sizeof(child_tf)); child_tf.rip = tf->rip; child_tf.rax = 0; child_tf.rsp = ARG1(tf); /* tell parent tid */ pthread_mutex_lock(&a->ta_mtx); a->ta_tid = tid; pthread_mutex_unlock(&a->ta_mtx); pthread_cond_signal(&a->ta_cnd); do_enter_thread(&child_tf); return NULL; }
/* Force the target to call `dlopen()'. Modify its registers and stack contents * and continue execution until a segmentation fault is caught. Return 0 on * success and -1 on failure. */ static int force_dlopen(pid_t pid, char *filename) { void *linker_addr, *dlopen_off, *dlopen_addr; regs_t regs; size_t size; int r = -1; if(resolve_symbol(LINKER_PATH, DLOPEN_NAME1, &dlopen_off) != 0 && resolve_symbol(LINKER_PATH, DLOPEN_NAME2, &dlopen_off) != 0 && resolve_symbol(LINKER_PATH, DLOPEN_NAME3, &dlopen_off) != 0) { printf("[*] Could not resolve dlopen()\n"); goto ret; } if((linker_addr = get_linker_addr(pid)) == NULL) { printf("[*] Linker not found in PID %d\n", pid); goto ret; } dlopen_addr = linker_addr + (ptrdiff_t)dlopen_off; printf("[*] Resolved dlopen() at %p\n", dlopen_addr); if(read_registers(pid, ®s) != 0) goto ret; /* Prepare `do_dlopen()' input arguments. On Android >= 7, we set the 4th * argument to a value that emulates `__builtin_return_address()', so that * our DSO is loaded in the correct namespace. */ ARG0(regs) = SP(regs) + SP_OFF; ARG1(regs) = RTLD_NOW | RTLD_GLOBAL; ARG2(regs) = 0; ARG3(regs) = PC(regs); /* We set the new PC and also set LR to force the debuggee to crash. */ #if defined(__aarch64__) LR(regs) = 0xffffffffffffffff; PC(regs) = (reg_t)dlopen_addr; #elif defined(__arm__) LR(regs) = 0xffffffff; PC(regs) = (reg_t)dlopen_addr | 1; CPSR(regs) |= 1 << 5; #endif printf("[*] Modifying target's state\n"); if(write_registers(pid, ®s) != 0) goto ret; size = strlen(filename) + 1; if(write_memory(pid, (void *)SP(regs) + SP_OFF, filename, size) != size) goto ret; printf("[*] Waiting for target to throw SIGSEGV or SIGBUS\n"); if(resume_and_wait(pid) != 0) goto ret; r = 0; ret: return r; }
return 1; } /************************************************************************/ /* All supported sample and ACL keywords must be declared here. */ /************************************************************************/ /* Note: must not be declared <const> as its list will be overwritten. * Note: fetches that may return multiple types must be declared as the lowest * common denominator, the type that can be casted into all other ones. For * instance IPv4/IPv6 must be declared IPv4. */ static struct sample_fetch_kw_list smp_kws = {ILH, { { "payload", smp_fetch_payload, ARG2(2,UINT,UINT), NULL, SMP_T_CBIN, SMP_USE_L6REQ|SMP_USE_L6RES }, { "payload_lv", smp_fetch_payload_lv, ARG3(2,UINT,UINT,SINT), val_payload_lv, SMP_T_CBIN, SMP_USE_L6REQ|SMP_USE_L6RES }, { "rdp_cookie", smp_fetch_rdp_cookie, ARG1(0,STR), NULL, SMP_T_CSTR, SMP_USE_L6REQ }, { "rdp_cookie_cnt", smp_fetch_rdp_cookie_cnt, ARG1(0,STR), NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "rep_ssl_hello_type", smp_fetch_ssl_hello_type, 0, NULL, SMP_T_UINT, SMP_USE_L6RES }, { "req_len", smp_fetch_len, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req_ssl_hello_type", smp_fetch_ssl_hello_type, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req_ssl_sni", smp_fetch_ssl_hello_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L6REQ }, { "req_ssl_ver", smp_fetch_req_ssl_ver, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req.len", smp_fetch_len, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req.payload", smp_fetch_payload, ARG2(2,UINT,UINT), NULL, SMP_T_CBIN, SMP_USE_L6REQ }, { "req.payload_lv", smp_fetch_payload_lv, ARG3(2,UINT,UINT,SINT), val_payload_lv, SMP_T_CBIN, SMP_USE_L6REQ }, { "req.rdp_cookie", smp_fetch_rdp_cookie, ARG1(0,STR), NULL, SMP_T_CSTR, SMP_USE_L6REQ }, { "req.rdp_cookie_cnt", smp_fetch_rdp_cookie_cnt, ARG1(0,STR), NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req.ssl_hello_type", smp_fetch_ssl_hello_type, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req.ssl_sni", smp_fetch_ssl_hello_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L6REQ }, { "req.ssl_ver", smp_fetch_req_ssl_ver, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ },
static void syscall_do_foreal(struct dune_tf *tf) { switch (tf->rax) { case SYS_arch_prctl: switch (ARG0(tf)) { case ARCH_GET_FS: *((unsigned long*) ARG1(tf)) = dune_get_user_fs(); tf->rax = 0; break; case ARCH_SET_FS: dune_set_user_fs(ARG1(tf)); tf->rax = 0; break; default: tf->rax = -EINVAL; break; } break; case SYS_brk: tf->rax = umm_brk((unsigned long) ARG0(tf)); break; case SYS_mmap: tf->rax = (unsigned long) umm_mmap((void *) ARG0(tf), (size_t) ARG1(tf), (int) ARG2(tf), (int) ARG3(tf), (int) ARG4(tf), (off_t) ARG5(tf)); break; case SYS_mprotect: tf->rax = umm_mprotect((void *) ARG0(tf), (size_t) ARG1(tf), ARG2(tf)); break; case SYS_munmap: tf->rax = umm_munmap((void *) ARG0(tf), (size_t) ARG1(tf)); break; case SYS_mremap: tf->rax = (unsigned long) umm_mremap((void*) ARG0(tf), (size_t) ARG1(tf), (size_t) ARG2(tf), (int) ARG3(tf), (void*) ARG4(tf)); break; case SYS_shmat: tf->rax = (unsigned long) umm_shmat((int) ARG0(tf), (void*) ARG1(tf), (int) ARG2(tf)); break; case SYS_clone: tf->rax = dune_clone(tf); break; case SYS_execve: tf->rax = exec_execev((const char *)ARG0(tf), (char **const)ARG1(tf), (char **const)ARG2(tf)); break; /* ignore signals for now */ case SYS_rt_sigaction: case SYS_rt_sigprocmask: tf->rax = 0; break; case SYS_sigaltstack: case SYS_signalfd: case SYS_signalfd4: case SYS_rt_sigpending: case SYS_rt_sigreturn: case SYS_rt_sigsuspend: case SYS_rt_sigqueueinfo: case SYS_rt_sigtimedwait: tf->rax = -ENOSYS; break; case SYS_exit_group: case SYS_exit: dune_ret_from_user(ARG0(tf)); break; default: dune_passthrough_syscall(tf); break; } }
static int syscall_check_params(struct dune_tf *tf) { void *ptr = NULL; uint64_t len = 0; char *str = NULL; int err = 0; switch (tf->rax) { case SYS_uname: ptr = (void*) ARG0(tf); len = sizeof(struct utsname); break; case SYS_arch_prctl: if (ARG0(tf) == ARCH_GET_FS) { ptr = (void*) ARG1(tf); len = sizeof(unsigned long); } break; case SYS_access: case SYS_open: case SYS_unlink: str = (char*) ARG0(tf); break; case SYS_openat: str = (char*) ARG1(tf); break; case SYS_getdents: case SYS_read: case SYS_write: case SYS_connect: case SYS_bind: ptr = (void*) ARG1(tf); len = ARG2(tf); break; case SYS_writev: case SYS_readv: err = check_iovec((struct iovec*) ARG1(tf), ARG2(tf)); break; case SYS_stat: case SYS_lstat: str = (char*) ARG0(tf); case SYS_fstat: ptr = (void*) ARG1(tf); len = sizeof(struct stat); break; case SYS_statfs: str = (char*) ARG0(tf); ptr = (void*) ARG1(tf); len = sizeof(struct statfs); break; case SYS_time: ptr = (void*) ARG0(tf); len = sizeof(time_t); break; case SYS_epoll_ctl: ptr = (void*) ARG3(tf); len = sizeof(struct epoll_event); break; case SYS_epoll_wait: ptr = (void*) ARG1(tf); len = ARG2(tf) * sizeof(struct epoll_event); break; case SYS_setsockopt: ptr = (void*) ARG3(tf); len = ARG4(tf); break; case SYS_accept: if (ARG2(tf)) { socklen_t *l = (socklen_t*) ARG2(tf); if (check_extent(l, sizeof(*l))) err = -EFAULT; else { len = *l; ptr = (void*) ARG1(tf); assert(ptr); } } break; case SYS_fcntl: switch (ARG1(tf)) { case F_DUPFD: case F_DUPFD_CLOEXEC: case F_GETFD: case F_SETFD: case F_GETFL: case F_SETFL: case F_GETOWN: case F_SETOWN: break; case F_SETLKW: case F_GETLK: case F_SETLK: ptr = (void*) ARG2(tf); len = sizeof(struct flock); break; default: err = -EFAULT; break; } break; case SYS_ioctl: /* XXX unreliable */ if (_IOC_DIR(ARG1(tf))) { ptr = (void*) ARG2(tf); len = _IOC_SIZE(ARG1(tf)); } break; case SYS_setgroups: ptr = (void*) ARG1(tf); len = sizeof(gid_t) * ARG0(tf); break; case SYS_rt_sigaction: ptr = (void*) ARG1(tf); len = sizeof(struct sigaction); if (ARG2(tf)) { if (check_extent((void*) ARG2(tf), len)) { tf->rax = -EFAULT; return -1; } } break; case SYS_sigaltstack: case SYS_signalfd: case SYS_signalfd4: ptr = (void*) ARG1(tf); len = sizeof(sigset_t); break; case SYS_rt_sigpending: ptr = (void*) ARG0(tf); len = sizeof(sigset_t); break; case SYS_rt_sigprocmask: if (ARG1(tf)) { ptr = (void*) ARG1(tf); len = sizeof(sigset_t); } if (ARG2(tf)) { if (check_extent((void*) ARG2(tf), sizeof(sigset_t))) { tf->rax = -EFAULT; return -1; } } break; case SYS_rt_sigreturn: break; case SYS_rt_sigsuspend: ptr = (void*) ARG0(tf); len = sizeof(sigset_t); break; case SYS_rt_sigqueueinfo: ptr = (void*) ARG1(tf); len = sizeof(siginfo_t); break; case SYS_rt_sigtimedwait: if (check_extent((void*) ARG0(tf), sizeof(siginfo_t))) { tf->rax = -EFAULT; return -1; } if (check_extent((void*) ARG1(tf), sizeof(siginfo_t))) { tf->rax = -EFAULT; return -1; } if (ARG2(tf)) { if (check_extent((void*) ARG2(tf), sizeof(struct timespec))) { tf->rax = -EFAULT; return -1; } } break; /* umm_ checks for correctness */ case SYS_brk: break; case SYS_mprotect: case SYS_munmap: case SYS_mmap: // ptr = (void*) ARG0(tf); // len = ARG1(tf); break; case SYS_getcwd: ptr = (void*) ARG0(tf); len = ARG1(tf); break; case SYS_getrlimit: ptr = (void*) ARG1(tf); len = sizeof(struct rlimit); break; case SYS_sendfile: ptr = (void*) ARG2(tf); len = sizeof(off_t); break; case SYS_getuid: case SYS_setuid: case SYS_getgid: case SYS_setgid: case SYS_getpid: case SYS_epoll_create: case SYS_dup2: case SYS_socket: case SYS_shutdown: case SYS_listen: case SYS_lseek: break; /* XXX - doesn't belong here */ case SYS_close: if (ARG0(tf) < 3) { tf->rax = 0; return -1; } break; case SYS_execve: { char *p = (char*)ARG0(tf); if (check_string(p)) { err = -EFAULT; break; } // XXX: Check arrays break; } default: #if 0 { static FILE *_out; if (!_out) _out = fopen("/tmp/syscall.log", "w"); fprintf(_out, "Syscall %d\n", tf->rax); fflush(_out); } #endif break; } if (ptr != NULL && len != 0 && check_extent(ptr, len)) err = -EFAULT; if (str != NULL && check_string(str)) err = -EFAULT; if (err) { tf->rax = err; return -1; } return 0; }
static int smp_fetch_fe_conn(struct proxy *px, struct session *l4, void *l7, unsigned int opt, const struct arg *args, struct sample *smp) { smp->flags = SMP_F_VOL_TEST; smp->type = SMP_T_UINT; smp->data.uint = args->data.prx->feconn; return 1; } /* Note: must not be declared <const> as its list will be overwritten. * Please take care of keeping this list alphabetically sorted. */ static struct sample_fetch_kw_list smp_kws = {{ },{ { "fe_conn", smp_fetch_fe_conn, ARG1(1,FE), NULL, SMP_T_UINT, SMP_USE_INTRN, }, { "fe_id", smp_fetch_fe_id, 0, NULL, SMP_T_UINT, SMP_USE_FTEND, }, { "fe_sess_rate", smp_fetch_fe_sess_rate, ARG1(1,FE), NULL, SMP_T_UINT, SMP_USE_INTRN, }, { /* END */ }, }}; /* Note: must not be declared <const> as its list will be overwritten. * Please take care of keeping this list alphabetically sorted. */ static struct acl_kw_list acl_kws = {{ },{ { /* END */ }, }}; __attribute__((constructor))