if (proc_data->syscall_data_len < 0 ||
proc_data->syscall_data_len >= ARRAY_SIZE(proc_data->syscall_data))
panic("Syscall data was corrupted by stub (len is: %d, expected maximum: %d)!",
proc_data->syscall_data_len,
mm_idp->syscall_data_len);
staticinlinelong do_syscall_stub(struct mm_id *mm_idp)
{ struct stub_data *proc_data = (void *)mm_idp->stack; int n, i; int err, pid = mm_idp->pid;
/* Inform process how much we have filled in. */
proc_data->syscall_data_len = mm_idp->syscall_data_len;
if (using_seccomp) {
proc_data->restart_wait = 1;
wait_stub_done_seccomp(mm_idp, 0, 1);
} else {
n = ptrace_setregs(pid, syscall_regs); if (n < 0) {
printk(UM_KERN_ERR "Registers -\n"); for (i = 0; i < MAX_REG_NR; i++)
printk(UM_KERN_ERR "\t%d\t0x%lx\n", i, syscall_regs[i]);
panic("%s : PTRACE_SETREGS failed, errno = %d\n",
__func__, -n);
}
err = ptrace(PTRACE_CONT, pid, 0, 0); if (err)
panic("Failed to continue stub, pid = %d, errno = %d\n",
pid, errno);
wait_stub_done(pid);
}
/* * proc_data->err will be negative if there was an (unexpected) error. * In that case, syscall_data_len points to the last executed syscall, * otherwise it will be zero (but we do not need to rely on that).
*/ if (proc_data->err < 0) {
syscall_stub_dump_error(mm_idp);
/* Store error code in case someone tries to add more syscalls */
mm_idp->syscall_data_len = proc_data->err;
} else {
mm_idp->syscall_data_len = 0;
}
if (using_seccomp)
mm_idp->syscall_fd_num = 0;
return mm_idp->syscall_data_len;
}
int syscall_stub_flush(struct mm_id *mm_idp)
{ int res;
if (mm_idp->syscall_data_len == 0) return 0;
/* If an error happened already, report it and reset the state. */ if (mm_idp->syscall_data_len < 0) {
res = mm_idp->syscall_data_len;
mm_idp->syscall_data_len = 0; return res;
}
res = do_syscall_stub(mm_idp);
mm_idp->syscall_data_len = 0;
staticint get_stub_fd(struct mm_id *mm_idp, int fd)
{ int i;
/* Find an FD slot (or flush and use first) */ if (!using_seccomp) return fd;
/* Already crashed, value does not matter */ if (mm_idp->syscall_data_len < 0) return 0;
/* Find existing FD in map if we can allocate another syscall */ if (mm_idp->syscall_data_len <
ARRAY_SIZE(((struct stub_data *)NULL)->syscall_data)) { for (i = 0; i < mm_idp->syscall_fd_num; i++) { if (mm_idp->syscall_fd_map[i] == fd) return i;
}
if (mm_idp->syscall_fd_num < STUB_MAX_FDS) {
i = mm_idp->syscall_fd_num;
mm_idp->syscall_fd_map[i] = fd;
mm_idp->syscall_fd_num++;
return i;
}
}
/* FD map full or no syscall space available, continue after flush */
do_syscall_stub(mm_idp);
mm_idp->syscall_fd_map[0] = fd;
mm_idp->syscall_fd_num = 1;
return 0;
}
int map(struct mm_id *mm_idp, unsignedlong virt, unsignedlong len, int prot, int phys_fd, unsignedlonglong offset)
{ struct stub_syscall *sc;
/* Compress with previous syscall if that is possible */
sc = syscall_stub_get_previous(mm_idp, STUB_SYSCALL_MMAP, virt); if (sc && sc->mem.prot == prot &&
sc->mem.offset == MMAP_OFFSET(offset - sc->mem.length)) { int prev_fd = sc->mem.fd;
if (using_seccomp)
prev_fd = mm_idp->syscall_fd_map[sc->mem.fd];
/* Compress with previous syscall if that is possible */
sc = syscall_stub_get_previous(mm_idp, STUB_SYSCALL_MUNMAP, addr); if (sc) {
sc->mem.length += len; return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.