Skip to content

Commit eda8972

Browse files
committed
fix catalina issue of mprotect on stack memory by defaulting to mmap for darwin
1 parent 59bd2d8 commit eda8972

File tree

4 files changed

+46
-134
lines changed

4 files changed

+46
-134
lines changed

accel/tcg/translate-all.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,27 @@ static inline void *split_cross_256mb(void *buf1, size_t size1)
603603
return buf1;
604604
}
605605
#endif
606-
607606
#ifdef USE_STATIC_CODE_GEN_BUFFER
607+
#if defined(CONFIG_DARWIN_USER)
608+
static inline void *alloc_code_gen_buffer(void)
609+
{
610+
int prot = PROT_WRITE | PROT_READ | PROT_EXEC;
611+
int flags = MAP_PRIVATE | MAP_ANON;
612+
/* let a kernel pick an address close to the executable */
613+
uintptr_t start = 0;
614+
/* Honor a command-line option limiting the size of the buffer. */
615+
size_t size = DEFAULT_CODE_GEN_BUFFER_SIZE;
616+
void *buf;
617+
618+
buf = mmap((void *)start, size, prot, flags, -1, 0);
619+
if (buf == MAP_FAILED) {
620+
return NULL;
621+
}
622+
623+
qemu_madvise(buf, size, QEMU_MADV_HUGEPAGE);
624+
return buf;
625+
}
626+
#else /* !CONFIG_DARWIN_USER */
608627
static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE]
609628
__attribute__((aligned(CODE_GEN_ALIGN)));
610629

@@ -641,6 +660,8 @@ static inline void *alloc_code_gen_buffer(void)
641660

642661
return buf;
643662
}
663+
#endif /* CONFIG_DARWIN_USER */
664+
644665
#elif defined(_WIN32)
645666
static inline void *alloc_code_gen_buffer(void)
646667
{

darwin-user/irix/target_syscall.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct target_dirent {
4141
char d_name[1];
4242
};
4343
/* size of struct target_dirent without the name array */
44-
#define target_dirent_len (offsetof(struct target_dirent, d_name))
44+
#define TARGET_DIRENT_LEN (offsetof(struct target_dirent, d_name))
4545

4646
/* IRIX sys/types.h */
4747
typedef uint64_t target_ino64_t;

darwin-user/syscall.c

Lines changed: 22 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -10806,25 +10806,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
1080610806
case TARGET_NR_getdents:
1080710807
{
1080810808
struct target_dirent *target_dirp;
10809-
struct dirent *host_dirp;
1081010809
DIR *dirp;
1081110810
abi_long dir_fd = arg1;
1081210811
abi_long count = arg3;
10813-
int found_err = FALSE;
10814-
// ret == bytes read, or target error code
10812+
10813+
// ret == >0 => bytes read
10814+
// 0 => end of directory
10815+
// <0 => -(target errno)
1081510816

1081610817
dirp = fdopendir(dir_fd);
1081710818
if (!dirp) {
1081810819
ret = -host_to_target_errno(errno);
1081910820
goto fail;
1082010821
}
1082110822

10822-
host_dirp = g_try_malloc(count);
10823-
if (!host_dirp) {
10824-
ret = -TARGET_ENOMEM;
10825-
goto fail;
10826-
}
10827-
1082810823
// collect readdir calls into getdents dirp * buffer
1082910824
target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
1083010825
if (!target_dirp) {
@@ -10837,10 +10832,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
1083710832
uint target_reclen;
1083810833
uint name_len;
1083910834

10835+
errno = 0;
1084010836
while ((de = readdir(dirp))) {
1084110837
// check if new entry will overflow the target buffer
1084210838
name_len = de->d_namlen + 1;
10843-
target_reclen = target_dirent_len + name_len;
10839+
target_reclen = TARGET_DIRENT_LEN + name_len;
1084410840
// is this the correct way to align this structure..?
1084510841
target_reclen = QEMU_ALIGN_UP(target_reclen, __alignof(struct target_dirent));
1084610842
if (bytes_used + target_reclen > count) {
@@ -10857,7 +10853,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
1085710853
bytes_used += target_reclen;
1085810854
}
1085910855

10860-
if (found_err) {
10856+
if (errno != 0) {
1086110857
ret = -host_to_target_errno(errno);
1086210858
} else {
1086310859
ret = bytes_used;
@@ -10867,112 +10863,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
1086710863
// which was used in `fdopendir`
1086810864
// closedir(dirp);
1086910865
}
10870-
// Old Linux code
10871-
// #ifdef __NR_getdents
10872-
// {
10873-
// struct target_dirent *target_dirp;
10874-
// struct linux_dirent *dirp;
10875-
// abi_long count = arg3;
10876-
//
10877-
// dirp = g_try_malloc(count);
10878-
// if (!dirp) {
10879-
// ret = -TARGET_ENOMEM;
10880-
// goto fail;
10881-
// }
10882-
//
10883-
// ret = get_errno(sys_getdents(arg1, dirp, count));
10884-
// if (!is_error(ret)) {
10885-
// struct linux_dirent *de;
10886-
// struct target_dirent *tde;
10887-
// int len = ret;
10888-
// int reclen, treclen;
10889-
// int count1, tnamelen;
10890-
//
10891-
// count1 = 0;
10892-
// de = dirp;
10893-
// if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
10894-
// goto efault;
10895-
// tde = target_dirp;
10896-
// while (len > 0) {
10897-
// reclen = de->d_reclen;
10898-
// tnamelen = reclen - offsetof(struct linux_dirent, d_name);
10899-
// tnamelen = strnlen(de->d_name, tnamelen) + 1;
10900-
// assert(tnamelen >= 0);
10901-
// treclen = tnamelen + offsetof(struct target_dirent, d_name);
10902-
// /* XXX: avoid buffer overflow, for the price of lost entries */
10903-
// if (count1 + treclen > count)
10904-
// break;
10905-
// __put_user(treclen, &tde->d_reclen);
10906-
// __put_user(de->d_ino, &tde->d_ino);
10907-
// __put_user(de->d_off, &tde->d_off);
10908-
// memcpy(tde->d_name, de->d_name, tnamelen);
10909-
// de = (struct linux_dirent *)((char *)de + reclen);
10910-
// len -= reclen;
10911-
// tde = (struct target_dirent *)((char *)tde + treclen);
10912-
// count1 += treclen;
10913-
// }
10914-
// ret = count1;
10915-
// unlock_user(target_dirp, arg2, ret);
10916-
// }
10917-
// g_free(dirp);
10918-
// }
10919-
// #else
10920-
// /* Implement getdents in terms of getdents64 */
10921-
// {
10922-
// struct linux_dirent64 *dirp;
10923-
// abi_long count = arg3;
10924-
//
10925-
// dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
10926-
// if (!dirp) {
10927-
// goto efault;
10928-
// }
10929-
// ret = get_errno(sys_getdents64(arg1, dirp, count));
10930-
// if (!is_error(ret)) {
10931-
// /* Convert the dirent64 structs to target dirent. We do this
10932-
// * in-place, since we can guarantee that a target_dirent is no
10933-
// * larger than a dirent64; however this means we have to be
10934-
// * careful to read everything before writing in the new format.
10935-
// */
10936-
// struct linux_dirent64 *de;
10937-
// struct target_dirent *tde;
10938-
// int len = ret;
10939-
// int tlen = 0;
10940-
//
10941-
// de = dirp;
10942-
// tde = (struct target_dirent *)dirp;
10943-
// while (len > 0) {
10944-
// int namelen, treclen;
10945-
// int reclen = de->d_reclen;
10946-
// uint64_t ino = de->d_ino;
10947-
// int64_t off = de->d_off;
10948-
// uint8_t type = de->d_type;
10949-
//
10950-
// namelen = de->d_reclen - offsetof(struct linux_dirent64, d_name);
10951-
// namelen = strnlen(de->d_name, namelen);
10952-
// treclen = offsetof(struct target_dirent, d_name)
10953-
// + namelen + 2;
10954-
// treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
10955-
//
10956-
// memmove(tde->d_name, de->d_name, namelen + 1);
10957-
// __put_user(ino, &tde->d_ino);
10958-
// __put_user(off, &tde->d_off);
10959-
// __put_user(treclen, &tde->d_reclen);
10960-
// #if !defined TARGET_ABI_IRIX && !defined TARGET_ABI_SOLARIS
10961-
// /* The target_dirent type is in what was formerly a padding
10962-
// * byte at the end of the structure:
10963-
// */
10964-
// *(((char *)tde) + treclen - 1) = type;
10965-
// #endif
10966-
// de = (struct linux_dirent64 *)((char *)de + reclen);
10967-
// tde = (struct target_dirent *)((char *)tde + treclen);
10968-
// len -= reclen;
10969-
// tlen += treclen;
10970-
// }
10971-
// ret = tlen;
10972-
// }
10973-
// unlock_user(dirp, arg2, ret);
10974-
// }
10975-
// #endif
1097610866
#ifdef TARGET_NR_ngetdents
1097710867
if (ret >= 0 && num == TARGET_NR_ngetdents) {
1097810868
abi_long *p = lock_user(VERIFY_WRITE, arg4, sizeof(abi_long), 0);
@@ -14484,31 +14374,31 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
1448414374
}
1448514375
}
1448614376
break;
14487-
case TARGET_NR_syssgi_sysid:
14488-
{
14489-
char * buf = lock_user(VERIFY_WRITE, arg2, 64, 0);
14490-
if (!buf) {
14491-
goto efault;
14377+
case TARGET_NR_syssgi_sysid:
14378+
{
14379+
char * buf = lock_user(VERIFY_WRITE, arg2, 64, 0);
14380+
if (!buf) {
14381+
goto efault;
14382+
}
14383+
snprintf(buf, 64, "%12llx", 0x08006900000DULL);
14384+
ret = 0;
14385+
unlock_user(buf, arg2, 64);
14386+
break;
1449214387
}
14493-
snprintf(buf, 64, "%12llx", 0x08006900000DULL);
14388+
case TARGET_NR_syssgi_rldenv:
14389+
case TARGET_NR_syssgi_tosstsave:
14390+
case TARGET_NR_syssgi_fpbcopy:
14391+
case TARGET_NR_syssgi_getprocattr: /* ? 2nd=string 3rd=result ptr */
1449414392
ret = 0;
14495-
unlock_user(buf, arg2, 64);
1449614393
break;
14497-
}
14498-
case TARGET_NR_syssgi_rldenv:
14499-
case TARGET_NR_syssgi_tosstsave:
14500-
case TARGET_NR_syssgi_fpbcopy:
14501-
case TARGET_NR_syssgi_getprocattr: /* ? 2nd=string 3rd=result ptr */
14502-
ret = 0;
14503-
break;
1450414394
case TARGET_NR_syssgi_setgroups:
1450514395
case TARGET_NR_syssgi_getgroups:
1450614396
default:
1450714397
gemu_log("qemu: Unsupported syscall: sgisys(%d)\n", (int)arg1);
1450814398
ret = -TARGET_ENOSYS;
1450914399
break;
1451014400
}
14511-
break;
14401+
break;
1451214402
}
1451314403
#endif
1451414404
#ifdef TARGET_NR_sginap

darwin-user/syscall_defs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3336,6 +3336,7 @@ struct target_utsname {
33363336

33373337
/* wait flags */
33383338
#define TARGET_WEXITED 0001
3339+
#define TARGET_WTRAPPED 0002
33393340
#define TARGET_WSTOPPED 0004
33403341
#define TARGET_WCONTINUED 0010
33413342
#define TARGET_WNOHANG 0100

0 commit comments

Comments
 (0)