fix catalina issue of mprotect on stack memory by defaulting to mmap for darwin
This commit is contained in:
parent
59bd2d84c0
commit
eda897279a
|
@ -603,8 +603,27 @@ static inline void *split_cross_256mb(void *buf1, size_t size1)
|
|||
return buf1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_STATIC_CODE_GEN_BUFFER
|
||||
#if defined(CONFIG_DARWIN_USER)
|
||||
static inline void *alloc_code_gen_buffer(void)
|
||||
{
|
||||
int prot = PROT_WRITE | PROT_READ | PROT_EXEC;
|
||||
int flags = MAP_PRIVATE | MAP_ANON;
|
||||
/* let a kernel pick an address close to the executable */
|
||||
uintptr_t start = 0;
|
||||
/* Honor a command-line option limiting the size of the buffer. */
|
||||
size_t size = DEFAULT_CODE_GEN_BUFFER_SIZE;
|
||||
void *buf;
|
||||
|
||||
buf = mmap((void *)start, size, prot, flags, -1, 0);
|
||||
if (buf == MAP_FAILED) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qemu_madvise(buf, size, QEMU_MADV_HUGEPAGE);
|
||||
return buf;
|
||||
}
|
||||
#else /* !CONFIG_DARWIN_USER */
|
||||
static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE]
|
||||
__attribute__((aligned(CODE_GEN_ALIGN)));
|
||||
|
||||
|
@ -641,6 +660,8 @@ static inline void *alloc_code_gen_buffer(void)
|
|||
|
||||
return buf;
|
||||
}
|
||||
#endif /* CONFIG_DARWIN_USER */
|
||||
|
||||
#elif defined(_WIN32)
|
||||
static inline void *alloc_code_gen_buffer(void)
|
||||
{
|
||||
|
|
|
@ -41,7 +41,7 @@ struct target_dirent {
|
|||
char d_name[1];
|
||||
};
|
||||
/* size of struct target_dirent without the name array */
|
||||
#define target_dirent_len (offsetof(struct target_dirent, d_name))
|
||||
#define TARGET_DIRENT_LEN (offsetof(struct target_dirent, d_name))
|
||||
|
||||
/* IRIX sys/types.h */
|
||||
typedef uint64_t target_ino64_t;
|
||||
|
|
|
@ -10806,12 +10806,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
case TARGET_NR_getdents:
|
||||
{
|
||||
struct target_dirent *target_dirp;
|
||||
struct dirent *host_dirp;
|
||||
DIR *dirp;
|
||||
abi_long dir_fd = arg1;
|
||||
abi_long count = arg3;
|
||||
int found_err = FALSE;
|
||||
// ret == bytes read, or target error code
|
||||
|
||||
// ret == >0 => bytes read
|
||||
// 0 => end of directory
|
||||
// <0 => -(target errno)
|
||||
|
||||
dirp = fdopendir(dir_fd);
|
||||
if (!dirp) {
|
||||
|
@ -10819,12 +10820,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
host_dirp = g_try_malloc(count);
|
||||
if (!host_dirp) {
|
||||
ret = -TARGET_ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// collect readdir calls into getdents dirp * buffer
|
||||
target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
|
||||
if (!target_dirp) {
|
||||
|
@ -10837,10 +10832,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
uint target_reclen;
|
||||
uint name_len;
|
||||
|
||||
errno = 0;
|
||||
while ((de = readdir(dirp))) {
|
||||
// check if new entry will overflow the target buffer
|
||||
name_len = de->d_namlen + 1;
|
||||
target_reclen = target_dirent_len + name_len;
|
||||
target_reclen = TARGET_DIRENT_LEN + name_len;
|
||||
// is this the correct way to align this structure..?
|
||||
target_reclen = QEMU_ALIGN_UP(target_reclen, __alignof(struct target_dirent));
|
||||
if (bytes_used + target_reclen > count) {
|
||||
|
@ -10857,7 +10853,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
bytes_used += target_reclen;
|
||||
}
|
||||
|
||||
if (found_err) {
|
||||
if (errno != 0) {
|
||||
ret = -host_to_target_errno(errno);
|
||||
} else {
|
||||
ret = bytes_used;
|
||||
|
@ -10867,112 +10863,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
// which was used in `fdopendir`
|
||||
// closedir(dirp);
|
||||
}
|
||||
// Old Linux code
|
||||
// #ifdef __NR_getdents
|
||||
// {
|
||||
// struct target_dirent *target_dirp;
|
||||
// struct linux_dirent *dirp;
|
||||
// abi_long count = arg3;
|
||||
//
|
||||
// dirp = g_try_malloc(count);
|
||||
// if (!dirp) {
|
||||
// ret = -TARGET_ENOMEM;
|
||||
// goto fail;
|
||||
// }
|
||||
//
|
||||
// ret = get_errno(sys_getdents(arg1, dirp, count));
|
||||
// if (!is_error(ret)) {
|
||||
// struct linux_dirent *de;
|
||||
// struct target_dirent *tde;
|
||||
// int len = ret;
|
||||
// int reclen, treclen;
|
||||
// int count1, tnamelen;
|
||||
//
|
||||
// count1 = 0;
|
||||
// de = dirp;
|
||||
// if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
|
||||
// goto efault;
|
||||
// tde = target_dirp;
|
||||
// while (len > 0) {
|
||||
// reclen = de->d_reclen;
|
||||
// tnamelen = reclen - offsetof(struct linux_dirent, d_name);
|
||||
// tnamelen = strnlen(de->d_name, tnamelen) + 1;
|
||||
// assert(tnamelen >= 0);
|
||||
// treclen = tnamelen + offsetof(struct target_dirent, d_name);
|
||||
// /* XXX: avoid buffer overflow, for the price of lost entries */
|
||||
// if (count1 + treclen > count)
|
||||
// break;
|
||||
// __put_user(treclen, &tde->d_reclen);
|
||||
// __put_user(de->d_ino, &tde->d_ino);
|
||||
// __put_user(de->d_off, &tde->d_off);
|
||||
// memcpy(tde->d_name, de->d_name, tnamelen);
|
||||
// de = (struct linux_dirent *)((char *)de + reclen);
|
||||
// len -= reclen;
|
||||
// tde = (struct target_dirent *)((char *)tde + treclen);
|
||||
// count1 += treclen;
|
||||
// }
|
||||
// ret = count1;
|
||||
// unlock_user(target_dirp, arg2, ret);
|
||||
// }
|
||||
// g_free(dirp);
|
||||
// }
|
||||
// #else
|
||||
// /* Implement getdents in terms of getdents64 */
|
||||
// {
|
||||
// struct linux_dirent64 *dirp;
|
||||
// abi_long count = arg3;
|
||||
//
|
||||
// dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
|
||||
// if (!dirp) {
|
||||
// goto efault;
|
||||
// }
|
||||
// ret = get_errno(sys_getdents64(arg1, dirp, count));
|
||||
// if (!is_error(ret)) {
|
||||
// /* Convert the dirent64 structs to target dirent. We do this
|
||||
// * in-place, since we can guarantee that a target_dirent is no
|
||||
// * larger than a dirent64; however this means we have to be
|
||||
// * careful to read everything before writing in the new format.
|
||||
// */
|
||||
// struct linux_dirent64 *de;
|
||||
// struct target_dirent *tde;
|
||||
// int len = ret;
|
||||
// int tlen = 0;
|
||||
//
|
||||
// de = dirp;
|
||||
// tde = (struct target_dirent *)dirp;
|
||||
// while (len > 0) {
|
||||
// int namelen, treclen;
|
||||
// int reclen = de->d_reclen;
|
||||
// uint64_t ino = de->d_ino;
|
||||
// int64_t off = de->d_off;
|
||||
// uint8_t type = de->d_type;
|
||||
//
|
||||
// namelen = de->d_reclen - offsetof(struct linux_dirent64, d_name);
|
||||
// namelen = strnlen(de->d_name, namelen);
|
||||
// treclen = offsetof(struct target_dirent, d_name)
|
||||
// + namelen + 2;
|
||||
// treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
|
||||
//
|
||||
// memmove(tde->d_name, de->d_name, namelen + 1);
|
||||
// __put_user(ino, &tde->d_ino);
|
||||
// __put_user(off, &tde->d_off);
|
||||
// __put_user(treclen, &tde->d_reclen);
|
||||
// #if !defined TARGET_ABI_IRIX && !defined TARGET_ABI_SOLARIS
|
||||
// /* The target_dirent type is in what was formerly a padding
|
||||
// * byte at the end of the structure:
|
||||
// */
|
||||
// *(((char *)tde) + treclen - 1) = type;
|
||||
// #endif
|
||||
// de = (struct linux_dirent64 *)((char *)de + reclen);
|
||||
// tde = (struct target_dirent *)((char *)tde + treclen);
|
||||
// len -= reclen;
|
||||
// tlen += treclen;
|
||||
// }
|
||||
// ret = tlen;
|
||||
// }
|
||||
// unlock_user(dirp, arg2, ret);
|
||||
// }
|
||||
// #endif
|
||||
#ifdef TARGET_NR_ngetdents
|
||||
if (ret >= 0 && num == TARGET_NR_ngetdents) {
|
||||
abi_long *p = lock_user(VERIFY_WRITE, arg4, sizeof(abi_long), 0);
|
||||
|
@ -14484,23 +14374,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
}
|
||||
}
|
||||
break;
|
||||
case TARGET_NR_syssgi_sysid:
|
||||
{
|
||||
char * buf = lock_user(VERIFY_WRITE, arg2, 64, 0);
|
||||
if (!buf) {
|
||||
goto efault;
|
||||
case TARGET_NR_syssgi_sysid:
|
||||
{
|
||||
char * buf = lock_user(VERIFY_WRITE, arg2, 64, 0);
|
||||
if (!buf) {
|
||||
goto efault;
|
||||
}
|
||||
snprintf(buf, 64, "%12llx", 0x08006900000DULL);
|
||||
ret = 0;
|
||||
unlock_user(buf, arg2, 64);
|
||||
break;
|
||||
}
|
||||
snprintf(buf, 64, "%12llx", 0x08006900000DULL);
|
||||
case TARGET_NR_syssgi_rldenv:
|
||||
case TARGET_NR_syssgi_tosstsave:
|
||||
case TARGET_NR_syssgi_fpbcopy:
|
||||
case TARGET_NR_syssgi_getprocattr: /* ? 2nd=string 3rd=result ptr */
|
||||
ret = 0;
|
||||
unlock_user(buf, arg2, 64);
|
||||
break;
|
||||
}
|
||||
case TARGET_NR_syssgi_rldenv:
|
||||
case TARGET_NR_syssgi_tosstsave:
|
||||
case TARGET_NR_syssgi_fpbcopy:
|
||||
case TARGET_NR_syssgi_getprocattr: /* ? 2nd=string 3rd=result ptr */
|
||||
ret = 0;
|
||||
break;
|
||||
case TARGET_NR_syssgi_setgroups:
|
||||
case TARGET_NR_syssgi_getgroups:
|
||||
default:
|
||||
|
@ -14508,7 +14398,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
|||
ret = -TARGET_ENOSYS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef TARGET_NR_sginap
|
||||
|
|
|
@ -3336,6 +3336,7 @@ struct target_utsname {
|
|||
|
||||
/* wait flags */
|
||||
#define TARGET_WEXITED 0001
|
||||
#define TARGET_WTRAPPED 0002
|
||||
#define TARGET_WSTOPPED 0004
|
||||
#define TARGET_WCONTINUED 0010
|
||||
#define TARGET_WNOHANG 0100
|
||||
|
|
Loading…
Reference in New Issue