syscall.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*
  2. * BSD syscalls
  3. *
  4. * Copyright (c) 2003 - 2008 Fabrice Bellard
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "qemu/osdep.h"
  20. #include "qemu/cutils.h"
  21. #include "qemu/path.h"
  22. #include <sys/syscall.h>
  23. #include <sys/param.h>
  24. #include <sys/sysctl.h>
  25. #include <utime.h>
  26. #include "qemu.h"
  27. #include "qemu-common.h"
  28. #include "user/syscall-trace.h"
  29. //#define DEBUG
  30. static abi_ulong target_brk;
  31. static abi_ulong target_original_brk;
  32. static inline abi_long get_errno(abi_long ret)
  33. {
  34. if (ret == -1)
  35. /* XXX need to translate host -> target errnos here */
  36. return -(errno);
  37. else
  38. return ret;
  39. }
  40. #define target_to_host_bitmask(x, tbl) (x)
  41. static inline int is_error(abi_long ret)
  42. {
  43. return (abi_ulong)ret >= (abi_ulong)(-4096);
  44. }
  45. void target_set_brk(abi_ulong new_brk)
  46. {
  47. target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
  48. }
  49. /* do_obreak() must return target errnos. */
  50. static abi_long do_obreak(abi_ulong new_brk)
  51. {
  52. abi_ulong brk_page;
  53. abi_long mapped_addr;
  54. int new_alloc_size;
  55. if (!new_brk)
  56. return 0;
  57. if (new_brk < target_original_brk)
  58. return -TARGET_EINVAL;
  59. brk_page = HOST_PAGE_ALIGN(target_brk);
  60. /* If the new brk is less than this, set it and we're done... */
  61. if (new_brk < brk_page) {
  62. target_brk = new_brk;
  63. return 0;
  64. }
  65. /* We need to allocate more memory after the brk... */
  66. new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
  67. mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
  68. PROT_READ|PROT_WRITE,
  69. MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0));
  70. if (!is_error(mapped_addr))
  71. target_brk = new_brk;
  72. else
  73. return mapped_addr;
  74. return 0;
  75. }
  76. #if defined(TARGET_I386)
  77. static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms)
  78. {
  79. abi_long ret = 0;
  80. abi_ulong val;
  81. int idx;
  82. switch(op) {
  83. #ifdef TARGET_ABI32
  84. case TARGET_FREEBSD_I386_SET_GSBASE:
  85. case TARGET_FREEBSD_I386_SET_FSBASE:
  86. if (op == TARGET_FREEBSD_I386_SET_GSBASE)
  87. #else
  88. case TARGET_FREEBSD_AMD64_SET_GSBASE:
  89. case TARGET_FREEBSD_AMD64_SET_FSBASE:
  90. if (op == TARGET_FREEBSD_AMD64_SET_GSBASE)
  91. #endif
  92. idx = R_GS;
  93. else
  94. idx = R_FS;
  95. if (get_user(val, parms, abi_ulong))
  96. return -TARGET_EFAULT;
  97. cpu_x86_load_seg(env, idx, 0);
  98. env->segs[idx].base = val;
  99. break;
  100. #ifdef TARGET_ABI32
  101. case TARGET_FREEBSD_I386_GET_GSBASE:
  102. case TARGET_FREEBSD_I386_GET_FSBASE:
  103. if (op == TARGET_FREEBSD_I386_GET_GSBASE)
  104. #else
  105. case TARGET_FREEBSD_AMD64_GET_GSBASE:
  106. case TARGET_FREEBSD_AMD64_GET_FSBASE:
  107. if (op == TARGET_FREEBSD_AMD64_GET_GSBASE)
  108. #endif
  109. idx = R_GS;
  110. else
  111. idx = R_FS;
  112. val = env->segs[idx].base;
  113. if (put_user(val, parms, abi_ulong))
  114. return -TARGET_EFAULT;
  115. break;
  116. /* XXX handle the others... */
  117. default:
  118. ret = -TARGET_EINVAL;
  119. break;
  120. }
  121. return ret;
  122. }
  123. #endif
  124. #ifdef TARGET_SPARC
  125. static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
  126. {
  127. /* XXX handle
  128. * TARGET_FREEBSD_SPARC_UTRAP_INSTALL,
  129. * TARGET_FREEBSD_SPARC_SIGTRAMP_INSTALL
  130. */
  131. return -TARGET_EINVAL;
  132. }
  133. #endif
  134. #ifdef __FreeBSD__
  135. /*
  136. * XXX this uses the undocumented oidfmt interface to find the kind of
  137. * a requested sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt()
  138. * (this is mostly copied from src/sbin/sysctl/sysctl.c)
  139. */
  140. static int
  141. oidfmt(int *oid, int len, char *fmt, uint32_t *kind)
  142. {
  143. int qoid[CTL_MAXNAME+2];
  144. uint8_t buf[BUFSIZ];
  145. int i;
  146. size_t j;
  147. qoid[0] = 0;
  148. qoid[1] = 4;
  149. memcpy(qoid + 2, oid, len * sizeof(int));
  150. j = sizeof(buf);
  151. i = sysctl(qoid, len + 2, buf, &j, 0, 0);
  152. if (i)
  153. return i;
  154. if (kind)
  155. *kind = *(uint32_t *)buf;
  156. if (fmt)
  157. strcpy(fmt, (char *)(buf + sizeof(uint32_t)));
  158. return (0);
  159. }
  160. /*
  161. * try and convert sysctl return data for the target.
  162. * XXX doesn't handle CTLTYPE_OPAQUE and CTLTYPE_STRUCT.
  163. */
  164. static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind)
  165. {
  166. switch (kind & CTLTYPE) {
  167. case CTLTYPE_INT:
  168. case CTLTYPE_UINT:
  169. *(uint32_t *)holdp = tswap32(*(uint32_t *)holdp);
  170. break;
  171. #ifdef TARGET_ABI32
  172. case CTLTYPE_LONG:
  173. case CTLTYPE_ULONG:
  174. *(uint32_t *)holdp = tswap32(*(long *)holdp);
  175. break;
  176. #else
  177. case CTLTYPE_LONG:
  178. *(uint64_t *)holdp = tswap64(*(long *)holdp);
  179. case CTLTYPE_ULONG:
  180. *(uint64_t *)holdp = tswap64(*(unsigned long *)holdp);
  181. break;
  182. #endif
  183. #ifdef CTLTYPE_U64
  184. case CTLTYPE_S64:
  185. case CTLTYPE_U64:
  186. #else
  187. case CTLTYPE_QUAD:
  188. #endif
  189. *(uint64_t *)holdp = tswap64(*(uint64_t *)holdp);
  190. break;
  191. case CTLTYPE_STRING:
  192. break;
  193. default:
  194. /* XXX unhandled */
  195. return -1;
  196. }
  197. return 0;
  198. }
  199. /* XXX this needs to be emulated on non-FreeBSD hosts... */
  200. static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong oldp,
  201. abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen)
  202. {
  203. abi_long ret;
  204. void *hnamep, *holdp, *hnewp = NULL;
  205. size_t holdlen;
  206. abi_ulong oldlen = 0;
  207. int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i;
  208. uint32_t kind = 0;
  209. if (oldlenp)
  210. get_user_ual(oldlen, oldlenp);
  211. if (!(hnamep = lock_user(VERIFY_READ, namep, namelen, 1)))
  212. return -TARGET_EFAULT;
  213. if (newp && !(hnewp = lock_user(VERIFY_READ, newp, newlen, 1)))
  214. return -TARGET_EFAULT;
  215. if (!(holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0)))
  216. return -TARGET_EFAULT;
  217. holdlen = oldlen;
  218. for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++)
  219. *q++ = tswap32(*p);
  220. oidfmt(snamep, namelen, NULL, &kind);
  221. /* XXX swap hnewp */
  222. ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen));
  223. if (!ret)
  224. sysctl_oldcvt(holdp, holdlen, kind);
  225. put_user_ual(holdlen, oldlenp);
  226. unlock_user(hnamep, namep, 0);
  227. unlock_user(holdp, oldp, holdlen);
  228. if (hnewp)
  229. unlock_user(hnewp, newp, 0);
  230. g_free(snamep);
  231. return ret;
  232. }
  233. #endif
  234. /* FIXME
  235. * lock_iovec()/unlock_iovec() have a return code of 0 for success where
  236. * other lock functions have a return code of 0 for failure.
  237. */
  238. static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
  239. int count, int copy)
  240. {
  241. struct target_iovec *target_vec;
  242. abi_ulong base;
  243. int i;
  244. target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
  245. if (!target_vec)
  246. return -TARGET_EFAULT;
  247. for(i = 0;i < count; i++) {
  248. base = tswapl(target_vec[i].iov_base);
  249. vec[i].iov_len = tswapl(target_vec[i].iov_len);
  250. if (vec[i].iov_len != 0) {
  251. vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
  252. /* Don't check lock_user return value. We must call writev even
  253. if a element has invalid base address. */
  254. } else {
  255. /* zero length pointer is ignored */
  256. vec[i].iov_base = NULL;
  257. }
  258. }
  259. unlock_user (target_vec, target_addr, 0);
  260. return 0;
  261. }
  262. static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
  263. int count, int copy)
  264. {
  265. struct target_iovec *target_vec;
  266. abi_ulong base;
  267. int i;
  268. target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
  269. if (!target_vec)
  270. return -TARGET_EFAULT;
  271. for(i = 0;i < count; i++) {
  272. if (target_vec[i].iov_base) {
  273. base = tswapl(target_vec[i].iov_base);
  274. unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
  275. }
  276. }
  277. unlock_user (target_vec, target_addr, 0);
  278. return 0;
  279. }
  280. /* do_syscall() should always have a single exit point at the end so
  281. that actions, such as logging of syscall results, can be performed.
  282. All errnos that do_syscall() returns must be -TARGET_<errcode>. */
  283. abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
  284. abi_long arg2, abi_long arg3, abi_long arg4,
  285. abi_long arg5, abi_long arg6, abi_long arg7,
  286. abi_long arg8)
  287. {
  288. CPUState *cpu = env_cpu(cpu_env);
  289. abi_long ret;
  290. void *p;
  291. #ifdef DEBUG
  292. gemu_log("freebsd syscall %d\n", num);
  293. #endif
  294. record_syscall_start(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, 0, 0);
  295. if(do_strace)
  296. print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
  297. switch(num) {
  298. case TARGET_FREEBSD_NR_exit:
  299. #ifdef TARGET_GPROF
  300. _mcleanup();
  301. #endif
  302. gdb_exit(cpu_env, arg1);
  303. qemu_plugin_atexit_cb();
  304. /* XXX: should free thread stack and CPU env */
  305. _exit(arg1);
  306. ret = 0; /* avoid warning */
  307. break;
  308. case TARGET_FREEBSD_NR_read:
  309. if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
  310. goto efault;
  311. ret = get_errno(read(arg1, p, arg3));
  312. unlock_user(p, arg2, ret);
  313. break;
  314. case TARGET_FREEBSD_NR_write:
  315. if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
  316. goto efault;
  317. ret = get_errno(write(arg1, p, arg3));
  318. unlock_user(p, arg2, 0);
  319. break;
  320. case TARGET_FREEBSD_NR_writev:
  321. {
  322. int count = arg3;
  323. struct iovec *vec;
  324. vec = alloca(count * sizeof(struct iovec));
  325. if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
  326. goto efault;
  327. ret = get_errno(writev(arg1, vec, count));
  328. unlock_iovec(vec, arg2, count, 0);
  329. }
  330. break;
  331. case TARGET_FREEBSD_NR_open:
  332. if (!(p = lock_user_string(arg1)))
  333. goto efault;
  334. ret = get_errno(open(path(p),
  335. target_to_host_bitmask(arg2, fcntl_flags_tbl),
  336. arg3));
  337. unlock_user(p, arg1, 0);
  338. break;
  339. case TARGET_FREEBSD_NR_mmap:
  340. ret = get_errno(target_mmap(arg1, arg2, arg3,
  341. target_to_host_bitmask(arg4, mmap_flags_tbl),
  342. arg5,
  343. arg6));
  344. break;
  345. case TARGET_FREEBSD_NR_mprotect:
  346. ret = get_errno(target_mprotect(arg1, arg2, arg3));
  347. break;
  348. case TARGET_FREEBSD_NR_break:
  349. ret = do_obreak(arg1);
  350. break;
  351. #ifdef __FreeBSD__
  352. case TARGET_FREEBSD_NR___sysctl:
  353. ret = do_freebsd_sysctl(arg1, arg2, arg3, arg4, arg5, arg6);
  354. break;
  355. #endif
  356. case TARGET_FREEBSD_NR_sysarch:
  357. ret = do_freebsd_sysarch(cpu_env, arg1, arg2);
  358. break;
  359. case TARGET_FREEBSD_NR_syscall:
  360. case TARGET_FREEBSD_NR___syscall:
  361. ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,arg7,arg8,0);
  362. break;
  363. default:
  364. ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
  365. break;
  366. }
  367. fail:
  368. #ifdef DEBUG
  369. gemu_log(" = %ld\n", ret);
  370. #endif
  371. if (do_strace)
  372. print_freebsd_syscall_ret(num, ret);
  373. record_syscall_return(cpu, num, ret);
  374. return ret;
  375. efault:
  376. ret = -TARGET_EFAULT;
  377. goto fail;
  378. }
  379. abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
  380. abi_long arg2, abi_long arg3, abi_long arg4,
  381. abi_long arg5, abi_long arg6)
  382. {
  383. CPUState *cpu = env_cpu(cpu_env);
  384. abi_long ret;
  385. void *p;
  386. #ifdef DEBUG
  387. gemu_log("netbsd syscall %d\n", num);
  388. #endif
  389. record_syscall_start(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, 0, 0);
  390. if(do_strace)
  391. print_netbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
  392. switch(num) {
  393. case TARGET_NETBSD_NR_exit:
  394. #ifdef TARGET_GPROF
  395. _mcleanup();
  396. #endif
  397. gdb_exit(cpu_env, arg1);
  398. qemu_plugin_atexit_cb();
  399. /* XXX: should free thread stack and CPU env */
  400. _exit(arg1);
  401. ret = 0; /* avoid warning */
  402. break;
  403. case TARGET_NETBSD_NR_read:
  404. if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
  405. goto efault;
  406. ret = get_errno(read(arg1, p, arg3));
  407. unlock_user(p, arg2, ret);
  408. break;
  409. case TARGET_NETBSD_NR_write:
  410. if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
  411. goto efault;
  412. ret = get_errno(write(arg1, p, arg3));
  413. unlock_user(p, arg2, 0);
  414. break;
  415. case TARGET_NETBSD_NR_open:
  416. if (!(p = lock_user_string(arg1)))
  417. goto efault;
  418. ret = get_errno(open(path(p),
  419. target_to_host_bitmask(arg2, fcntl_flags_tbl),
  420. arg3));
  421. unlock_user(p, arg1, 0);
  422. break;
  423. case TARGET_NETBSD_NR_mmap:
  424. ret = get_errno(target_mmap(arg1, arg2, arg3,
  425. target_to_host_bitmask(arg4, mmap_flags_tbl),
  426. arg5,
  427. arg6));
  428. break;
  429. case TARGET_NETBSD_NR_mprotect:
  430. ret = get_errno(target_mprotect(arg1, arg2, arg3));
  431. break;
  432. case TARGET_NETBSD_NR_syscall:
  433. case TARGET_NETBSD_NR___syscall:
  434. ret = do_netbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
  435. break;
  436. default:
  437. ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
  438. break;
  439. }
  440. fail:
  441. #ifdef DEBUG
  442. gemu_log(" = %ld\n", ret);
  443. #endif
  444. if (do_strace)
  445. print_netbsd_syscall_ret(num, ret);
  446. record_syscall_return(cpu, num, ret);
  447. return ret;
  448. efault:
  449. ret = -TARGET_EFAULT;
  450. goto fail;
  451. }
  452. abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
  453. abi_long arg2, abi_long arg3, abi_long arg4,
  454. abi_long arg5, abi_long arg6)
  455. {
  456. CPUState *cpu = env_cpu(cpu_env);
  457. abi_long ret;
  458. void *p;
  459. #ifdef DEBUG
  460. gemu_log("openbsd syscall %d\n", num);
  461. #endif
  462. record_syscall_start(cpu, num, arg1, arg2, arg3, arg4, arg5, arg6, 0, 0);
  463. if(do_strace)
  464. print_openbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
  465. switch(num) {
  466. case TARGET_OPENBSD_NR_exit:
  467. #ifdef TARGET_GPROF
  468. _mcleanup();
  469. #endif
  470. gdb_exit(cpu_env, arg1);
  471. qemu_plugin_atexit_cb();
  472. /* XXX: should free thread stack and CPU env */
  473. _exit(arg1);
  474. ret = 0; /* avoid warning */
  475. break;
  476. case TARGET_OPENBSD_NR_read:
  477. if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
  478. goto efault;
  479. ret = get_errno(read(arg1, p, arg3));
  480. unlock_user(p, arg2, ret);
  481. break;
  482. case TARGET_OPENBSD_NR_write:
  483. if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
  484. goto efault;
  485. ret = get_errno(write(arg1, p, arg3));
  486. unlock_user(p, arg2, 0);
  487. break;
  488. case TARGET_OPENBSD_NR_open:
  489. if (!(p = lock_user_string(arg1)))
  490. goto efault;
  491. ret = get_errno(open(path(p),
  492. target_to_host_bitmask(arg2, fcntl_flags_tbl),
  493. arg3));
  494. unlock_user(p, arg1, 0);
  495. break;
  496. case TARGET_OPENBSD_NR_mmap:
  497. ret = get_errno(target_mmap(arg1, arg2, arg3,
  498. target_to_host_bitmask(arg4, mmap_flags_tbl),
  499. arg5,
  500. arg6));
  501. break;
  502. case TARGET_OPENBSD_NR_mprotect:
  503. ret = get_errno(target_mprotect(arg1, arg2, arg3));
  504. break;
  505. case TARGET_OPENBSD_NR_syscall:
  506. case TARGET_OPENBSD_NR___syscall:
  507. ret = do_openbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
  508. break;
  509. default:
  510. ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
  511. break;
  512. }
  513. fail:
  514. #ifdef DEBUG
  515. gemu_log(" = %ld\n", ret);
  516. #endif
  517. if (do_strace)
  518. print_openbsd_syscall_ret(num, ret);
  519. record_syscall_return(cpu, num, ret);
  520. return ret;
  521. efault:
  522. ret = -TARGET_EFAULT;
  523. goto fail;
  524. }
  525. void syscall_init(void)
  526. {
  527. }