2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 18:07:57 +00:00
criu/cr-exec.c
Kir Kolyshkin d90d4b1b88 Fix typos in log messages
Someone has to do it, right?..

Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
2013-04-15 12:46:25 +04:00

129 lines
2.6 KiB
C

#include <unistd.h>
#include <string.h>
#include "crtools.h"
#include "ptrace.h"
#include "parasite-syscall.h"
struct syscall_exec_desc {
char *name;
unsigned nr;
};
static struct syscall_exec_desc sc_exec_table[] = {
#define SYSCALL(__name, __nr) { .name = #__name, .nr = __nr, },
#include "sys-exec-tbl.c"
#undef SYSCALL
{ }, /* terminator */
};
static struct syscall_exec_desc *find_syscall(char *name)
{
int i;
for (i = 0; sc_exec_table[i].name != NULL; i++)
if (!strcmp(sc_exec_table[i].name, name))
return &sc_exec_table[i];
return NULL;
}
#define MAX_ARGS 6
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;
void *r_mem = NULL;
for (i = 0; i < MAX_ARGS; i++) {
if (opt[i] == NULL)
break;
if (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;
}
len = strlen(opt[i]);
if (r_mem_size < len) {
pr_err("Arg size overflow\n");
return -1;
}
memcpy(r_mem, opt[i] + 1, len);
args[i] = (unsigned long)ctl->remote_map + (r_mem - ctl->local_map);
pr_info("Pushing mem arg [%s]\n", (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);
return 0;
}
int cr_exec(int pid, char **opt)
{
char *sys_name = opt[0];
struct syscall_exec_desc *si;
struct parasite_ctl *ctl;
struct vm_area_list vmas;
int ret = -1, prev_state;
if (!sys_name) {
pr_err("Syscall name required\n");
goto out;
}
si = find_syscall(sys_name);
if (!si) {
pr_err("Unknown syscall [%s]\n", sys_name);
goto out;
}
prev_state = ret = seize_task(pid, -1, NULL, NULL);
if (ret < 0) {
pr_err("Can't seize task %d\n", pid);
goto out;
}
ret = collect_mappings(pid, &vmas);
if (ret) {
pr_err("Can't collect vmas for %d\n", pid);
goto out_unseize;
}
ctl = parasite_prep_ctl(pid, &vmas);
if (!ctl) {
pr_err("Can't prep ctl %d\n", pid);
goto out_unseize;
}
ret = execute_syscall(ctl, si, opt + 1);
if (ret < 0)
pr_err("Can't execute syscall remotely\n");
parasite_cure_seized(ctl, NULL);
out_unseize:
unseize_task(pid, prev_state);
out:
return ret;
}