Revert the rest of the COMPAT_MODE changes (back to hrev52003.)

This reverts commit 458e758f37.
This reverts commit ce5eb94a82.
This reverts commit aac8d4c317.
This reverts commit c70cba914a.
This reverts commit 2ffbe7aaca
This reverts commit c6e120e2d2.
This commit is contained in:
Augustin Cavalier
2018-06-15 00:20:56 -04:00
parent 513403d420
commit 4f7b9506fd
20 changed files with 122 additions and 1721 deletions
-6
View File
@@ -31,12 +31,6 @@ bool arch_on_signal_stack(Thread *thread);
status_t arch_setup_signal_frame(Thread *thread, struct sigaction *action, status_t arch_setup_signal_frame(Thread *thread, struct sigaction *action,
struct signal_frame_data *signalFrameData); struct signal_frame_data *signalFrameData);
int64 arch_restore_signal_frame(struct signal_frame_data* signalFrameData); int64 arch_restore_signal_frame(struct signal_frame_data* signalFrameData);
#ifdef _COMPAT_MODE
status_t arch_setup_compat_signal_frame(Thread *thread,
struct sigaction *action, struct compat_signal_frame_data *signalFrameData);
int64 arch_restore_compat_signal_frame(
struct compat_signal_frame_data* signalFrameData);
#endif
void arch_store_fork_frame(struct arch_fork_arg *arg); void arch_store_fork_frame(struct arch_fork_arg *arg);
void arch_restore_fork_frame(struct arch_fork_arg *arg); void arch_restore_fork_frame(struct arch_fork_arg *arg);
@@ -51,30 +51,6 @@ arch_thread_set_current_thread(Thread* t)
} }
#ifdef _COMPAT_MODE
static inline void
arch_thread_set_ds(unsigned short ds)
{
asm volatile("mov %0, %%ds" : : "r" (ds) : "memory");
}
static inline void
arch_thread_set_es(unsigned short es)
{
asm volatile("mov %0, %%es" : : "r" (es) : "memory");
}
// override empty macro
#undef arch_syscall_64_bit_return_value
void arch_syscall_64_bit_return_value(void);
#endif // _COMPAT_MODE
#else // __x86_64__ #else // __x86_64__
-277
View File
@@ -1,277 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_OS_H
#define _KERNEL_COMPAT_OS_H
typedef struct {
bigtime_t boot_time; /* time of boot (usecs since 1/1/1970) */
uint32 cpu_count; /* number of cpus */
uint64 max_pages; /* total # of accessible pages */
uint64 used_pages; /* # of accessible pages in use */
uint64 cached_pages;
uint64 block_cache_pages;
uint64 ignored_pages; /* # of ignored/inaccessible pages */
uint64 needed_memory;
uint64 free_memory;
uint64 max_swap_pages;
uint64 free_swap_pages;
uint32 page_faults; /* # of page faults */
uint32 max_sems;
uint32 used_sems;
uint32 max_ports;
uint32 used_ports;
uint32 max_threads;
uint32 used_threads;
uint32 max_teams;
uint32 used_teams;
char kernel_name[B_FILE_NAME_LENGTH];
char kernel_build_date[B_OS_NAME_LENGTH];
char kernel_build_time[B_OS_NAME_LENGTH];
int64 kernel_version;
uint32 abi; /* the system API */
} _PACKED compat_system_info;
static_assert(sizeof(compat_system_info) == 0x1c4,
"size of compat_system_info mismatch");
inline status_t
copy_ref_var_to_user(system_info &info, system_info* userInfo)
{
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_system_info compat_info;
compat_info.boot_time = info.boot_time;
compat_info.cpu_count = info.cpu_count;
compat_info.max_pages = info.max_pages;
compat_info.used_pages = info.used_pages;
compat_info.cached_pages = info.cached_pages;
compat_info.block_cache_pages = info.block_cache_pages;
compat_info.ignored_pages = info.ignored_pages;
compat_info.needed_memory = info.needed_memory;
compat_info.free_memory = info.free_memory;
compat_info.needed_memory = info.needed_memory;
compat_info.max_swap_pages = info.max_swap_pages;
compat_info.free_swap_pages = info.free_swap_pages;
compat_info.max_sems = info.max_sems;
compat_info.used_sems = info.used_sems;
compat_info.max_ports = info.max_ports;
compat_info.used_ports = info.used_ports;
compat_info.max_threads = info.max_threads;
compat_info.used_threads = info.used_threads;
compat_info.max_teams = info.max_teams;
compat_info.used_teams = info.used_teams;
strlcpy(compat_info.kernel_name, info.kernel_name, B_FILE_NAME_LENGTH);
strlcpy(compat_info.kernel_build_date, info.kernel_build_date,
B_OS_NAME_LENGTH);
strlcpy(compat_info.kernel_build_time, info.kernel_build_time,
B_OS_NAME_LENGTH);
compat_info.kernel_version = info.kernel_version;
compat_info.abi = info.abi;
if (user_memcpy(userInfo, &compat_info, sizeof(compat_info)) < B_OK)
return B_BAD_ADDRESS;
} else if (user_memcpy(userInfo, &info, sizeof(system_info)) < B_OK)
return B_BAD_ADDRESS;
return B_OK;
}
#define compat_size_t uint32
#define compat_ptr_t uint32
typedef struct compat_area_info {
area_id area;
char name[B_OS_NAME_LENGTH];
compat_size_t size;
uint32 lock;
uint32 protection;
team_id team;
uint32 ram_size;
uint32 copy_count;
uint32 in_count;
uint32 out_count;
compat_ptr_t address;
} _PACKED compat_area_info;
static_assert(sizeof(compat_area_info) == 0x48,
"size of compat_area_info mismatch");
inline status_t
copy_ref_var_to_user(area_info &info, area_info* userInfo)
{
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_area_info compatInfo;
compatInfo.area = info.area;
strlcpy(compatInfo.name, info.name, B_OS_NAME_LENGTH);
compatInfo.size = info.size;
compatInfo.lock = info.lock;
compatInfo.protection = info.protection;
compatInfo.team = info.team;
compatInfo.ram_size = info.ram_size;
compatInfo.copy_count = info.copy_count;
compatInfo.in_count = info.in_count;
compatInfo.out_count = info.out_count;
compatInfo.address = (compat_ptr_t)(addr_t)info.address;
if (user_memcpy(userInfo, &compatInfo, sizeof(compatInfo)) < B_OK)
return B_BAD_ADDRESS;
} else if (user_memcpy(userInfo, &info, sizeof(info)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
typedef struct {
thread_id thread;
team_id team;
char name[B_OS_NAME_LENGTH];
thread_state state;
int32 priority;
sem_id sem;
bigtime_t user_time;
bigtime_t kernel_time;
uint32 stack_base;
uint32 stack_end;
} _PACKED compat_thread_info;
static_assert(sizeof(compat_thread_info) == 76,
"size of compat_thread_info mismatch");
inline status_t
copy_ref_var_to_user(void* &addr, void** userAddr)
{
if (!IS_USER_ADDRESS(userAddr))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_ptr_t compatAddr = (uint32)(addr_t)addr;
if (user_memcpy(userAddr, &compatAddr, sizeof(compatAddr)) < B_OK)
return B_BAD_ADDRESS;
} else if (user_memcpy(userAddr, &addr, sizeof(addr)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_from_user(void** userAddr, void* &addr)
{
if (!IS_USER_ADDRESS(userAddr))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_ptr_t compatAddr;
if (user_memcpy(&compatAddr, userAddr, sizeof(compatAddr)) < B_OK)
return B_BAD_ADDRESS;
addr = (void*)(addr_t)compatAddr;
} else if (user_memcpy(&addr, userAddr, sizeof(addr)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_to_user(addr_t &addr, addr_t* userAddr)
{
if (!IS_USER_ADDRESS(userAddr))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
uint32 compatAddr = (uint32)addr;
if (user_memcpy(userAddr, &compatAddr, sizeof(compatAddr)) < B_OK)
return B_BAD_ADDRESS;
} else if (user_memcpy(userAddr, &addr, sizeof(addr)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_from_user(addr_t* userAddr, addr_t &addr)
{
if (!IS_USER_ADDRESS(userAddr))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
uint32 compatAddr;
if (user_memcpy(&compatAddr, userAddr, sizeof(compatAddr)) < B_OK)
return B_BAD_ADDRESS;
addr = (addr_t)compatAddr;
} else if (user_memcpy(&addr, userAddr, sizeof(addr)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_to_user(ssize_t &size, ssize_t* userSize)
{
if (!IS_USER_ADDRESS(userSize))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
int32 compatSize = (int32)size;
if (user_memcpy(userSize, &compatSize, sizeof(compatSize)) < B_OK)
return B_BAD_ADDRESS;
} else if (user_memcpy(userSize, &size, sizeof(size)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_from_user(ssize_t* userSize, ssize_t &size)
{
if (!IS_USER_ADDRESS(userSize))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
int32 compatSize;
if (user_memcpy(&compatSize, userSize, sizeof(compatSize)) < B_OK)
return B_BAD_ADDRESS;
size = (ssize_t)compatSize;
} else if (user_memcpy(&size, userSize, sizeof(size)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_OS_H
@@ -1,113 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_ARCH_SIGNAL_H
#define _KERNEL_COMPAT_ARCH_SIGNAL_H
typedef struct packed_fp_stack {
unsigned char st0[10];
unsigned char st1[10];
unsigned char st2[10];
unsigned char st3[10];
unsigned char st4[10];
unsigned char st5[10];
unsigned char st6[10];
unsigned char st7[10];
} packed_fp_stack;
typedef struct packed_mmx_regs {
unsigned char mm0[10];
unsigned char mm1[10];
unsigned char mm2[10];
unsigned char mm3[10];
unsigned char mm4[10];
unsigned char mm5[10];
unsigned char mm6[10];
unsigned char mm7[10];
} packed_mmx_regs;
typedef struct xmmx_regs {
unsigned char xmm0[16];
unsigned char xmm1[16];
unsigned char xmm2[16];
unsigned char xmm3[16];
unsigned char xmm4[16];
unsigned char xmm5[16];
unsigned char xmm6[16];
unsigned char xmm7[16];
} xmmx_regs;
typedef struct compat_stack_t {
uint32 ss_sp;
uint32 ss_size;
int ss_flags;
} compat_stack_t;
typedef struct compat_old_extended_regs {
unsigned short fp_control;
unsigned short _reserved1;
unsigned short fp_status;
unsigned short _reserved2;
unsigned short fp_tag;
unsigned short _reserved3;
uint32 fp_eip;
unsigned short fp_cs;
unsigned short fp_opcode;
uint32 fp_datap;
unsigned short fp_ds;
unsigned short _reserved4;
union {
packed_fp_stack fp;
packed_mmx_regs mmx;
} fp_mmx;
} compat_old_extended_regs;
typedef struct compat_new_extended_regs {
unsigned short fp_control;
unsigned short fp_status;
unsigned short fp_tag;
unsigned short fp_opcode;
uint32 fp_eip;
unsigned short fp_cs;
unsigned short res_14_15;
uint32 fp_datap;
unsigned short fp_ds;
unsigned short _reserved_22_23;
uint32 mxcsr;
uint32 _reserved_28_31;
union {
fp_stack fp;
mmx_regs mmx;
} fp_mmx;
xmmx_regs xmmx;
unsigned char _reserved_288_511[224];
} compat_new_extended_regs;
typedef struct compat_extended_regs {
union {
compat_old_extended_regs old_format;
compat_new_extended_regs new_format;
} state;
uint32 format;
} compat_extended_regs;
struct compat_vregs {
uint32 eip;
uint32 eflags;
uint32 eax;
uint32 ecx;
uint32 edx;
uint32 esp;
uint32 ebp;
uint32 _reserved_1;
compat_extended_regs xregs;
uint32 edi;
uint32 esi;
uint32 ebx;
};
#endif // _KERNEL_COMPAT_ARCH_SIGNAL_H
@@ -1,74 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_FCNTL_H
#define _KERNEL_COMPAT_FCNTL_H
#include <fcntl.h>
struct compat_flock {
short l_type;
short l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
} _PACKED;
static_assert(sizeof(struct compat_flock) == 24,
"size of compat_flock mismatch");
inline status_t
copy_ref_var_from_user(struct flock* userFlock, struct flock &flock)
{
if (!IS_USER_ADDRESS(userFlock))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_flock compat_flock;
if (user_memcpy(&compat_flock, userFlock, sizeof(compat_flock)) < B_OK)
return B_BAD_ADDRESS;
flock.l_type = compat_flock.l_type;
flock.l_whence = compat_flock.l_whence;
flock.l_start = compat_flock.l_start;
flock.l_len = compat_flock.l_len;
flock.l_pid = compat_flock.l_pid;
} else {
if (user_memcpy(&flock, userFlock, sizeof(struct flock)) < B_OK)
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_to_user(struct flock &flock, struct flock* userFlock)
{
if (!IS_USER_ADDRESS(userFlock))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_flock compat_flock;
compat_flock.l_type = flock.l_type;
compat_flock.l_whence = flock.l_whence;
compat_flock.l_start = flock.l_start;
compat_flock.l_len = flock.l_len;
compat_flock.l_pid = flock.l_pid;
if (user_memcpy(userFlock, &compat_flock, sizeof(compat_flock)) < B_OK)
return B_BAD_ADDRESS;
} else {
if (user_memcpy(userFlock, &flock, sizeof(flock)) < B_OK)
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_FCNTL_H
@@ -1,44 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_FS_ATTR_H
#define _KERNEL_COMPAT_FS_ATTR_H
#include <fs_attr.h>
struct compat_attr_info {
uint32 type;
off_t size;
} _PACKED;
static_assert(sizeof(compat_attr_info) == 12,
"size of compat_attr_info mismatch");
inline status_t
copy_ref_var_to_user(attr_info &info, attr_info* userInfo)
{
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_attr_info compat_info;
compat_info.type = info.type;
compat_info.size = info.size;
if (user_memcpy(userInfo, &compat_info, sizeof(compat_info)) < B_OK)
return B_BAD_ADDRESS;
} else {
if (user_memcpy(userInfo, &info, sizeof(info)) < B_OK)
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_FS_ATTR_H
@@ -1,94 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_FS_INFO_H
#define _KERNEL_COMPAT_FS_INFO_H
#include <fs_info.h>
typedef struct compat_fs_info {
dev_t dev; /* volume dev_t */
ino_t root; /* root ino_t */
uint32 flags; /* flags (see above) */
off_t block_size; /* fundamental block size */
off_t io_size; /* optimal i/o size */
off_t total_blocks; /* total number of blocks */
off_t free_blocks; /* number of free blocks */
off_t total_nodes; /* total number of nodes */
off_t free_nodes; /* number of free nodes */
char device_name[128]; /* device holding fs */
char volume_name[B_FILE_NAME_LENGTH]; /* volume name */
char fsh_name[B_OS_NAME_LENGTH]; /* name of fs handler */
} _PACKED compat_fs_info;
static_assert(sizeof(compat_fs_info) == 480,
"size of compat_fs_info mismatch");
inline status_t
copy_ref_var_to_user(fs_info &info, fs_info* userInfo)
{
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_fs_info compat_info;
compat_info.dev = info.dev;
compat_info.root = info.root;
compat_info.flags = info.flags;
compat_info.block_size = info.block_size;
compat_info.io_size = info.io_size;
compat_info.total_blocks = info.total_blocks;
compat_info.free_blocks = info.free_blocks;
compat_info.total_nodes = info.total_nodes;
compat_info.free_nodes = info.free_nodes;
strlcpy(compat_info.device_name, info.device_name, 128);
strlcpy(compat_info.volume_name, info.volume_name, B_FILE_NAME_LENGTH);
strlcpy(compat_info.fsh_name, info.fsh_name, B_OS_NAME_LENGTH);
if (user_memcpy(userInfo, &compat_info, sizeof(compat_info)) < B_OK)
return B_BAD_ADDRESS;
} else {
if (user_memcpy(userInfo, &info, sizeof(info)) < B_OK)
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_from_user(fs_info* userInfo, fs_info &info)
{
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_fs_info compat_info;
if (user_memcpy(&compat_info, userInfo, sizeof(compat_info)) < B_OK)
return B_BAD_ADDRESS;
info.dev = compat_info.dev;
info.root = compat_info.root;
info.flags = compat_info.flags;
info.block_size = compat_info.block_size;
info.io_size = compat_info.io_size;
info.total_blocks = compat_info.total_blocks;
info.free_blocks = compat_info.free_blocks;
info.total_nodes = compat_info.total_nodes;
info.free_nodes = compat_info.free_nodes;
strlcpy(info.device_name, compat_info.device_name, 128);
strlcpy(info.volume_name, compat_info.volume_name, B_FILE_NAME_LENGTH);
strlcpy(info.fsh_name, compat_info.fsh_name, B_OS_NAME_LENGTH);
} else if (user_memcpy(&info, userInfo, sizeof(info)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_FS_INFO_H
@@ -1,129 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_IMAGE_H
#define _KERNEL_COMPAT_IMAGE_H
#include <image.h>
#define compat_uintptr_t uint32
typedef struct {
image_id id;
image_type type;
int32 sequence;
int32 init_order;
compat_uintptr_t init_routine;
compat_uintptr_t term_routine;
dev_t device;
ino_t node;
char name[MAXPATHLEN];
compat_uintptr_t text;
compat_uintptr_t data;
int32 text_size;
int32 data_size;
/* Haiku R1 extensions */
int32 api_version; /* the Haiku API version used by the image */
int32 abi; /* the Haiku ABI used by the image */
} _PACKED compat_image_info;
typedef struct {
compat_image_info basic_info;
int32 text_delta;
compat_uintptr_t symbol_table;
compat_uintptr_t symbol_hash;
compat_uintptr_t string_table;
} _PACKED compat_extended_image_info;
static_assert(sizeof(compat_image_info) == 1084,
"size of compat_image_info mismatch");
static_assert(sizeof(compat_extended_image_info) == 1100,
"size of compat_extended_image_info mismatch");
inline status_t
copy_ref_var_to_user(image_info &info, image_info* userInfo, size_t size)
{
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
if (size > sizeof(compat_image_info))
return B_BAD_VALUE;
compat_image_info compat_info;
compat_info.id = info.id;
compat_info.type = info.type;
compat_info.sequence = info.sequence;
compat_info.init_order = info.init_order;
compat_info.init_routine = (uint32)(addr_t)info.init_routine;
compat_info.term_routine = (uint32)(addr_t)info.term_routine;
compat_info.device = info.device;
compat_info.node = info.node;
strlcpy(compat_info.name, info.name, MAXPATHLEN);
compat_info.text = (uint32)(addr_t)info.text;
compat_info.data = (uint32)(addr_t)info.data;
compat_info.text_size = info.text_size;
compat_info.data_size = info.data_size;
if (user_memcpy(userInfo, &compat_info, size) < B_OK)
return B_BAD_ADDRESS;
} else {
if (size > sizeof(image_info))
return B_BAD_VALUE;
if (user_memcpy(userInfo, &info, size) < B_OK)
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_from_user(extended_image_info* userInfo,
extended_image_info &info, size_t size)
{
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_extended_image_info compat_info;
if (size != sizeof(compat_info))
return B_BAD_VALUE;
if (user_memcpy(&compat_info, userInfo, size) < B_OK)
return B_BAD_ADDRESS;
info.basic_info.id = compat_info.basic_info.id;
info.basic_info.type = compat_info.basic_info.type;
info.basic_info.sequence = compat_info.basic_info.sequence;
info.basic_info.init_order = compat_info.basic_info.init_order;
info.basic_info.init_routine = (void(*)())(addr_t)compat_info.basic_info.init_routine;
info.basic_info.term_routine = (void(*)())(addr_t)compat_info.basic_info.term_routine;
info.basic_info.device = compat_info.basic_info.device;
info.basic_info.node = compat_info.basic_info.node;
strlcpy(info.basic_info.name, compat_info.basic_info.name, MAXPATHLEN);
info.basic_info.text = (void*)(addr_t)compat_info.basic_info.text;
info.basic_info.data = (void*)(addr_t)compat_info.basic_info.data;
info.basic_info.text_size = compat_info.basic_info.text_size;
info.basic_info.data_size = compat_info.basic_info.data_size;
info.text_delta = compat_info.text_delta;
info.symbol_table = (void*)(addr_t)compat_info.symbol_table;
info.symbol_hash = (void*)(addr_t)compat_info.symbol_hash;
info.string_table = (void*)(addr_t)compat_info.string_table;
} else {
if (size != sizeof(info))
return B_BAD_VALUE;
if (user_memcpy(&info, userInfo, size) < B_OK)
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_IMAGE_H
@@ -1,165 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_KSIGNAL_H
#define _KERNEL_COMPAT_KSIGNAL_H
#include <compat/signal_compat.h>
#include <compat/arch/x86/signal_compat.h>
typedef struct compat_vregs compat_mcontext_t;
typedef struct __compat_ucontext_t {
uint32 uc_link;
sigset_t uc_sigmask;
compat_stack_t uc_stack;
compat_mcontext_t uc_mcontext;
} _PACKED compat_ucontext_t;
union compat_sigval {
int sival_int;
uint32 sival_ptr;
};
typedef struct __compat_siginfo_t {
int si_signo; /* signal number */
int si_code; /* signal code */
int si_errno; /* if non zero, an error number associated with
this signal */
pid_t si_pid; /* sending process ID */
uid_t si_uid; /* real user ID of sending process */
uint32 si_addr; /* address of faulting instruction */
int si_status; /* exit value or signal */
uint32 si_band; /* band event for SIGPOLL */
union compat_sigval si_value; /* signal value */
} compat_siginfo_t;
struct compat_signal_frame_data {
compat_siginfo_t info;
compat_ucontext_t context;
uint32 user_data;
uint32 handler;
bool siginfo_handler;
char _pad[3];
int32 thread_flags;
uint64 syscall_restart_return_value;
uint8 syscall_restart_parameters[SYSCALL_RESTART_PARAMETER_SIZE];
uint32 commpage_address;
} _PACKED;
static_assert(sizeof(compat_stack_t) == 12,
"size of compat_stack_t mismatch");
static_assert(sizeof(compat_mcontext_t) == 560,
"size of compat_mcontext_t mismatch");
static_assert(sizeof(compat_ucontext_t) == 584,
"size of compat_ucontext_t mismatch");
static_assert(sizeof(compat_siginfo_t) == 36,
"size of compat_siginfo_t mismatch");
static_assert(sizeof(struct compat_signal_frame_data) == 680,
"size of compat_signal_frame_data mismatch");
inline status_t
copy_ref_var_from_user(union sigval* userSigval, union sigval &sigval)
{
if (!IS_USER_ADDRESS(userSigval))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_sigval compat_sigval;
if (user_memcpy(&compat_sigval, userSigval, sizeof(compat_sigval))
< B_OK) {
return B_BAD_ADDRESS;
}
sigval.sival_ptr = (void*)(addr_t)compat_sigval.sival_ptr;
} else if (user_memcpy(&sigval, userSigval, sizeof(union sigval)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_to_user(siginfo_t &info, siginfo_t* userInfo)
{
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_siginfo_t compat_info;
compat_info.si_signo = info.si_signo;
compat_info.si_code = info.si_code;
compat_info.si_errno = info.si_errno;
compat_info.si_pid = info.si_pid;
compat_info.si_uid = info.si_uid;
compat_info.si_addr = (addr_t)info.si_addr;
compat_info.si_status = info.si_status;
compat_info.si_band = info.si_band;
compat_info.si_value.sival_ptr = (addr_t)info.si_value.sival_ptr;
if (user_memcpy(userInfo, &compat_info, sizeof(compat_info))
< B_OK) {
return B_BAD_ADDRESS;
}
} else if (user_memcpy(userInfo, &info, sizeof(info)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_from_user(stack_t* userStack, stack_t &stack)
{
if (!IS_USER_ADDRESS(userStack))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_stack_t compatStack;
if (user_memcpy(&compatStack, userStack, sizeof(compatStack))
< B_OK) {
return B_BAD_ADDRESS;
}
stack.ss_sp = (void*)(addr_t)compatStack.ss_sp;
stack.ss_size = compatStack.ss_size;
stack.ss_flags = compatStack.ss_flags;
} else if (user_memcpy(&stack, userStack, sizeof(stack_t)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_to_user(stack_t &stack, stack_t* userStack)
{
if (!IS_USER_ADDRESS(userStack))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
compat_stack_t compatStack;
compatStack.ss_sp = (addr_t)stack.ss_sp;
compatStack.ss_size = stack.ss_size;
compatStack.ss_flags = stack.ss_flags;
if (user_memcpy(userStack, &compatStack, sizeof(compatStack))
< B_OK) {
return B_BAD_ADDRESS;
}
} else if (user_memcpy(userStack, &stack, sizeof(stack)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_KSIGNAL_H
@@ -1,70 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_SIGNAL_H
#define _KERNEL_COMPAT_SIGNAL_H
struct compat_sigaction {
union {
uint32 sa_handler;
uint32 sa_sigaction;
};
sigset_t sa_mask;
int sa_flags;
uint32 sa_userdata; /* will be passed to the signal
handler, BeOS extension */
} _PACKED;
inline status_t
copy_ref_var_from_user(struct sigaction* userAction, struct sigaction &action)
{
if (!IS_USER_ADDRESS(userAction))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
struct compat_sigaction compat_action;
if (user_memcpy(&compat_action, userAction, sizeof(compat_sigaction))
< B_OK) {
return B_BAD_ADDRESS;
}
action.sa_handler = (__sighandler_t)(addr_t)compat_action.sa_handler;
action.sa_mask = compat_action.sa_mask;
action.sa_flags = compat_action.sa_flags;
action.sa_userdata = (void*)(addr_t)compat_action.sa_userdata;
} else if (user_memcpy(&action, userAction, sizeof(action)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_to_user(struct sigaction &action, struct sigaction* userAction)
{
if (!IS_USER_ADDRESS(userAction))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
struct compat_sigaction compat_action;
compat_action.sa_handler = (addr_t)action.sa_handler;
compat_action.sa_mask = action.sa_mask;
compat_action.sa_flags = action.sa_flags;
compat_action.sa_userdata = (addr_t)action.sa_userdata;
if (user_memcpy(userAction, &compat_action, sizeof(compat_action))
< B_OK) {
return B_BAD_ADDRESS;
}
} else if (user_memcpy(userAction, &action, sizeof(action)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_SIGNAL_H
-117
View File
@@ -1,117 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_STAT_H
#define _KERNEL_COMPAT_STAT_H
#include <sys/stat.h>
#include <time_compat.h>
struct compat_stat {
dev_t st_dev; /* device ID that this file resides on */
ino_t st_ino; /* this file's serial inode ID */
mode_t st_mode; /* file mode (rwx for user, group, etc) */
nlink_t st_nlink; /* number of hard links to this file */
uid_t st_uid; /* user ID of the owner of this file */
gid_t st_gid; /* group ID of the owner of this file */
off_t st_size; /* size in bytes of this file */
dev_t st_rdev; /* device type (not used) */
blksize_t st_blksize; /* preferred block size for I/O */
struct compat_timespec st_atim; /* last access time */
struct compat_timespec st_mtim; /* last modification time */
struct compat_timespec st_ctim; /* last change time, not creation time */
struct compat_timespec st_crtim; /* creation time */
__haiku_uint32 st_type; /* attribute/index type */
blkcnt_t st_blocks; /* number of blocks allocated for object */
} _PACKED;
static_assert(sizeof(struct compat_stat) == 88,
"size of struct compat_stat mismatch");
inline status_t
copy_ref_var_to_user(struct stat &stat, struct stat* userStat, size_t size)
{
if (!IS_USER_ADDRESS(userStat))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
if (size > sizeof(compat_stat))
return B_BAD_VALUE;
struct compat_stat compat_stat;
compat_stat.st_dev = stat.st_dev;
compat_stat.st_ino = stat.st_ino;
compat_stat.st_mode = stat.st_mode;
compat_stat.st_nlink = stat.st_nlink;
compat_stat.st_uid = stat.st_gid;
compat_stat.st_size = stat.st_size;
compat_stat.st_rdev = stat.st_rdev;
compat_stat.st_blksize = stat.st_blksize;
compat_stat.st_atim.tv_sec = stat.st_atim.tv_sec;
compat_stat.st_atim.tv_nsec = stat.st_atim.tv_nsec;
compat_stat.st_mtim.tv_sec = stat.st_mtim.tv_sec;
compat_stat.st_mtim.tv_nsec = stat.st_mtim.tv_nsec;
compat_stat.st_ctim.tv_sec = stat.st_ctim.tv_sec;
compat_stat.st_ctim.tv_nsec = stat.st_ctim.tv_nsec;
compat_stat.st_crtim.tv_sec = stat.st_crtim.tv_sec;
compat_stat.st_crtim.tv_nsec = stat.st_crtim.tv_nsec;
compat_stat.st_type = stat.st_type;
compat_stat.st_blocks = stat.st_blocks;
if (user_memcpy(userStat, &compat_stat, size) < B_OK)
return B_BAD_ADDRESS;
} else {
if (size > sizeof(struct stat))
return B_BAD_VALUE;
if (user_memcpy(userStat, &stat, size) < B_OK)
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_to_user(struct stat &stat, struct stat* userStat)
{
if (!IS_USER_ADDRESS(userStat))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
struct compat_stat compat_stat;
compat_stat.st_dev = stat.st_dev;
compat_stat.st_ino = stat.st_ino;
compat_stat.st_mode = stat.st_mode;
compat_stat.st_nlink = stat.st_nlink;
compat_stat.st_uid = stat.st_gid;
compat_stat.st_size = stat.st_size;
compat_stat.st_rdev = stat.st_rdev;
compat_stat.st_blksize = stat.st_blksize;
compat_stat.st_atim.tv_sec = stat.st_atim.tv_sec;
compat_stat.st_atim.tv_nsec = stat.st_atim.tv_nsec;
compat_stat.st_mtim.tv_sec = stat.st_mtim.tv_sec;
compat_stat.st_mtim.tv_nsec = stat.st_mtim.tv_nsec;
compat_stat.st_ctim.tv_sec = stat.st_ctim.tv_sec;
compat_stat.st_ctim.tv_nsec = stat.st_ctim.tv_nsec;
compat_stat.st_crtim.tv_sec = stat.st_crtim.tv_sec;
compat_stat.st_crtim.tv_nsec = stat.st_crtim.tv_nsec;
compat_stat.st_type = stat.st_type;
compat_stat.st_blocks = stat.st_blocks;
if (user_memcpy(userStat, &compat_stat, sizeof(compat_stat)) < B_OK)
return B_BAD_ADDRESS;
} else {
if (user_memcpy(userStat, &stat, sizeof(stat)) < B_OK)
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_STAT_H
@@ -1,19 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_TIME_H
#define _KERNEL_COMPAT_TIME_H
#include <time.h>
struct compat_timespec {
uint32 tv_sec; /* seconds */
uint32 tv_nsec; /* and nanoseconds */
};
#endif // _KERNEL_COMPAT_TIME_H
@@ -1,79 +0,0 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_VFS_DEFS_H
#define _KERNEL_COMPAT_VFS_DEFS_H
#include <vfs_defs.h>
struct compat_fd_info {
int number;
int32 open_mode;
dev_t device;
ino_t node;
} _PACKED;
static_assert(sizeof(compat_fd_info) == 20,
"size of compat_fd_info mismatch");
inline status_t
copy_ref_var_to_user(attr_info &info, attr_info* userInfo, size_t size)
{
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
if (size != sizeof(compat_fd_info))
return B_BAD_VALUE;
compat_fd_info compat_info;
compat_info.number = info.number;
compat_info.open_mode = info.open_mode;
compat_info.device = info.device;
compat_info.node = info.node;
if (user_memcpy(userInfo, &compat_info, size) < B_OK)
return B_BAD_ADDRESS;
} else {
if (size != sizeof(fd_info))
return B_BAD_VALUE;
if (user_memcpy(userInfo, &info, size) < B_OK)
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_from_user(fd_info* userInfo, fd_info &info, size_t size)
{
if (!IS_USER_ADDRESS(userInfo))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
if (size != sizeof(compat_fd_info))
return B_BAD_VALUE;
compat_fd_info compat_info;
if (user_memcpy(&compat_info, userInfo, size) < B_OK)
return B_BAD_ADDRESS;
info.number = compat_info.number;
info.open_mode = compat_info.open_mode;
info.device = compat_info.device;
info.node = compat_info.node;
} else {
if (size != sizeof(fd_info))
return B_BAD_VALUE;
if (user_memcpy(&info, userInfo, size) < B_OK)
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_VFS_DEFS_H
@@ -23,18 +23,6 @@ copy_ref_var_from_user(T *user, T &kernel)
return user_memcpy(&kernel, user, sizeof(T)); return user_memcpy(&kernel, user, sizeof(T));
} }
template<typename T>
inline
status_t
copy_ref_var_from_user(T *user, T &kernel, size_t size)
{
if (size != sizeof(T))
return B_BAD_VALUE;
return copy_ref_var_from_user(user, kernel);
}
// copy_ref_var_to_user // copy_ref_var_to_user
template<typename T> template<typename T>
inline inline
@@ -47,17 +35,4 @@ copy_ref_var_to_user(T &kernel, T *user)
} }
template<typename T>
inline
status_t
copy_ref_var_to_user(T &kernel, T *user, size_t size)
{
if (size > sizeof(T))
return B_BAD_VALUE;
if (!IS_USER_ADDRESS(user))
return B_BAD_ADDRESS;
return user_memcpy(user, &kernel, size);
}
#endif // _SYSCALL_ARGS_H #endif // _SYSCALL_ARGS_H
+13 -201
View File
@@ -18,9 +18,6 @@
#include <debug.h> #include <debug.h>
#include <kernel.h> #include <kernel.h>
#include <ksignal.h> #include <ksignal.h>
#ifdef _COMPAT_MODE
# include <compat/ksignal_compat.h>
#endif
#include <int.h> #include <int.h>
#include <team.h> #include <team.h>
#include <thread.h> #include <thread.h>
@@ -91,33 +88,11 @@ x86_restart_syscall(iframe* frame)
} }
#ifdef _COMPAT_MODE
static inline void
set_fs_register(uint32 segment)
{
asm("movl %0,%%fs" :: "r" (segment));
}
#endif // _COMPAT_MODE
void void
x86_set_tls_context(Thread* thread) x86_set_tls_context(Thread* thread)
{ {
#ifdef _COMPAT_MODE // Set FS segment base address to the TLS segment.
if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0) { x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage);
unsigned index = x86_64_set_user_tls_segment_base(
smp_get_current_cpu(), thread->user_local_storage);
set_fs_register((index << 3) | DPL_USER);
} else
#endif
{
// Set FS segment base address to the TLS segment.
x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage);
}
} }
@@ -134,24 +109,6 @@ arch_randomize_stack_pointer(addr_t value)
} }
#ifdef _COMPAT_MODE
static addr_t
arch_compat_randomize_stack_pointer(addr_t value)
{
STATIC_ASSERT(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1);
value -= random_value() & (B_PAGE_SIZE - 1);
return (value & ~addr_t(0xf)) - 4;
// This means, result % 16 == 12, which is what esp should adhere to
// when a function is entered for the stack to be considered aligned to
// 16 byte.
}
#endif // _COMPAT_MODE
static uint8* static uint8*
get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action, get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action,
size_t spaceNeeded) size_t spaceNeeded)
@@ -261,55 +218,27 @@ arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1,
TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, " TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, "
"stackTop %#lx\n", entry, args1, args2, stackTop); "stackTop %#lx\n", entry, args1, args2, stackTop);
stackTop = arch_randomize_stack_pointer(stackTop - sizeof(codeAddr));
// Copy the address of the stub that calls exit_thread() when the thread // Copy the address of the stub that calls exit_thread() when the thread
// entry function returns to the top of the stack to act as the return // entry function returns to the top of the stack to act as the return
// address. The stub is inside commpage. // address. The stub is inside commpage.
addr_t commPageAddress = (addr_t)thread->team->commpage_address; addr_t commPageAddress = (addr_t)thread->team->commpage_address;
set_ac();
#ifdef _COMPAT_MODE codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT]
if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0) { + commPageAddress;
uint32 args[3]; clear_ac();
stackTop = arch_compat_randomize_stack_pointer(stackTop - sizeof(args)); if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr))
set_ac();
args[0] = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT]
+ commPageAddress;
clear_ac();
args[1] = (uint32)(addr_t)args1;
args[2] = (uint32)(addr_t)args2;
if (user_memcpy((void *)stackTop, args, sizeof(args)) < B_OK)
return B_BAD_ADDRESS;
} else
#endif
{
stackTop = arch_randomize_stack_pointer(stackTop - sizeof(codeAddr));
set_ac();
codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT]
+ commPageAddress;
clear_ac();
if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr))
!= B_OK) != B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
}
// Prepare the user iframe. // Prepare the user iframe.
iframe frame = {}; iframe frame = {};
frame.type = IFRAME_TYPE_SYSCALL; frame.type = IFRAME_TYPE_SYSCALL;
frame.si = (uint64)args2;
frame.di = (uint64)args1;
frame.ip = entry; frame.ip = entry;
#ifdef _COMPAT_MODE frame.cs = USER_CODE_SELECTOR;
if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0) {
frame.cs = USER32_CODE_SELECTOR;
arch_thread_set_ds(USER_DATA_SELECTOR);
arch_thread_set_es(USER_DATA_SELECTOR);
} else
#endif
{
frame.si = (uint64)args2;
frame.di = (uint64)args1;
frame.cs = USER_CODE_SELECTOR;
}
frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT
| (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT);
frame.sp = stackTop; frame.sp = stackTop;
@@ -465,120 +394,3 @@ arch_restore_signal_frame(struct signal_frame_data* signalFrameData)
// restored. // restored.
return frame->ax; return frame->ax;
} }
#ifdef _COMPAT_MODE
status_t
arch_setup_compat_signal_frame(Thread* thread, struct sigaction* action,
struct compat_signal_frame_data* signalFrameData)
{
iframe* frame = x86_get_current_iframe();
if (!IFRAME_IS_USER(frame)) {
panic("arch_setup_compat_signal_frame(): No user iframe!");
return B_BAD_VALUE;
}
// Store the register state.
signalFrameData->context.uc_mcontext.eax = frame->ax;
signalFrameData->context.uc_mcontext.ebx = frame->bx;
signalFrameData->context.uc_mcontext.ecx = frame->cx;
signalFrameData->context.uc_mcontext.edx = frame->dx;
signalFrameData->context.uc_mcontext.edi = frame->di;
signalFrameData->context.uc_mcontext.esi = frame->si;
signalFrameData->context.uc_mcontext.ebp = frame->bp;
signalFrameData->context.uc_mcontext.esp = frame->user_sp;
signalFrameData->context.uc_mcontext.eip = frame->ip;
signalFrameData->context.uc_mcontext.eflags = frame->flags;
x86_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs));
// Fill in signalFrameData->context.uc_stack.
stack_t stack;
signal_get_user_stack(frame->user_sp, &stack);
signalFrameData->context.uc_stack.ss_sp = (addr_t)stack.ss_sp;
signalFrameData->context.uc_stack.ss_size = stack.ss_size;
signalFrameData->context.uc_stack.ss_flags = stack.ss_flags;
// Store syscall_restart_return_value.
signalFrameData->syscall_restart_return_value = frame->orig_rax;
// Get the stack to use and copy the frame data to it.
uint32 stackFrame[2];
uint8* userStack = get_signal_stack(thread, frame, action,
sizeof(*signalFrameData) + sizeof(stackFrame));
compat_signal_frame_data* userSignalFrameData
= (compat_signal_frame_data*)(userStack + sizeof(stackFrame));
if (user_memcpy(userSignalFrameData, signalFrameData,
sizeof(*signalFrameData)) != B_OK) {
return B_BAD_ADDRESS;
}
// prepare the user stack frame for a function call to the signal handler
// wrapper function
stackFrame[0] = frame->ip;
stackFrame[1] = (addr_t)userSignalFrameData;
// parameter: pointer to signal frame data
if (user_memcpy(userStack, stackFrame, sizeof(stackFrame)) != B_OK)
return B_BAD_ADDRESS;
// Update Thread::user_signal_context, now that everything seems to have
// gone fine.
thread->user_signal_context = (ucontext_t*)&userSignalFrameData->context;
// Set up the iframe to execute the signal handler wrapper on our prepared
// stack. First argument points to the frame data.
addr_t* commPageAddress = (addr_t*)thread->team->commpage_address;
frame->user_sp = (addr_t)userStack;
set_ac();
// from x86/arch_commpage_defs.h
#define COMPAT_COMMPAGE_ENTRY_X86_SIGNAL_HANDLER \
(COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 3)
frame->ip = commPageAddress[COMPAT_COMMPAGE_ENTRY_X86_SIGNAL_HANDLER]
+ (addr_t)commPageAddress;
clear_ac();
return B_OK;
}
int64
arch_restore_compat_signal_frame(struct compat_signal_frame_data* signalFrameData)
{
iframe* frame = x86_get_current_iframe();
frame->orig_rax = signalFrameData->syscall_restart_return_value;
frame->ax = signalFrameData->context.uc_mcontext.eax;
frame->bx = signalFrameData->context.uc_mcontext.ebx;
frame->cx = signalFrameData->context.uc_mcontext.ecx;
frame->dx = signalFrameData->context.uc_mcontext.edx;
frame->di = signalFrameData->context.uc_mcontext.edi;
frame->si = signalFrameData->context.uc_mcontext.esi;
frame->bp = signalFrameData->context.uc_mcontext.ebp;
frame->user_sp = signalFrameData->context.uc_mcontext.esp;
frame->ip = signalFrameData->context.uc_mcontext.eip;
frame->flags = (frame->flags & ~(uint64)X86_EFLAGS_USER_FLAGS)
| (signalFrameData->context.uc_mcontext.eflags & X86_EFLAGS_USER_FLAGS);
x86_frstor((void*)(&signalFrameData->context.uc_mcontext.xregs));
// The syscall return code overwrites frame->ax with the return value of
// the syscall, need to return it here to ensure the correct value is
// restored.
return frame->ax;
}
void
arch_syscall_64_bit_return_value(void)
{
Thread* thread = thread_get_current_thread();
if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0)
atomic_or(&thread->flags, THREAD_FLAGS_64_BIT_SYSCALL_RETURN);
}
#endif // _COMPAT_MODE
+25 -20
View File
@@ -49,19 +49,11 @@
#include <util/atomic.h> #include <util/atomic.h>
#include <util/AutoLock.h> #include <util/AutoLock.h>
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
#include <util/syscall_args.h>
#include <vfs.h> #include <vfs.h>
#include <vm/vm.h> #include <vm/vm.h>
#include <vm/VMCache.h> #include <vm/VMCache.h>
#include <wait_for_objects.h> #include <wait_for_objects.h>
#ifdef _COMPAT_MODE
# include <fcntl_compat.h>
# include <stat_compat.h>
# include <fs_attr_compat.h>
# include <fs_info_compat.h>
#endif
#include "EntryCache.h" #include "EntryCache.h"
#include "fifo.h" #include "fifo.h"
#include "IORequest.h" #include "IORequest.h"
@@ -6124,8 +6116,10 @@ common_fcntl(int fd, int op, size_t argument, bool kernel)
if (op == F_SETLK || op == F_SETLKW || op == F_GETLK) { if (op == F_SETLK || op == F_SETLKW || op == F_GETLK) {
if (descriptor->type != FDTYPE_FILE) if (descriptor->type != FDTYPE_FILE)
status = B_BAD_VALUE; status = B_BAD_VALUE;
else else if (user_memcpy(&flock, (struct flock*)argument,
status = copy_ref_var_from_user((struct flock*)argument, flock); sizeof(struct flock)) != B_OK)
status = B_BAD_ADDRESS;
if (status != B_OK) { if (status != B_OK) {
put_fd(descriptor); put_fd(descriptor);
return status; return status;
@@ -8804,7 +8798,10 @@ _user_read_fs_info(dev_t device, struct fs_info* userInfo)
if (status != B_OK) if (status != B_OK)
return status; return status;
return copy_ref_var_to_user(info, userInfo); if (user_memcpy(userInfo, &info, sizeof(struct fs_info)) != B_OK)
return B_BAD_ADDRESS;
return B_OK;
} }
@@ -8816,9 +8813,9 @@ _user_write_fs_info(dev_t device, const struct fs_info* userInfo, int mask)
if (userInfo == NULL) if (userInfo == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
status_t status = copy_ref_var_from_user((struct fs_info*)userInfo, info); if (!IS_USER_ADDRESS(userInfo)
if (status != B_OK) || user_memcpy(&info, userInfo, sizeof(struct fs_info)) != B_OK)
return status; return B_BAD_ADDRESS;
return fs_write_info(device, &info, mask); return fs_write_info(device, &info, mask);
} }
@@ -8864,6 +8861,9 @@ _user_get_next_fd_info(team_id team, uint32* userCookie, fd_info* userInfo,
if (geteuid() != 0) if (geteuid() != 0)
return B_NOT_ALLOWED; return B_NOT_ALLOWED;
if (infoSize != sizeof(fd_info))
return B_BAD_VALUE;
if (!IS_USER_ADDRESS(userCookie) || !IS_USER_ADDRESS(userInfo) if (!IS_USER_ADDRESS(userCookie) || !IS_USER_ADDRESS(userInfo)
|| user_memcpy(&cookie, userCookie, sizeof(uint32)) != B_OK) || user_memcpy(&cookie, userCookie, sizeof(uint32)) != B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
@@ -8872,9 +8872,11 @@ _user_get_next_fd_info(team_id team, uint32* userCookie, fd_info* userInfo,
if (status != B_OK) if (status != B_OK)
return status; return status;
if (user_memcpy(userCookie, &cookie, sizeof(uint32)) != B_OK) if (user_memcpy(userCookie, &cookie, sizeof(uint32)) != B_OK
|| user_memcpy(userInfo, &info, infoSize) != B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
return copy_ref_var_to_user(info, userInfo);
return status;
} }
@@ -9525,7 +9527,7 @@ _user_read_stat(int fd, const char* userPath, bool traverseLink,
if (status != B_OK) if (status != B_OK)
return status; return status;
return copy_ref_var_to_user(stat, userStat, statSize); return user_memcpy(userStat, &stat, statSize);
} }
@@ -9696,7 +9698,8 @@ _user_stat_attr(int fd, const char* userAttribute,
info.type = stat.st_type; info.type = stat.st_type;
info.size = stat.st_size; info.size = stat.st_size;
status = copy_ref_var_to_user(info, userAttrInfo); if (user_memcpy(userAttrInfo, &info, sizeof(struct attr_info)) != B_OK)
return B_BAD_ADDRESS;
} }
return status; return status;
@@ -9805,8 +9808,10 @@ _user_read_index_stat(dev_t device, const char* userName, struct stat* userStat)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
status = index_name_read_stat(device, name, &stat, false); status = index_name_read_stat(device, name, &stat, false);
if (status == B_OK) if (status == B_OK) {
status = copy_ref_var_to_user(stat, userStat); if (user_memcpy(userStat, &stat, sizeof(stat)) != B_OK)
return B_BAD_ADDRESS;
}
return status; return status;
} }
+15 -15
View File
@@ -18,11 +18,6 @@
#include <thread_types.h> #include <thread_types.h>
#include <user_debugger.h> #include <user_debugger.h>
#include <util/AutoLock.h> #include <util/AutoLock.h>
#include <util/syscall_args.h>
#ifdef _COMPAT_MODE
# include <image_compat.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -469,9 +464,12 @@ _user_register_image(extended_image_info *userInfo, size_t size)
{ {
extended_image_info info; extended_image_info info;
status_t status = copy_ref_var_from_user(userInfo, info, size); if (size != sizeof(info))
if (status != B_OK) return B_BAD_VALUE;
return status;
if (!IS_USER_ADDRESS(userInfo)
|| user_memcpy(&info, userInfo, size) < B_OK)
return B_BAD_ADDRESS;
return register_image(thread_get_current_thread()->team, &info, size); return register_image(thread_get_current_thread()->team, &info, size);
} }
@@ -527,9 +525,9 @@ _user_get_image_info(image_id id, image_info *userInfo, size_t size)
status = _get_image_info(id, &info, sizeof(image_info)); status = _get_image_info(id, &info, sizeof(image_info));
status_t err = copy_ref_var_to_user(info, userInfo, size); if (user_memcpy(userInfo, &info, size) < B_OK)
if (err != B_OK) return B_BAD_ADDRESS;
return err;
return status; return status;
} }
@@ -542,6 +540,9 @@ _user_get_next_image_info(team_id team, int32 *_cookie, image_info *userInfo,
status_t status; status_t status;
int32 cookie; int32 cookie;
if (size > sizeof(image_info))
return B_BAD_VALUE;
if (!IS_USER_ADDRESS(userInfo) || !IS_USER_ADDRESS(_cookie) if (!IS_USER_ADDRESS(userInfo) || !IS_USER_ADDRESS(_cookie)
|| user_memcpy(&cookie, _cookie, sizeof(int32)) < B_OK) { || user_memcpy(&cookie, _cookie, sizeof(int32)) < B_OK) {
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
@@ -549,11 +550,10 @@ _user_get_next_image_info(team_id team, int32 *_cookie, image_info *userInfo,
status = _get_next_image_info(team, &cookie, &info, sizeof(image_info)); status = _get_next_image_info(team, &cookie, &info, sizeof(image_info));
status_t err = copy_ref_var_to_user(info, userInfo, size); if (user_memcpy(userInfo, &info, size) < B_OK
if (err != B_OK) || user_memcpy(_cookie, &cookie, sizeof(int32)) < B_OK) {
return err;
if (user_memcpy(_cookie, &cookie, sizeof(int32)) < B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
}
return status; return status;
} }
+23 -143
View File
@@ -35,11 +35,6 @@
#include <user_debugger.h> #include <user_debugger.h>
#include <user_thread.h> #include <user_thread.h>
#include <util/AutoLock.h> #include <util/AutoLock.h>
#include <util/syscall_args.h>
#ifdef _COMPAT_MODE
# include <compat/ksignal_compat.h>
#endif
//#define TRACE_SIGNAL //#define TRACE_SIGNAL
@@ -913,61 +908,6 @@ setup_signal_frame(Thread* thread, struct sigaction* action, Signal* signal,
} }
#ifdef _COMPAT_MODE
static status_t
setup_compat_signal_frame(Thread* thread, struct sigaction* action, Signal* signal,
sigset_t signalMask)
{
// prepare the data, we need to copy onto the user stack
struct compat_signal_frame_data frameData;
// signal info
frameData.info.si_signo = signal->Number();
frameData.info.si_code = signal->SignalCode();
frameData.info.si_errno = signal->ErrorCode();
frameData.info.si_pid = signal->SendingProcess();
frameData.info.si_uid = signal->SendingUser();
frameData.info.si_addr = (addr_t)signal->Address();
frameData.info.si_status = signal->Status();
frameData.info.si_band = signal->PollBand();
frameData.info.si_value.sival_ptr = (addr_t)signal->UserValue().sival_ptr;
// context
frameData.context.uc_link = (addr_t)thread->user_signal_context;
frameData.context.uc_sigmask = signalMask;
// uc_stack and uc_mcontext are filled in by the architecture specific code.
// user data
frameData.user_data = (addr_t)action->sa_userdata;
// handler function
frameData.siginfo_handler = (action->sa_flags & SA_SIGINFO) != 0;
frameData.handler = frameData.siginfo_handler
? (addr_t)action->sa_sigaction : (addr_t)action->sa_handler;
// thread flags -- save the and clear the thread's syscall restart related
// flags
frameData.thread_flags = atomic_and(&thread->flags,
~(THREAD_FLAGS_RESTART_SYSCALL | THREAD_FLAGS_64_BIT_SYSCALL_RETURN));
// syscall restart related fields
memcpy(frameData.syscall_restart_parameters,
thread->syscall_restart.parameters,
sizeof(frameData.syscall_restart_parameters));
// commpage address
frameData.commpage_address = (addr_t)thread->team->commpage_address;
// syscall_restart_return_value is filled in by the architecture specific
// code.
return arch_setup_compat_signal_frame(thread, action, &frameData);
}
#endif // _COMPAT_MODE
/*! Actually handles pending signals -- i.e. the thread will exit, a custom /*! Actually handles pending signals -- i.e. the thread will exit, a custom
signal handler is prepared, or whatever the signal demands. signal handler is prepared, or whatever the signal demands.
The function will not return, when a deadly signal is encountered. The The function will not return, when a deadly signal is encountered. The
@@ -1318,11 +1258,6 @@ handle_signals(Thread* thread)
locker.Unlock(); locker.Unlock();
#ifdef _COMPAT_MODE
if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0)
setup_compat_signal_frame(thread, &handler, signal, oldBlockMask);
else
#endif
setup_signal_frame(thread, &handler, signal, oldBlockMask); setup_signal_frame(thread, &handler, signal, oldBlockMask);
// Reset sigsuspend_original_unblocked_mask. It would have been set by // Reset sigsuspend_original_unblocked_mask. It would have been set by
@@ -2300,10 +2235,11 @@ _user_send_signal(int32 id, uint32 signalNumber,
// Copy the user value from userland. If not given, use a dummy value. // Copy the user value from userland. If not given, use a dummy value.
union sigval userValue; union sigval userValue;
if (userUserValue != NULL) { if (userUserValue != NULL) {
status_t status = copy_ref_var_from_user((union sigval*)userUserValue, if (!IS_USER_ADDRESS(userUserValue)
userValue); || user_memcpy(&userValue, userUserValue, sizeof(userValue))
if (status != B_OK) != B_OK) {
return status; return B_BAD_ADDRESS;
}
} else } else
userValue.sival_ptr = NULL; userValue.sival_ptr = NULL;
@@ -2360,23 +2296,20 @@ _user_sigaction(int signal, const struct sigaction *userAction,
struct sigaction act, oact; struct sigaction act, oact;
status_t status; status_t status;
if (userAction != NULL) { if ((userAction != NULL && (!IS_USER_ADDRESS(userAction)
status = copy_ref_var_from_user((struct sigaction*)userAction, act); || user_memcpy(&act, userAction, sizeof(struct sigaction)) < B_OK))
if (status < B_OK) || (userOldAction != NULL && (!IS_USER_ADDRESS(userOldAction)
return status; || user_memcpy(&oact, userOldAction, sizeof(struct sigaction))
} < B_OK)))
if (userOldAction != NULL) { return B_BAD_ADDRESS;
status = copy_ref_var_from_user(userOldAction, oact);
if (status < B_OK)
return status;
}
status = sigaction_internal(signal, userAction ? &act : NULL, status = sigaction_internal(signal, userAction ? &act : NULL,
userOldAction ? &oact : NULL); userOldAction ? &oact : NULL);
// only copy the old action if a pointer has been given // only copy the old action if a pointer has been given
if (status >= B_OK && userOldAction != NULL) if (status >= B_OK && userOldAction != NULL
status = copy_ref_var_to_user(oact, userOldAction); && user_memcpy(userOldAction, &oact, sizeof(struct sigaction)) < B_OK)
return B_BAD_ADDRESS;
return status; return status;
} }
@@ -2406,7 +2339,7 @@ _user_sigwait(const sigset_t *userSet, siginfo_t *userInfo, uint32 flags,
if (status == B_OK) { if (status == B_OK) {
// copy the info back to userland, if userSet is non-NULL // copy the info back to userland, if userSet is non-NULL
if (userInfo != NULL) if (userInfo != NULL)
status = copy_ref_var_to_user(info, userInfo); status = user_memcpy(userInfo, &info, sizeof(info));
} else if (status == B_INTERRUPTED) { } else if (status == B_INTERRUPTED) {
// make sure we'll be restarted // make sure we'll be restarted
Thread* thread = thread_get_current_thread(); Thread* thread = thread_get_current_thread();
@@ -2460,17 +2393,11 @@ _user_set_signal_stack(const stack_t* newUserStack, stack_t* oldUserStack)
struct stack_t newStack, oldStack; struct stack_t newStack, oldStack;
bool onStack = false; bool onStack = false;
if (newUserStack != NULL) { if ((newUserStack != NULL && (!IS_USER_ADDRESS(newUserStack)
status_t status = copy_ref_var_from_user((stack_t*)newUserStack, || user_memcpy(&newStack, newUserStack, sizeof(stack_t)) < B_OK))
newStack); || (oldUserStack != NULL && (!IS_USER_ADDRESS(oldUserStack)
if (status < B_OK) || user_memcpy(&oldStack, oldUserStack, sizeof(stack_t)) < B_OK)))
return status; return B_BAD_ADDRESS;
}
if (oldUserStack != NULL) {
status_t status = copy_ref_var_from_user(oldUserStack, oldStack);
if (status < B_OK)
return status;
}
if (thread->signal_stack_enabled) { if (thread->signal_stack_enabled) {
// determine whether or not the user thread is currently // determine whether or not the user thread is currently
@@ -2507,8 +2434,9 @@ _user_set_signal_stack(const stack_t* newUserStack, stack_t* oldUserStack)
} }
// only copy the old stack info if a pointer has been given // only copy the old stack info if a pointer has been given
if (oldUserStack != NULL) if (oldUserStack != NULL
return copy_ref_var_to_user(oldStack, oldUserStack); && user_memcpy(oldUserStack, &oldStack, sizeof(stack_t)) < B_OK)
return B_BAD_ADDRESS;
return B_OK; return B_OK;
} }
@@ -2542,54 +2470,6 @@ _user_restore_signal_frame(struct signal_frame_data* userSignalFrameData)
Thread *thread = thread_get_current_thread(); Thread *thread = thread_get_current_thread();
#ifdef _COMPAT_MODE
if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0) {
// copy the signal frame data from userland
compat_signal_frame_data signalFrameData;
if (userSignalFrameData == NULL || !IS_USER_ADDRESS(userSignalFrameData)
|| user_memcpy(&signalFrameData, userSignalFrameData,
sizeof(signalFrameData)) != B_OK) {
// We failed to copy the signal frame data from userland. This is a
// serious problem. Kill the thread.
dprintf("_user_restore_signal_frame(): thread %" B_PRId32 ": Failed to "
"copy signal frame data (%p) from userland. Killing thread...\n",
thread->id, userSignalFrameData);
kill_thread(thread->id);
return B_BAD_ADDRESS;
}
// restore the signal block mask
InterruptsSpinLocker locker(thread->team->signal_lock);
thread->sig_block_mask
= signalFrameData.context.uc_sigmask & BLOCKABLE_SIGNALS;
update_current_thread_signals_flag();
locker.Unlock();
// restore the syscall restart related thread flags and the syscall restart
// parameters
atomic_and(&thread->flags,
~(THREAD_FLAGS_RESTART_SYSCALL | THREAD_FLAGS_64_BIT_SYSCALL_RETURN));
atomic_or(&thread->flags, signalFrameData.thread_flags
& (THREAD_FLAGS_RESTART_SYSCALL | THREAD_FLAGS_64_BIT_SYSCALL_RETURN));
memcpy(thread->syscall_restart.parameters,
signalFrameData.syscall_restart_parameters,
sizeof(thread->syscall_restart.parameters));
// restore the previously stored Thread::user_signal_context
thread->user_signal_context = (ucontext_t*)(addr_t)signalFrameData.context.uc_link;
if (thread->user_signal_context != NULL
&& !IS_USER_ADDRESS(thread->user_signal_context)) {
thread->user_signal_context = NULL;
}
// let the architecture specific code restore the registers
return arch_restore_compat_signal_frame(&signalFrameData);
}
#endif
// copy the signal frame data from userland // copy the signal frame data from userland
signal_frame_data signalFrameData; signal_frame_data signalFrameData;
if (userSignalFrameData == NULL || !IS_USER_ADDRESS(userSignalFrameData) if (userSignalFrameData == NULL || !IS_USER_ADDRESS(userSignalFrameData)
+7 -6
View File
@@ -31,9 +31,6 @@
#include <lock.h> #include <lock.h>
#include <Notifications.h> #include <Notifications.h>
#include <messaging.h> #include <messaging.h>
#ifdef _COMPAT_MODE
# include <OS_compat.h>
#endif
#include <port.h> #include <port.h>
#include <real_time_clock.h> #include <real_time_clock.h>
#include <sem.h> #include <sem.h>
@@ -41,7 +38,6 @@
#include <team.h> #include <team.h>
#include <thread.h> #include <thread.h>
#include <util/AutoLock.h> #include <util/AutoLock.h>
#include <util/syscall_args.h>
#include <vm/vm.h> #include <vm/vm.h>
#include <vm/vm_page.h> #include <vm/vm_page.h>
@@ -549,8 +545,13 @@ _user_get_system_info(system_info* userInfo)
system_info info; system_info info;
status_t status = get_system_info(&info); status_t status = get_system_info(&info);
if (status == B_OK) if (status == B_OK) {
return copy_ref_var_to_user(info, userInfo); if (user_memcpy(userInfo, &info, sizeof(system_info)) < B_OK)
return B_BAD_ADDRESS;
return B_OK;
}
return status; return status;
} }
+39 -100
View File
@@ -47,17 +47,12 @@
#include <team.h> #include <team.h>
#include <tracing.h> #include <tracing.h>
#include <util/AutoLock.h> #include <util/AutoLock.h>
#include <util/syscall_args.h>
#include <vm/vm_page.h> #include <vm/vm_page.h>
#include <vm/vm_priv.h> #include <vm/vm_priv.h>
#include <vm/VMAddressSpace.h> #include <vm/VMAddressSpace.h>
#include <vm/VMArea.h> #include <vm/VMArea.h>
#include <vm/VMCache.h> #include <vm/VMCache.h>
#ifdef _COMPAT_MODE
# include <OS_compat.h>
#endif
#include "VMAddressSpaceLocking.h" #include "VMAddressSpaceLocking.h"
#include "VMAnonymousCache.h" #include "VMAnonymousCache.h"
#include "VMAnonymousNoSwapCache.h" #include "VMAnonymousNoSwapCache.h"
@@ -6008,44 +6003,6 @@ _get_next_area_info(team_id team, ssize_t* cookie, area_info* info, size_t size)
} }
#ifdef _COMPAT_MODE
status_t
_compat_get_next_area_info(team_id team, ssize_t* cookie, area_info* info, size_t size)
{
area_id nextID = *(area_id*)cookie;
// we're already through the list
if (nextID == (area_id)-1)
return B_ENTRY_NOT_FOUND;
if (team == B_CURRENT_TEAM)
team = team_get_current_team_id();
AddressSpaceReadLocker locker(team);
if (!locker.IsLocked())
return B_BAD_TEAM_ID;
VMArea* area;
for (VMAddressSpace::AreaIterator it
= locker.AddressSpace()->GetAreaIterator();
(area = it.Next()) != NULL;) {
if (area->id > nextID)
break;
}
if (area == NULL) {
nextID = (area_id)-1;
return B_ENTRY_NOT_FOUND;
}
fill_area_info(area, info, size);
*cookie = (ssize_t)(area->id);
return B_OK;
}
#endif
status_t status_t
set_area_protection(area_id area, uint32 newProtection) set_area_protection(area_id area, uint32 newProtection)
{ {
@@ -6175,22 +6132,23 @@ _user_reserve_address_range(addr_t* userAddress, uint32 addressSpec,
addr_t address; addr_t address;
status_t status = copy_ref_var_from_user(userAddress, address); if (!IS_USER_ADDRESS(userAddress)
if (status != B_OK) || user_memcpy(&address, userAddress, sizeof(address)) != B_OK)
return status; return B_BAD_ADDRESS;
status = vm_reserve_address_range( status_t status = vm_reserve_address_range(
VMAddressSpace::CurrentID(), (void**)&address, addressSpec, size, VMAddressSpace::CurrentID(), (void**)&address, addressSpec, size,
RESERVED_AVOID_BASE); RESERVED_AVOID_BASE);
if (status != B_OK) if (status != B_OK)
return status; return status;
status = copy_ref_var_to_user(address, userAddress); if (user_memcpy(userAddress, &address, sizeof(address)) != B_OK) {
if (status != B_OK) {
vm_unreserve_address_range(VMAddressSpace::CurrentID(), vm_unreserve_address_range(VMAddressSpace::CurrentID(),
(void*)address, size); (void*)address, size);
return B_BAD_ADDRESS;
} }
return status;
return B_OK;
} }
@@ -6236,8 +6194,10 @@ _user_get_area_info(area_id area, area_info* userInfo)
// TODO: do we want to prevent userland from seeing kernel protections? // TODO: do we want to prevent userland from seeing kernel protections?
//info.protection &= B_USER_PROTECTION; //info.protection &= B_USER_PROTECTION;
return copy_ref_var_to_user(info, userInfo); if (user_memcpy(userInfo, &info, sizeof(area_info)) < B_OK)
return B_BAD_ADDRESS;
return status;
} }
@@ -6247,28 +6207,21 @@ _user_get_next_area_info(team_id team, ssize_t* userCookie, area_info* userInfo)
ssize_t cookie; ssize_t cookie;
if (!IS_USER_ADDRESS(userCookie) if (!IS_USER_ADDRESS(userCookie)
|| !IS_USER_ADDRESS(userInfo)) || !IS_USER_ADDRESS(userInfo)
|| user_memcpy(&cookie, userCookie, sizeof(ssize_t)) < B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
status_t status = copy_ref_var_from_user(userCookie, cookie);
if (status != B_OK)
return status;
area_info info; area_info info;
#ifdef _COMPAT_MODE status_t status = _get_next_area_info(team, &cookie, &info,
status = _compat_get_next_area_info(team, &cookie, &info,
#else
status = _get_next_area_info(team, &cookie, &info,
#endif
sizeof(area_info)); sizeof(area_info));
if (status != B_OK) if (status != B_OK)
return status; return status;
//info.protection &= B_USER_PROTECTION; //info.protection &= B_USER_PROTECTION;
status = copy_ref_var_to_user(cookie, userCookie); if (user_memcpy(userCookie, &cookie, sizeof(ssize_t)) < B_OK
if (status == B_OK) || user_memcpy(userInfo, &info, sizeof(area_info)) < B_OK)
status = copy_ref_var_to_user(info, userInfo); return B_BAD_ADDRESS;
return status; return status;
} }
@@ -6306,17 +6259,16 @@ _user_transfer_area(area_id area, void** userAddress, uint32 addressSpec,
} }
void* address; void* address;
status_t status = copy_ref_var_from_user(userAddress, address); if (!IS_USER_ADDRESS(userAddress)
if (status != B_OK) || user_memcpy(&address, userAddress, sizeof(address)) < B_OK)
return status; return B_BAD_ADDRESS;
area_id newArea = transfer_area(area, &address, addressSpec, target, false); area_id newArea = transfer_area(area, &address, addressSpec, target, false);
if (newArea < B_OK) if (newArea < B_OK)
return newArea; return newArea;
status = copy_ref_var_to_user(address, userAddress); if (user_memcpy(userAddress, &address, sizeof(address)) < B_OK)
if (status != B_OK) return B_BAD_ADDRESS;
return status;
return newArea; return newArea;
} }
@@ -6339,13 +6291,11 @@ _user_clone_area(const char* userName, void** userAddress, uint32 addressSpec,
return B_BAD_VALUE; return B_BAD_VALUE;
if (!IS_USER_ADDRESS(userName) if (!IS_USER_ADDRESS(userName)
|| user_strlcpy(name, userName, sizeof(name)) < B_OK) || !IS_USER_ADDRESS(userAddress)
|| user_strlcpy(name, userName, sizeof(name)) < B_OK
|| user_memcpy(&address, userAddress, sizeof(address)) < B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
status_t status = copy_ref_var_from_user(userAddress, address);
if (status != B_OK)
return status;
fix_protection(&protection); fix_protection(&protection);
area_id clonedArea = vm_clone_area(VMAddressSpace::CurrentID(), name, area_id clonedArea = vm_clone_area(VMAddressSpace::CurrentID(), name,
@@ -6354,10 +6304,9 @@ _user_clone_area(const char* userName, void** userAddress, uint32 addressSpec,
if (clonedArea < B_OK) if (clonedArea < B_OK)
return clonedArea; return clonedArea;
status = copy_ref_var_to_user(address, userAddress); if (user_memcpy(userAddress, &address, sizeof(address)) < B_OK) {
if (status < B_OK) {
delete_area(clonedArea); delete_area(clonedArea);
return status; return B_BAD_ADDRESS;
} }
return clonedArea; return clonedArea;
@@ -6381,13 +6330,11 @@ _user_create_area(const char* userName, void** userAddress, uint32 addressSpec,
return B_BAD_VALUE; return B_BAD_VALUE;
if (!IS_USER_ADDRESS(userName) if (!IS_USER_ADDRESS(userName)
|| user_strlcpy(name, userName, sizeof(name)) < B_OK) || !IS_USER_ADDRESS(userAddress)
|| user_strlcpy(name, userName, sizeof(name)) < B_OK
|| user_memcpy(&address, userAddress, sizeof(address)) < B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
status_t status = copy_ref_var_from_user(userAddress, address);
if (status != B_OK)
return status;
if (addressSpec == B_EXACT_ADDRESS if (addressSpec == B_EXACT_ADDRESS
&& IS_KERNEL_ADDRESS(address)) && IS_KERNEL_ADDRESS(address))
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -6407,12 +6354,10 @@ _user_create_area(const char* userName, void** userAddress, uint32 addressSpec,
size, lock, protection, 0, 0, &virtualRestrictions, size, lock, protection, 0, 0, &virtualRestrictions,
&physicalRestrictions, false, &address); &physicalRestrictions, false, &address);
if (area >= B_OK) { if (area >= B_OK
status = copy_ref_var_to_user(address, userAddress); && user_memcpy(userAddress, &address, sizeof(address)) < B_OK) {
if (status < B_OK) { delete_area(area);
delete_area(area); return B_BAD_ADDRESS;
return status;
}
} }
return area; return area;
@@ -6446,14 +6391,11 @@ _user_map_file(const char* userName, void** userAddress, uint32 addressSpec,
fix_protection(&protection); fix_protection(&protection);
if (!IS_USER_ADDRESS(userName) if (!IS_USER_ADDRESS(userName) || !IS_USER_ADDRESS(userAddress)
|| user_strlcpy(name, userName, B_OS_NAME_LENGTH) < B_OK) || user_strlcpy(name, userName, B_OS_NAME_LENGTH) < B_OK
|| user_memcpy(&address, userAddress, sizeof(address)) < B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
status_t status = copy_ref_var_from_user(userAddress, address);
if (status != B_OK)
return status;
if (addressSpec == B_EXACT_ADDRESS) { if (addressSpec == B_EXACT_ADDRESS) {
if ((addr_t)address + size < (addr_t)address if ((addr_t)address + size < (addr_t)address
|| (addr_t)address % B_PAGE_SIZE != 0) { || (addr_t)address % B_PAGE_SIZE != 0) {
@@ -6471,11 +6413,8 @@ _user_map_file(const char* userName, void** userAddress, uint32 addressSpec,
if (area < B_OK) if (area < B_OK)
return area; return area;
status = copy_ref_var_to_user(address, userAddress); if (user_memcpy(userAddress, &address, sizeof(address)) < B_OK)
if (status < B_OK) { return B_BAD_ADDRESS;
delete_area(area);
return status;
}
return area; return area;
} }