static int munmap_seized(struct parasite_ctl *ctl, void *addr, size_t length) { unsigned long x; return syscall_seized(ctl, __NR_munmap, &x, (unsigned long)addr, length, 0, 0, 0, 0); }
void *mmap_seized(struct parasite_ctl *ctl, void *addr, size_t length, int prot, int flags, int fd, off_t offset) { unsigned long map; int err; err = syscall_seized(ctl, __NR_mmap, &map, (unsigned long)addr, length, prot, flags, fd, offset); if (err < 0 || map > TASK_SIZE) map = 0; return (void *)map; }
void *mmap_seized(struct parasite_ctl *ctl, void *addr, size_t length, int prot, int flags, int fd, off_t offset) { unsigned long map; int err; err = syscall_seized(ctl, __NR_mmap, &map, (unsigned long)addr, length, prot, flags, fd, offset); if (err < 0) return NULL; if (IS_ERR_VALUE(map)) { if (map == -EACCES && (prot & PROT_WRITE) && (prot & PROT_EXEC)) pr_warn("mmap(PROT_WRITE | PROT_EXEC) failed for %d, " "check selinux execmem policy\n", ctl->pid.real); return NULL; } return (void *)map; }
static int execute_syscall(struct parasite_ctl *ctl, struct syscall_exec_desc *scd, char **opt) { int i, err; unsigned long args[MAX_ARGS] = {}, ret, r_mem_size = 0; unsigned int ret_args[MAX_ARGS] = {}; void *r_mem = NULL; for (i = 0; i < MAX_ARGS; i++) { if (opt[i] == NULL) break; /* * &foo -- argument string "foo" * @<size> -- ret-arg of size <size> */ if ((opt[i][0] == '&') || (opt[i][0] == '@')) { int len; if (!r_mem) { err = parasite_map_exchange(ctl, PAGE_SIZE); if (err) return err; r_mem_size = PAGE_SIZE; r_mem = ctl->local_map; } if (opt[i][0] == '&') { len = strlen(opt[i]); if (r_mem_size < len) { pr_err("Arg size overflow\n"); return -1; } memcpy(r_mem, opt[i] + 1, len); } else { len = strtol(opt[i] + 1, NULL, 0); if (!len || (r_mem_size < len)) { pr_err("Bad argument size %d\n", len); return -1; } ret_args[i] = len; } args[i] = (unsigned long)ctl->remote_map + (r_mem - ctl->local_map); pr_info("Pushing %c mem arg [%s]\n", opt[i][0], (char *)r_mem); r_mem_size -= len; r_mem += len; } else args[i] = strtol(opt[i], NULL, 0); } pr_info("Calling %d with %lu %lu %lu %lu %lu %lu\n", scd->nr, args[0], args[1], args[2], args[3], args[4], args[5]); err = syscall_seized(ctl, scd->nr, &ret, args[0], args[1], args[2], args[3], args[4], args[5]); if (err) return err; pr_msg("Syscall returned %lx(%d)\n", ret, (int)ret); for (i = 0; i < MAX_ARGS; i++) { unsigned long addr; if (!ret_args[i]) continue; pr_msg("Argument %d returns:\n", i); addr = (unsigned long)ctl->local_map + (args[i] - (unsigned long)ctl->remote_map); print_data(0, (unsigned char *)addr, ret_args[i]); } return 0; }