blob: 09e7ed7e3f3eecc00e5a40d4ed968f4a16ecec03 [file] [log] [blame]
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/stddef.h>
#include <linux/syscalls.h>
#include <linux/alt-syscall.h>
#include <asm/syscall.h>
#include <asm/syscalls.h>
int arch_dup_sys_call_table(struct alt_sys_call_table *entry)
{
if (!entry)
return -EINVAL;
/* Table already allocated. */
if (entry->table)
return -EINVAL;
#ifdef CONFIG_IA32_EMULATION
if (entry->compat_table)
return -EINVAL;
#endif
entry->size = NR_syscalls;
entry->table = kcalloc(entry->size, sizeof(sys_call_ptr_t),
GFP_KERNEL);
if (!entry->table)
goto failed;
memcpy(entry->table, sys_call_table,
entry->size * sizeof(sys_call_ptr_t));
#ifdef CONFIG_IA32_EMULATION
entry->compat_size = IA32_NR_syscalls;
entry->compat_table = kcalloc(entry->compat_size,
sizeof(sys_call_ptr_t), GFP_KERNEL);
if (!entry->compat_table)
goto failed;
memcpy(entry->compat_table, ia32_sys_call_table,
entry->compat_size * sizeof(sys_call_ptr_t));
#endif
return 0;
failed:
entry->size = 0;
kfree(entry->table);
entry->table = NULL;
#ifdef CONFIG_IA32_EMULATION
entry->compat_size = 0;
#endif
return -ENOMEM;
}
/* Operates on "current", which isn't racey, since it's _in_ a syscall. */
int arch_set_sys_call_table(struct alt_sys_call_table *entry)
{
if (!entry)
return -EINVAL;
current_thread_info()->nr_syscalls = entry->size;
current_thread_info()->sys_call_table = entry->table;
#ifdef CONFIG_IA32_EMULATION
current_thread_info()->ia32_nr_syscalls = entry->compat_size;
current_thread_info()->ia32_sys_call_table = entry->compat_table;
#endif
return 0;
}