fix REQ-43
This commit is contained in:
@@ -28,6 +28,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <cls.h>
|
#include <cls.h>
|
||||||
|
#include <prctl.h>
|
||||||
|
|
||||||
#define LAPIC_ID 0x020
|
#define LAPIC_ID 0x020
|
||||||
#define LAPIC_TIMER 0x320
|
#define LAPIC_TIMER 0x320
|
||||||
@@ -1533,6 +1534,15 @@ ihk_mc_user_context_t *lookup_user_context(struct thread *thread)
|
|||||||
return uctx;
|
return uctx;
|
||||||
} /* lookup_user_context() */
|
} /* lookup_user_context() */
|
||||||
|
|
||||||
|
extern long do_arch_prctl(unsigned long code, unsigned long address);
|
||||||
|
void
|
||||||
|
ihk_mc_init_user_tlsbase(ihk_mc_user_context_t *ctx,
|
||||||
|
unsigned long tls_base_addr)
|
||||||
|
{
|
||||||
|
do_arch_prctl(ARCH_SET_FS, tls_base_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
@ assigns \nothing;
|
@ assigns \nothing;
|
||||||
@*/
|
@*/
|
||||||
|
|||||||
17
arch/x86/kernel/include/prctl.h
Normal file
17
arch/x86/kernel/include/prctl.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* \file prctl.h
|
||||||
|
* License details are found in the file LICENSE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* HISTORY
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_PRCTL_H
|
||||||
|
#define __ARCH_PRCTL_H
|
||||||
|
|
||||||
|
#define ARCH_SET_GS 0x1001
|
||||||
|
#define ARCH_SET_FS 0x1002
|
||||||
|
#define ARCH_GET_FS 0x1003
|
||||||
|
#define ARCH_GET_GS 0x1004
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <uio.h>
|
#include <uio.h>
|
||||||
#include <mman.h>
|
#include <mman.h>
|
||||||
#include <shm.h>
|
#include <shm.h>
|
||||||
|
#include <prctl.h>
|
||||||
|
|
||||||
void terminate(int, int);
|
void terminate(int, int);
|
||||||
extern long do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact);
|
extern long do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact);
|
||||||
@@ -550,6 +551,75 @@ void ptrace_report_signal(struct thread *thread, int sig)
|
|||||||
schedule();
|
schedule();
|
||||||
dkprintf("ptrace_report_signal,wake up\n");
|
dkprintf("ptrace_report_signal,wake up\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
ptrace_arch_prctl(int pid, long code, long addr)
|
||||||
|
{
|
||||||
|
long rc = -EIO;
|
||||||
|
struct thread *child;
|
||||||
|
struct mcs_rwlock_node_irqsave lock;
|
||||||
|
|
||||||
|
child = find_thread(pid, pid, &lock);
|
||||||
|
if (!child)
|
||||||
|
return -ESRCH;
|
||||||
|
if (child->proc->status == PS_TRACED) {
|
||||||
|
switch (code) {
|
||||||
|
case ARCH_GET_FS: {
|
||||||
|
unsigned long value;
|
||||||
|
unsigned long *p = (unsigned long *)addr;
|
||||||
|
rc = ptrace_read_user(child,
|
||||||
|
offsetof(struct user_regs_struct, fs_base),
|
||||||
|
&value);
|
||||||
|
if (rc == 0) {
|
||||||
|
rc = copy_to_user(p, (char *)&value, sizeof(value));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARCH_GET_GS: {
|
||||||
|
unsigned long value;
|
||||||
|
unsigned long *p = (unsigned long *)addr;
|
||||||
|
rc = ptrace_read_user(child,
|
||||||
|
offsetof(struct user_regs_struct, gs_base),
|
||||||
|
&value);
|
||||||
|
if (rc == 0) {
|
||||||
|
rc = copy_to_user(p, (char *)&value, sizeof(value));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ARCH_SET_FS:
|
||||||
|
rc = ptrace_write_user(child,
|
||||||
|
offsetof(struct user_regs_struct, fs_base),
|
||||||
|
(unsigned long)addr);
|
||||||
|
break;
|
||||||
|
case ARCH_SET_GS:
|
||||||
|
rc = ptrace_write_user(child,
|
||||||
|
offsetof(struct user_regs_struct, gs_base),
|
||||||
|
(unsigned long)addr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thread_unlock(child, &lock);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
long
|
||||||
|
arch_ptrace(long request, int pid, long addr, long data)
|
||||||
|
{
|
||||||
|
switch(request) {
|
||||||
|
case PTRACE_ARCH_PRCTL:
|
||||||
|
return ptrace_arch_prctl(pid, data, addr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isrestart(int num, unsigned long rc, int sig, int restart)
|
isrestart(int num, unsigned long rc, int sig, int restart)
|
||||||
{
|
{
|
||||||
@@ -1387,3 +1457,52 @@ out:
|
|||||||
dkprintf("shmget(%#lx,%#lx,%#x): %d %d\n", key, size, shmflg0, error, shmid);
|
dkprintf("shmget(%#lx,%#lx,%#x): %d %d\n", key, size, shmflg0, error, shmid);
|
||||||
return (error)?: shmid;
|
return (error)?: shmid;
|
||||||
} /* sys_shmget() */
|
} /* sys_shmget() */
|
||||||
|
|
||||||
|
long do_arch_prctl(unsigned long code, unsigned long address)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
enum ihk_asr_type type;
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case ARCH_SET_FS:
|
||||||
|
case ARCH_GET_FS:
|
||||||
|
type = IHK_ASR_X86_FS;
|
||||||
|
break;
|
||||||
|
case ARCH_GET_GS:
|
||||||
|
type = IHK_ASR_X86_GS;
|
||||||
|
break;
|
||||||
|
case ARCH_SET_GS:
|
||||||
|
return -ENOTSUPP;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case ARCH_SET_FS:
|
||||||
|
dkprintf("[%d] arch_prctl: ARCH_SET_FS: 0x%lX\n",
|
||||||
|
ihk_mc_get_processor_id(), address);
|
||||||
|
cpu_local_var(current)->tlsblock_base = address;
|
||||||
|
err = ihk_mc_arch_set_special_register(type, address);
|
||||||
|
break;
|
||||||
|
case ARCH_SET_GS:
|
||||||
|
err = ihk_mc_arch_set_special_register(type, address);
|
||||||
|
break;
|
||||||
|
case ARCH_GET_FS:
|
||||||
|
case ARCH_GET_GS:
|
||||||
|
err = ihk_mc_arch_get_special_register(type,
|
||||||
|
(unsigned long*)address);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SYSCALL_DECLARE(arch_prctl)
|
||||||
|
{
|
||||||
|
return do_arch_prctl(ihk_mc_syscall_arg0(ctx),
|
||||||
|
ihk_mc_syscall_arg1(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,11 +69,6 @@
|
|||||||
#define SCD_MSG_PROCFS_TID_CREATE 0x44
|
#define SCD_MSG_PROCFS_TID_CREATE 0x44
|
||||||
#define SCD_MSG_PROCFS_TID_DELETE 0x45
|
#define SCD_MSG_PROCFS_TID_DELETE 0x45
|
||||||
|
|
||||||
#define ARCH_SET_GS 0x1001
|
|
||||||
#define ARCH_SET_FS 0x1002
|
|
||||||
#define ARCH_GET_FS 0x1003
|
|
||||||
#define ARCH_GET_GS 0x1004
|
|
||||||
|
|
||||||
/* Cloning flags. */
|
/* Cloning flags. */
|
||||||
# define CSIGNAL 0x000000ff /* Signal mask to be sent at exit. */
|
# define CSIGNAL 0x000000ff /* Signal mask to be sent at exit. */
|
||||||
# define CLONE_VM 0x00000100 /* Set if VM shared between processes. */
|
# define CLONE_VM 0x00000100 /* Set if VM shared between processes. */
|
||||||
|
|||||||
@@ -42,7 +42,6 @@
|
|||||||
#define ekprintf(...) kprintf(__VA_ARGS__)
|
#define ekprintf(...) kprintf(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern long do_arch_prctl(unsigned long code, unsigned long address);
|
|
||||||
extern long alloc_debugreg(struct thread *proc);
|
extern long alloc_debugreg(struct thread *proc);
|
||||||
extern void save_debugreg(unsigned long *debugreg);
|
extern void save_debugreg(unsigned long *debugreg);
|
||||||
extern void restore_debugreg(unsigned long *debugreg);
|
extern void restore_debugreg(unsigned long *debugreg);
|
||||||
@@ -2626,7 +2625,7 @@ redo:
|
|||||||
ihk_mc_get_processor_id(), next->tlsblock_base);
|
ihk_mc_get_processor_id(), next->tlsblock_base);
|
||||||
|
|
||||||
/* Set up new TLS.. */
|
/* Set up new TLS.. */
|
||||||
do_arch_prctl(ARCH_SET_FS, next->tlsblock_base);
|
ihk_mc_init_user_tlsbase(next->uctx, next->tlsblock_base);
|
||||||
|
|
||||||
if (prev) {
|
if (prev) {
|
||||||
last = ihk_mc_switch_context(&prev->ctx, &next->ctx, prev);
|
last = ihk_mc_switch_context(&prev->ctx, &next->ctx, prev);
|
||||||
|
|||||||
108
kernel/syscall.c
108
kernel/syscall.c
@@ -114,6 +114,7 @@ extern void debug_log(unsigned long);
|
|||||||
extern void free_all_process_memory_range(struct process_vm *vm);
|
extern void free_all_process_memory_range(struct process_vm *vm);
|
||||||
extern int arch_clear_host_user_space();
|
extern int arch_clear_host_user_space();
|
||||||
extern int arch_range_check(unsigned long addr, unsigned long len);
|
extern int arch_range_check(unsigned long addr, unsigned long len);
|
||||||
|
extern long arch_ptrace(long request, int pid, long addr, long data);
|
||||||
extern struct cpu_local_var *clv;
|
extern struct cpu_local_var *clv;
|
||||||
|
|
||||||
int prepare_process_ranges_args_envs(struct thread *thread,
|
int prepare_process_ranges_args_envs(struct thread *thread,
|
||||||
@@ -1426,54 +1427,6 @@ SYSCALL_DECLARE(gettid)
|
|||||||
return cpu_local_var(current)->tid;
|
return cpu_local_var(current)->tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
long do_arch_prctl(unsigned long code, unsigned long address)
|
|
||||||
{
|
|
||||||
int err = 0;
|
|
||||||
enum ihk_asr_type type;
|
|
||||||
|
|
||||||
switch (code) {
|
|
||||||
case ARCH_SET_FS:
|
|
||||||
case ARCH_GET_FS:
|
|
||||||
type = IHK_ASR_X86_FS;
|
|
||||||
break;
|
|
||||||
case ARCH_GET_GS:
|
|
||||||
type = IHK_ASR_X86_GS;
|
|
||||||
break;
|
|
||||||
case ARCH_SET_GS:
|
|
||||||
return -ENOTSUPP;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (code) {
|
|
||||||
case ARCH_SET_FS:
|
|
||||||
dkprintf("[%d] arch_prctl: ARCH_SET_FS: 0x%lX\n",
|
|
||||||
ihk_mc_get_processor_id(), address);
|
|
||||||
cpu_local_var(current)->tlsblock_base = address;
|
|
||||||
err = ihk_mc_arch_set_special_register(type, address);
|
|
||||||
break;
|
|
||||||
case ARCH_SET_GS:
|
|
||||||
err = ihk_mc_arch_set_special_register(type, address);
|
|
||||||
break;
|
|
||||||
case ARCH_GET_FS:
|
|
||||||
case ARCH_GET_GS:
|
|
||||||
err = ihk_mc_arch_get_special_register(type,
|
|
||||||
(unsigned long*)address);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SYSCALL_DECLARE(arch_prctl)
|
|
||||||
{
|
|
||||||
return do_arch_prctl(ihk_mc_syscall_arg0(ctx),
|
|
||||||
ihk_mc_syscall_arg1(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void ptrace_report_signal(struct thread *thread, int sig);
|
extern void ptrace_report_signal(struct thread *thread, int sig);
|
||||||
static int ptrace_report_exec(struct thread *thread)
|
static int ptrace_report_exec(struct thread *thread)
|
||||||
{
|
{
|
||||||
@@ -4606,59 +4559,6 @@ static long ptrace_setregs(int pid, long data)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long ptrace_arch_prctl(int pid, long code, long addr)
|
|
||||||
{
|
|
||||||
long rc = -EIO;
|
|
||||||
struct thread *child;
|
|
||||||
struct mcs_rwlock_node_irqsave lock;
|
|
||||||
|
|
||||||
child = find_thread(pid, pid, &lock);
|
|
||||||
if (!child)
|
|
||||||
return -ESRCH;
|
|
||||||
if (child->proc->status == PS_TRACED) {
|
|
||||||
switch (code) {
|
|
||||||
case ARCH_GET_FS: {
|
|
||||||
unsigned long value;
|
|
||||||
unsigned long *p = (unsigned long *)addr;
|
|
||||||
rc = ptrace_read_user(child,
|
|
||||||
offsetof(struct user_regs_struct, fs_base),
|
|
||||||
&value);
|
|
||||||
if (rc == 0) {
|
|
||||||
rc = copy_to_user(p, (char *)&value, sizeof(value));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ARCH_GET_GS: {
|
|
||||||
unsigned long value;
|
|
||||||
unsigned long *p = (unsigned long *)addr;
|
|
||||||
rc = ptrace_read_user(child,
|
|
||||||
offsetof(struct user_regs_struct, gs_base),
|
|
||||||
&value);
|
|
||||||
if (rc == 0) {
|
|
||||||
rc = copy_to_user(p, (char *)&value, sizeof(value));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ARCH_SET_FS:
|
|
||||||
rc = ptrace_write_user(child,
|
|
||||||
offsetof(struct user_regs_struct, fs_base),
|
|
||||||
(unsigned long)addr);
|
|
||||||
break;
|
|
||||||
case ARCH_SET_GS:
|
|
||||||
rc = ptrace_write_user(child,
|
|
||||||
offsetof(struct user_regs_struct, gs_base),
|
|
||||||
(unsigned long)addr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rc = -EINVAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
thread_unlock(child, &lock);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern long ptrace_read_fpregs(struct thread *thread, void *fpregs);
|
extern long ptrace_read_fpregs(struct thread *thread, void *fpregs);
|
||||||
extern long ptrace_write_fpregs(struct thread *thread, void *fpregs);
|
extern long ptrace_write_fpregs(struct thread *thread, void *fpregs);
|
||||||
|
|
||||||
@@ -5169,16 +5069,12 @@ SYSCALL_DECLARE(ptrace)
|
|||||||
dkprintf("ptrace: PTRACE_SETREGSET: addr=0x%x, data=%p\n", addr, data);
|
dkprintf("ptrace: PTRACE_SETREGSET: addr=0x%x, data=%p\n", addr, data);
|
||||||
error = ptrace_setregset(pid, addr, data);
|
error = ptrace_setregset(pid, addr, data);
|
||||||
break;
|
break;
|
||||||
case PTRACE_ARCH_PRCTL:
|
|
||||||
error = ptrace_arch_prctl(pid, data, addr);
|
|
||||||
dkprintf("PTRACE_ARCH_PRCTL: data=%p addr=%p return=%p\n", data, addr, error);
|
|
||||||
break;
|
|
||||||
case PTRACE_GETEVENTMSG:
|
case PTRACE_GETEVENTMSG:
|
||||||
dkprintf("ptrace: PTRACE_GETEVENTMSG: data=%p\n", data);
|
dkprintf("ptrace: PTRACE_GETEVENTMSG: data=%p\n", data);
|
||||||
error = ptrace_geteventmsg(pid, data);
|
error = ptrace_geteventmsg(pid, data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
kprintf("ptrace: unimplemented ptrace(%d) called.\n", request);
|
error = arch_ptrace(request, pid, addr, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ void ihk_mc_init_user_process(ihk_mc_kernel_context_t *ctx,
|
|||||||
void *stack_pointer, unsigned long user_pc,
|
void *stack_pointer, unsigned long user_pc,
|
||||||
unsigned long user_sp);
|
unsigned long user_sp);
|
||||||
|
|
||||||
|
void ihk_mc_init_user_tlsbase(ihk_mc_user_context_t *ctx,
|
||||||
|
unsigned long tls_base_addr);
|
||||||
|
|
||||||
enum ihk_mc_user_context_regtype {
|
enum ihk_mc_user_context_regtype {
|
||||||
IHK_UCR_STACK_POINTER = 1,
|
IHK_UCR_STACK_POINTER = 1,
|
||||||
IHK_UCR_PROGRAM_COUNTER = 2,
|
IHK_UCR_PROGRAM_COUNTER = 2,
|
||||||
|
|||||||
Reference in New Issue
Block a user