Commit 094afe85 authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Andrei Vagin

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: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent f6126361
......@@ -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(&regs) ? "native" : "compat";
int req_sysnr = user_regs_native(&regs) ? 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(&regs) && (REG_SYSCALL_NR(regs) == sys_nr))
return true;
if (!user_regs_native(&regs) && (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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment