mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-28 12:36:47 +00:00
syscalls: add __NR(syscall, compat) wrapper
Generic code uses raw syscall numbers for: - syscall_seized, to execute through parasite control needed syscall; - parasite_stop_on_syscall, to trap couple of tasks on needed syscall. As syscall numbers may differ (and differ for x86) between native and compatible mode, we need proper syscall wrapper here. Cc: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com> Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
parent
f6126361a2
commit
094afe856b
9 changed files with 53 additions and 21 deletions
|
|
@ -5,6 +5,7 @@ struct parasite_ctl;
|
|||
|
||||
#define ARCH_SI_TRAP TRAP_BRKPT
|
||||
|
||||
#define __NR(syscall, compat) __NR_##syscall
|
||||
|
||||
void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ struct parasite_ctl;
|
|||
|
||||
#define ARCH_SI_TRAP TRAP_BRKPT
|
||||
|
||||
#define __NR(syscall, compat) __NR_##syscall
|
||||
|
||||
void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ struct parasite_ctl;
|
|||
|
||||
#define ARCH_SI_TRAP TRAP_BRKPT
|
||||
|
||||
#define __NR(syscall, compat) __NR_##syscall
|
||||
|
||||
void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
|
||||
|
||||
void *mmap_seized(struct parasite_ctl *ctl,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "types.h"
|
||||
#include "asm/processor-flags.h"
|
||||
#include "asm/parasite-syscall.h"
|
||||
#include "asm/restorer.h"
|
||||
#include "asm/fpu.h"
|
||||
|
||||
|
|
@ -18,6 +19,7 @@
|
|||
#include "util.h"
|
||||
#include "cpu.h"
|
||||
#include "errno.h"
|
||||
#include "syscall-codes.h"
|
||||
|
||||
#include "protobuf.h"
|
||||
#include "images/core.pb-c.h"
|
||||
|
|
@ -570,8 +572,9 @@ void *mmap_seized(struct parasite_ctl *ctl,
|
|||
{
|
||||
unsigned long map;
|
||||
int err;
|
||||
bool compat_task = !user_regs_native(&ctl->orig.regs);
|
||||
|
||||
err = syscall_seized(ctl, __NR_mmap, &map,
|
||||
err = syscall_seized(ctl, __NR(mmap, compat_task), &map,
|
||||
(unsigned long)addr, length, prot, flags, fd, offset);
|
||||
if (err < 0)
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,16 @@ struct parasite_ctl;
|
|||
|
||||
#define ARCH_SI_TRAP SI_KERNEL
|
||||
|
||||
#define __NR(syscall, compat) ((compat) ? __NR32_##syscall : __NR_##syscall)
|
||||
|
||||
/*
|
||||
* For x86_32 __NR_mmap inside the kernel represents old_mmap system
|
||||
* call, but since we didn't use it yet lets go further and simply
|
||||
* define own alias for __NR_mmap2 which would allow us to unify code
|
||||
* between 32 and 64 bits version.
|
||||
*/
|
||||
#define __NR32_mmap __NR32_mmap2
|
||||
|
||||
|
||||
void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,4 @@ extern long sys_getsockopt(int sockfd, int level, int optname, const void *optva
|
|||
extern long sys_shmat(int shmid, void *shmaddr, int shmflag);
|
||||
extern long sys_pread(unsigned int fd, char *ubuf, u32 count, u64 pos);
|
||||
|
||||
/*
|
||||
* For x86_32 __NR_mmap inside the kernel represents old_mmap system
|
||||
* call, but since we didn't use it yet lets go further and simply
|
||||
* define own alias for __NR_mmap2 which would allow us to unify code
|
||||
* between 32 and 64 bits version.
|
||||
*/
|
||||
#define __NR_mmap __NR_mmap2
|
||||
|
||||
#endif /* __CR_SYSCALL32_H__ */
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@
|
|||
|
||||
#include "parasite-syscall.h"
|
||||
#include "files-reg.h"
|
||||
#include "syscall-codes.h"
|
||||
|
||||
#include "protobuf.h"
|
||||
#include "images/sa.pb-c.h"
|
||||
|
|
@ -1864,7 +1865,7 @@ static int restore_root_task(struct pstree_item *init)
|
|||
|
||||
if (ret == 0)
|
||||
ret = parasite_stop_on_syscall(task_entries->nr_threads,
|
||||
__NR_rt_sigreturn, flag);
|
||||
__NR(rt_sigreturn, 0), __NR(rt_sigreturn, 1), flag);
|
||||
|
||||
if (clear_breakpoints())
|
||||
pr_err("Unable to flush breakpoints\n");
|
||||
|
|
|
|||
|
|
@ -132,7 +132,8 @@ enum trace_flags {
|
|||
};
|
||||
|
||||
extern int parasite_stop_daemon(struct parasite_ctl *ctl);
|
||||
extern int parasite_stop_on_syscall(int tasks, int sys_nr, enum trace_flags trace);
|
||||
extern int parasite_stop_on_syscall(int tasks, int sys_nr,
|
||||
int sys_nr_compat, enum trace_flags trace);
|
||||
extern int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr);
|
||||
extern int ptrace_stop_pie(pid_t pid, void *addr, enum trace_flags *tf);
|
||||
|
||||
|
|
|
|||
|
|
@ -927,7 +927,8 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (parasite_stop_on_syscall(1, __NR_rt_sigreturn, flag))
|
||||
if (parasite_stop_on_syscall(1, __NR(rt_sigreturn, 0),
|
||||
__NR(rt_sigreturn, 1), flag))
|
||||
return -1;
|
||||
|
||||
if (ptrace_flush_breakpoints(pid))
|
||||
|
|
@ -962,13 +963,31 @@ static bool task_is_trapped(int status, pid_t pid)
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline int is_required_syscall(user_regs_struct_t regs, pid_t pid,
|
||||
const int sys_nr, const int sys_nr_compat)
|
||||
{
|
||||
const char *mode = user_regs_native(®s) ? "native" : "compat";
|
||||
int req_sysnr = user_regs_native(®s) ? sys_nr : sys_nr_compat;
|
||||
|
||||
pr_debug("%d (%s) is going to execute the syscall %lu, required is %d\n",
|
||||
pid, mode, REG_SYSCALL_NR(regs), req_sysnr);
|
||||
if (user_regs_native(®s) && (REG_SYSCALL_NR(regs) == sys_nr))
|
||||
return true;
|
||||
if (!user_regs_native(®s) && (REG_SYSCALL_NR(regs) == sys_nr_compat))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Trap tasks on the exit from the specified syscall
|
||||
*
|
||||
* tasks - number of processes, which should be trapped
|
||||
* sys_nr - the required syscall number
|
||||
* sys_nr_compat - the required compatible syscall number
|
||||
*/
|
||||
int parasite_stop_on_syscall(int tasks, const int sys_nr, enum trace_flags trace)
|
||||
int parasite_stop_on_syscall(int tasks,
|
||||
const int sys_nr, const int sys_nr_compat,
|
||||
enum trace_flags trace)
|
||||
{
|
||||
user_regs_struct_t regs;
|
||||
int status, ret;
|
||||
|
|
@ -1004,8 +1023,7 @@ int parasite_stop_on_syscall(int tasks, const int sys_nr, enum trace_flags trace
|
|||
return -1;
|
||||
}
|
||||
|
||||
pr_debug("%d is going to execute the syscall %lu\n", pid, REG_SYSCALL_NR(regs));
|
||||
if (REG_SYSCALL_NR(regs) == sys_nr) {
|
||||
if (is_required_syscall(regs, pid, sys_nr, sys_nr_compat)) {
|
||||
/*
|
||||
* The process is going to execute the required syscall,
|
||||
* the next stop will be on the exit from this syscall
|
||||
|
|
@ -1083,7 +1101,7 @@ int parasite_cure_remote(struct parasite_ctl *ctl)
|
|||
} else {
|
||||
unsigned long ret;
|
||||
|
||||
syscall_seized(ctl, __NR_munmap, &ret,
|
||||
syscall_seized(ctl, __NR(munmap, !seized_native(ctl)), &ret,
|
||||
(unsigned long)ctl->remote_map, ctl->map_length,
|
||||
0, 0, 0, 0);
|
||||
if (ret) {
|
||||
|
|
@ -1137,7 +1155,8 @@ int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr)
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = parasite_stop_on_syscall(1, __NR_munmap, TRACE_ENTER);
|
||||
ret = parasite_stop_on_syscall(1, __NR(munmap, 0),
|
||||
__NR(munmap, 1), TRACE_ENTER);
|
||||
|
||||
if (restore_thread_ctx(pid, &ctl->orig))
|
||||
ret = -1;
|
||||
|
|
@ -1217,6 +1236,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
|
|||
pid_t pid = ctl->rpid;
|
||||
unsigned long sret = -ENOSYS;
|
||||
int ret, fd, lfd;
|
||||
bool __maybe_unused compat_task = !user_regs_native(&ctl->orig.regs);
|
||||
|
||||
if (fault_injected(FI_NO_MEMFD))
|
||||
return 1;
|
||||
|
|
@ -1228,13 +1248,14 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ret = syscall_seized(ctl, __NR_memfd_create, &sret,
|
||||
ret = syscall_seized(ctl, __NR(memfd_create, compat_task), &sret,
|
||||
(unsigned long)where, 0, 0, 0, 0, 0);
|
||||
|
||||
if (ptrace_poke_area(pid, orig_code, where, sizeof(orig_code))) {
|
||||
fd = (int)(long)sret;
|
||||
if (fd >= 0)
|
||||
syscall_seized(ctl, __NR_close, &sret, fd, 0, 0, 0, 0, 0);
|
||||
syscall_seized(ctl, __NR(close, compat_task), &sret,
|
||||
fd, 0, 0, 0, 0, 0);
|
||||
pr_err("Can't restore memfd args (pid: %d)\n", pid);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1274,7 +1295,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
|
|||
goto err_curef;
|
||||
}
|
||||
|
||||
syscall_seized(ctl, __NR_close, &sret, fd, 0, 0, 0, 0, 0);
|
||||
syscall_seized(ctl, __NR(close, compat_task), &sret, fd, 0, 0, 0, 0, 0);
|
||||
close(lfd);
|
||||
|
||||
pr_info("Set up parasite blob using memfd\n");
|
||||
|
|
@ -1283,7 +1304,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
|
|||
err_curef:
|
||||
close(lfd);
|
||||
err_cure:
|
||||
syscall_seized(ctl, __NR_close, &sret, fd, 0, 0, 0, 0, 0);
|
||||
syscall_seized(ctl, __NR(close, compat_task), &sret, fd, 0, 0, 0, 0, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue