kernel/x86_64: setup a new thread in compatibility mode.

* define compat_thread_info, compat_rlim_t, compat_rlimit and
compat_thread_creation_attributes to be used when applicable in compatibility
mode.
* handle 32-bit types in _user_spawn_thread(), _user_get_thread_info(),
_user_get_next_thread_info(), _user_getrlimit(), _user_setrlimit(),
other syscalls are compatible as is.
* init TLS for compatibility mode threads.

Change-Id: I483ba95e6198ddac9d240671bcb56fcd2ad831d2
This commit is contained in:
Jérôme Duval
2018-06-12 17:56:55 +02:00
parent 951182620e
commit a69cb33030
6 changed files with 205 additions and 22 deletions
+28
View File
@@ -163,6 +163,34 @@ static_assert(sizeof(compat_thread_info) == 76,
"size of compat_thread_info mismatch");
inline status_t
copy_ref_var_to_user(thread_info &info, thread_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_thread_info compatInfo;
compatInfo.thread = info.thread;
compatInfo.team = info.team;
strlcpy(compatInfo.name, info.name, sizeof(compatInfo.name));
compatInfo.state = info.state;
compatInfo.priority = info.priority;
compatInfo.sem = info.sem;
compatInfo.user_time = info.user_time;
compatInfo.kernel_time = info.kernel_time;
compatInfo.stack_base = (uint32)(addr_t)info.stack_base;
compatInfo.stack_end = (uint32)(addr_t)info.stack_end;
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;
}
inline status_t
copy_ref_var_to_user(void* &addr, void** userAddr)
{
@@ -0,0 +1,60 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_RESOURCE_H
#define _KERNEL_COMPAT_RESOURCE_H
#include <sys/resource.h>
typedef uint32 compat_rlim_t;
struct compat_rlimit {
compat_rlim_t rlim_cur; /* current soft limit */
compat_rlim_t rlim_max; /* hard limit */
};
inline status_t
copy_ref_var_to_user(struct rlimit &rl, struct rlimit* urlp)
{
if (!IS_USER_ADDRESS(urlp))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
struct compat_rlimit compat_rl;
compat_rl.rlim_cur = rl.rlim_cur;
compat_rl.rlim_max = rl.rlim_max;
if (user_memcpy(urlp, &compat_rl, sizeof(compat_rl)) < B_OK)
return B_BAD_ADDRESS;
} else if (user_memcpy(urlp, &rl, sizeof(rl)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
inline status_t
copy_ref_var_from_user(struct rlimit* urlp, struct rlimit &rl)
{
if (!IS_USER_ADDRESS(urlp))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
struct compat_rlimit compat_rl;
if (user_memcpy(&compat_rl, urlp, sizeof(compat_rl)) < B_OK)
return B_BAD_ADDRESS;
rl.rlim_cur = compat_rl.rlim_cur;
rl.rlim_max = compat_rl.rlim_max;
} else if (user_memcpy(&rl, urlp, sizeof(rl)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_RESOURCE_H
@@ -0,0 +1,61 @@
/*
* Copyright 2018, Haiku Inc. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_COMPAT_THREAD_DEFS_H
#define _KERNEL_COMPAT_THREAD_DEFS_H
#include <thread_defs.h>
#define compat_ptr_t uint32
struct compat_thread_creation_attributes {
compat_ptr_t entry;
compat_ptr_t name;
int32 priority;
compat_ptr_t args1;
compat_ptr_t args2;
compat_ptr_t stack_address;
uint32_t stack_size;
uint32_t guard_size;
compat_ptr_t pthread;
uint32 flags;
} _PACKED;
static_assert(sizeof(struct compat_thread_creation_attributes) == 40,
"size of compat_thread_creation_attributes mismatch");
inline status_t
copy_ref_var_from_user(BKernel::ThreadCreationAttributes* userAttrs,
BKernel::ThreadCreationAttributes &attrs)
{
if (!IS_USER_ADDRESS(userAttrs))
return B_BAD_ADDRESS;
Thread* thread = thread_get_current_thread();
bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
if (compatMode) {
struct compat_thread_creation_attributes compatAttrs;
if (user_memcpy(&compatAttrs, userAttrs, sizeof(compatAttrs)) < B_OK)
return B_BAD_ADDRESS;
attrs.entry = (int32 (*)(void*, void*))(addr_t)compatAttrs.entry;
attrs.name = (const char*)(addr_t)compatAttrs.name;
attrs.priority = compatAttrs.priority;
attrs.args1 = (void*)(addr_t)compatAttrs.args1;
attrs.args2 = (void*)(addr_t)compatAttrs.args2;
attrs.stack_address = (void*)(addr_t)compatAttrs.stack_address;
attrs.stack_size = compatAttrs.stack_size;
attrs.guard_size = compatAttrs.guard_size;
attrs.pthread = (pthread_t)(addr_t)compatAttrs.pthread;
attrs.flags = compatAttrs.flags;
} else if (user_memcpy(&attrs, userAttrs, sizeof(attrs)) < B_OK) {
return B_BAD_ADDRESS;
}
return B_OK;
}
#endif // _KERNEL_COMPAT_THREAD_DEFS_H