os-sys.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. * FreeBSD sysctl() and sysarch() system call emulation
  3. *
  4. * Copyright (c) 2013-15 Stacey D. Son
  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.h"
  21. #include "target_arch_sysarch.h"
  22. #include <sys/sysctl.h>
  23. /*
  24. * Length for the fixed length types.
  25. * 0 means variable length for strings and structures
  26. * Compare with sys/kern_sysctl.c ctl_size
  27. * Note: Not all types appear to be used in-tree.
  28. */
  29. static const int guest_ctl_size[CTLTYPE + 1] = {
  30. [CTLTYPE_INT] = sizeof(abi_int),
  31. [CTLTYPE_UINT] = sizeof(abi_uint),
  32. [CTLTYPE_LONG] = sizeof(abi_long),
  33. [CTLTYPE_ULONG] = sizeof(abi_ulong),
  34. [CTLTYPE_S8] = sizeof(int8_t),
  35. [CTLTYPE_S16] = sizeof(int16_t),
  36. [CTLTYPE_S32] = sizeof(int32_t),
  37. [CTLTYPE_S64] = sizeof(int64_t),
  38. [CTLTYPE_U8] = sizeof(uint8_t),
  39. [CTLTYPE_U16] = sizeof(uint16_t),
  40. [CTLTYPE_U32] = sizeof(uint32_t),
  41. [CTLTYPE_U64] = sizeof(uint64_t),
  42. };
  43. static const int host_ctl_size[CTLTYPE + 1] = {
  44. [CTLTYPE_INT] = sizeof(int),
  45. [CTLTYPE_UINT] = sizeof(u_int),
  46. [CTLTYPE_LONG] = sizeof(long),
  47. [CTLTYPE_ULONG] = sizeof(u_long),
  48. [CTLTYPE_S8] = sizeof(int8_t),
  49. [CTLTYPE_S16] = sizeof(int16_t),
  50. [CTLTYPE_S32] = sizeof(int32_t),
  51. [CTLTYPE_S64] = sizeof(int64_t),
  52. [CTLTYPE_U8] = sizeof(uint8_t),
  53. [CTLTYPE_U16] = sizeof(uint16_t),
  54. [CTLTYPE_U32] = sizeof(uint32_t),
  55. [CTLTYPE_U64] = sizeof(uint64_t),
  56. };
  57. #ifdef TARGET_ABI32
  58. /*
  59. * Limit the amount of available memory to be most of the 32-bit address
  60. * space. 0x100c000 was arrived at through trial and error as a good
  61. * definition of 'most'.
  62. */
  63. static const abi_ulong guest_max_mem = UINT32_MAX - 0x100c000 + 1;
  64. static abi_ulong cap_memory(uint64_t mem)
  65. {
  66. return MIN(guest_max_mem, mem);
  67. }
  68. #endif
  69. static abi_ulong scale_to_guest_pages(uint64_t pages)
  70. {
  71. /* Scale pages from host to guest */
  72. pages = muldiv64(pages, qemu_real_host_page_size(), TARGET_PAGE_SIZE);
  73. #ifdef TARGET_ABI32
  74. /* cap pages if need be */
  75. pages = MIN(pages, guest_max_mem / (abi_ulong)TARGET_PAGE_SIZE);
  76. #endif
  77. return pages;
  78. }
  79. #ifdef TARGET_ABI32
  80. /* Used only for TARGET_ABI32 */
  81. static abi_long h2g_long_sat(long l)
  82. {
  83. if (l > INT32_MAX) {
  84. l = INT32_MAX;
  85. } else if (l < INT32_MIN) {
  86. l = INT32_MIN;
  87. }
  88. return l;
  89. }
  90. static abi_ulong h2g_ulong_sat(u_long ul)
  91. {
  92. return MIN(ul, UINT32_MAX);
  93. }
  94. #endif
  95. /*
  96. * placeholder until bsd-user downstream upstreams this with its thread support
  97. */
  98. #define bsd_get_ncpu() 1
  99. /*
  100. * This uses the undocumented oidfmt interface to find the kind of a requested
  101. * sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt() (compare to
  102. * src/sbin/sysctl/sysctl.c)
  103. */
  104. static int oidfmt(int *oid, int len, char *fmt, uint32_t *kind)
  105. {
  106. int qoid[CTL_MAXNAME + 2];
  107. uint8_t buf[BUFSIZ];
  108. int i;
  109. size_t j;
  110. qoid[0] = CTL_SYSCTL;
  111. qoid[1] = CTL_SYSCTL_OIDFMT;
  112. memcpy(qoid + 2, oid, len * sizeof(int));
  113. j = sizeof(buf);
  114. i = sysctl(qoid, len + 2, buf, &j, 0, 0);
  115. if (i) {
  116. return i;
  117. }
  118. if (kind) {
  119. *kind = *(uint32_t *)buf;
  120. }
  121. if (fmt) {
  122. strcpy(fmt, (char *)(buf + sizeof(uint32_t)));
  123. }
  124. return 0;
  125. }
  126. /*
  127. * Convert the old value from host to guest.
  128. *
  129. * For LONG and ULONG on ABI32, we need to 'down convert' the 8 byte quantities
  130. * to 4 bytes. The caller setup a buffer in host memory to get this data from
  131. * the kernel and pass it to us. We do the down conversion and adjust the length
  132. * so the caller knows what to write as the returned length into the target when
  133. * it copies the down converted values into the target.
  134. *
  135. * For normal integral types, we just need to byte swap. No size changes.
  136. *
  137. * For strings and node data, there's no conversion needed.
  138. *
  139. * For opaque data, per sysctl OID converts take care of it.
  140. */
  141. static void h2g_old_sysctl(void *holdp, size_t *holdlen, uint32_t kind)
  142. {
  143. size_t len;
  144. int hlen, glen;
  145. uint8_t *hp, *gp;
  146. /*
  147. * Although rare, we can have arrays of sysctl. Both sysctl_old_ddb in
  148. * kern_sysctl.c and show_var in sbin/sysctl/sysctl.c have code that loops
  149. * this way. *holdlen has been set by the kernel to the host's length.
  150. * Only LONG and ULONG on ABI32 have different sizes: see below.
  151. */
  152. gp = hp = (uint8_t *)holdp;
  153. len = 0;
  154. hlen = host_ctl_size[kind & CTLTYPE];
  155. glen = guest_ctl_size[kind & CTLTYPE];
  156. /*
  157. * hlen == 0 for CTLTYPE_STRING and CTLTYPE_NODE, which need no conversion
  158. * as well as CTLTYPE_OPAQUE, which needs special converters.
  159. */
  160. if (hlen == 0) {
  161. return;
  162. }
  163. while (len < *holdlen) {
  164. if (hlen == glen) {
  165. switch (hlen) {
  166. case 1:
  167. /* Nothing needed: no byteswapping and assigning in place */
  168. break;
  169. case 2:
  170. *(uint16_t *)gp = tswap16(*(uint16_t *)hp);
  171. break;
  172. case 4:
  173. *(uint32_t *)gp = tswap32(*(uint32_t *)hp);
  174. break;
  175. case 8:
  176. *(uint64_t *)gp = tswap64(*(uint64_t *)hp);
  177. break;
  178. default:
  179. g_assert_not_reached();
  180. }
  181. } else {
  182. #ifdef TARGET_ABI32
  183. /*
  184. * Saturating assignment for the only two types that differ between
  185. * 32-bit and 64-bit machines. All other integral types have the
  186. * same, fixed size and will be converted w/o loss of precision
  187. * in the above switch.
  188. */
  189. switch (kind & CTLTYPE) {
  190. case CTLTYPE_LONG:
  191. *(abi_long *)gp = tswap32(h2g_long_sat(*(long *)hp));
  192. break;
  193. case CTLTYPE_ULONG:
  194. *(abi_ulong *)gp = tswap32(h2g_ulong_sat(*(u_long *)hp));
  195. break;
  196. default:
  197. g_assert_not_reached();
  198. }
  199. #else
  200. g_assert_not_reached();
  201. #endif
  202. }
  203. gp += glen;
  204. hp += hlen;
  205. len += hlen;
  206. }
  207. #ifdef TARGET_ABI32
  208. if (hlen != glen) {
  209. *holdlen = (*holdlen / hlen) * glen;
  210. }
  211. #endif
  212. }
  213. /*
  214. * Convert the undocmented name2oid sysctl data for the target.
  215. */
  216. static inline void sysctl_name2oid(uint32_t *holdp, size_t holdlen)
  217. {
  218. size_t i, num = holdlen / sizeof(uint32_t);
  219. for (i = 0; i < num; i++) {
  220. holdp[i] = tswap32(holdp[i]);
  221. }
  222. }
  223. static inline void sysctl_oidfmt(uint32_t *holdp)
  224. {
  225. /* byte swap the kind */
  226. holdp[0] = tswap32(holdp[0]);
  227. }
  228. static abi_long do_freebsd_sysctl_oid(CPUArchState *env, int32_t *snamep,
  229. int32_t namelen, void *holdp, size_t *holdlenp, void *hnewp,
  230. size_t newlen)
  231. {
  232. uint32_t kind = 0;
  233. abi_long ret;
  234. size_t holdlen, oldlen;
  235. #ifdef TARGET_ABI32
  236. void *old_holdp;
  237. #endif
  238. holdlen = oldlen = *holdlenp;
  239. oidfmt(snamep, namelen, NULL, &kind);
  240. /* Handle some arch/emulator dependent sysctl()'s here. */
  241. switch (snamep[0]) {
  242. case CTL_KERN:
  243. switch (snamep[1]) {
  244. case KERN_USRSTACK:
  245. if (oldlen) {
  246. (*(abi_ulong *)holdp) = tswapal(TARGET_USRSTACK);
  247. }
  248. holdlen = sizeof(abi_ulong);
  249. ret = 0;
  250. goto out;
  251. case KERN_PS_STRINGS:
  252. if (oldlen) {
  253. (*(abi_ulong *)holdp) = tswapal(TARGET_PS_STRINGS);
  254. }
  255. holdlen = sizeof(abi_ulong);
  256. ret = 0;
  257. goto out;
  258. default:
  259. break;
  260. }
  261. break;
  262. case CTL_HW:
  263. switch (snamep[1]) {
  264. case HW_MACHINE:
  265. holdlen = sizeof(TARGET_HW_MACHINE);
  266. if (holdp) {
  267. strlcpy(holdp, TARGET_HW_MACHINE, oldlen);
  268. }
  269. ret = 0;
  270. goto out;
  271. case HW_MACHINE_ARCH:
  272. {
  273. holdlen = sizeof(TARGET_HW_MACHINE_ARCH);
  274. if (holdp) {
  275. strlcpy(holdp, TARGET_HW_MACHINE_ARCH, oldlen);
  276. }
  277. ret = 0;
  278. goto out;
  279. }
  280. case HW_NCPU:
  281. if (oldlen) {
  282. (*(abi_int *)holdp) = tswap32(bsd_get_ncpu());
  283. }
  284. holdlen = sizeof(int32_t);
  285. ret = 0;
  286. goto out;
  287. #if defined(TARGET_ARM)
  288. case HW_FLOATINGPT:
  289. if (oldlen) {
  290. ARMCPU *cpu = env_archcpu(env);
  291. *(abi_int *)holdp = cpu_isar_feature(aa32_vfp, cpu);
  292. }
  293. holdlen = sizeof(abi_int);
  294. ret = 0;
  295. goto out;
  296. #endif
  297. #ifdef TARGET_ABI32
  298. case HW_PHYSMEM:
  299. case HW_USERMEM:
  300. case HW_REALMEM:
  301. holdlen = sizeof(abi_ulong);
  302. ret = 0;
  303. if (oldlen) {
  304. int mib[2] = {snamep[0], snamep[1]};
  305. unsigned long lvalue;
  306. size_t len = sizeof(lvalue);
  307. if (sysctl(mib, 2, &lvalue, &len, NULL, 0) == -1) {
  308. ret = -1;
  309. } else {
  310. lvalue = cap_memory(lvalue);
  311. (*(abi_ulong *)holdp) = tswapal((abi_ulong)lvalue);
  312. }
  313. }
  314. goto out;
  315. #endif
  316. default:
  317. {
  318. static int oid_hw_availpages;
  319. static int oid_hw_pagesizes;
  320. if (!oid_hw_availpages) {
  321. int real_oid[CTL_MAXNAME + 2];
  322. size_t len = sizeof(real_oid) / sizeof(int);
  323. if (sysctlnametomib("hw.availpages", real_oid, &len) >= 0) {
  324. oid_hw_availpages = real_oid[1];
  325. }
  326. }
  327. if (!oid_hw_pagesizes) {
  328. int real_oid[CTL_MAXNAME + 2];
  329. size_t len = sizeof(real_oid) / sizeof(int);
  330. if (sysctlnametomib("hw.pagesizes", real_oid, &len) >= 0) {
  331. oid_hw_pagesizes = real_oid[1];
  332. }
  333. }
  334. if (oid_hw_availpages && snamep[1] == oid_hw_availpages) {
  335. long lvalue;
  336. size_t len = sizeof(lvalue);
  337. if (sysctlbyname("hw.availpages", &lvalue, &len, NULL, 0) == -1) {
  338. ret = -1;
  339. } else {
  340. if (oldlen) {
  341. lvalue = scale_to_guest_pages(lvalue);
  342. (*(abi_ulong *)holdp) = tswapal((abi_ulong)lvalue);
  343. }
  344. holdlen = sizeof(abi_ulong);
  345. ret = 0;
  346. }
  347. goto out;
  348. }
  349. if (oid_hw_pagesizes && snamep[1] == oid_hw_pagesizes) {
  350. if (oldlen) {
  351. (*(abi_ulong *)holdp) = tswapal((abi_ulong)TARGET_PAGE_SIZE);
  352. ((abi_ulong *)holdp)[1] = 0;
  353. }
  354. holdlen = sizeof(abi_ulong) * 2;
  355. ret = 0;
  356. goto out;
  357. }
  358. break;
  359. }
  360. }
  361. break;
  362. default:
  363. break;
  364. }
  365. #ifdef TARGET_ABI32
  366. /*
  367. * For long and ulong with a 64-bit host and a 32-bit target we have to do
  368. * special things. holdlen here is the length provided by the target to the
  369. * system call. So we allocate a buffer twice as large because longs are
  370. * twice as big on the host which will be writing them. In h2g_old_sysctl
  371. * we'll adjust them and adjust the length.
  372. */
  373. if (kind == CTLTYPE_LONG || kind == CTLTYPE_ULONG) {
  374. old_holdp = holdp;
  375. holdlen = holdlen * 2;
  376. holdp = g_malloc(holdlen);
  377. }
  378. #endif
  379. ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen));
  380. if (!ret && (holdp != 0)) {
  381. if (snamep[0] == CTL_SYSCTL) {
  382. switch (snamep[1]) {
  383. case CTL_SYSCTL_NEXT:
  384. case CTL_SYSCTL_NAME2OID:
  385. case CTL_SYSCTL_NEXTNOSKIP:
  386. /*
  387. * All of these return an OID array, so we need to convert to
  388. * target.
  389. */
  390. sysctl_name2oid(holdp, holdlen);
  391. break;
  392. case CTL_SYSCTL_OIDFMT:
  393. /* Handle oidfmt */
  394. sysctl_oidfmt(holdp);
  395. break;
  396. case CTL_SYSCTL_OIDDESCR:
  397. case CTL_SYSCTL_OIDLABEL:
  398. default:
  399. /* Handle it based on the type */
  400. h2g_old_sysctl(holdp, &holdlen, kind);
  401. /* NB: None of these are LONG or ULONG */
  402. break;
  403. }
  404. } else {
  405. /*
  406. * Need to convert from host to target. All the weird special cases
  407. * are handled above.
  408. */
  409. h2g_old_sysctl(holdp, &holdlen, kind);
  410. #ifdef TARGET_ABI32
  411. /*
  412. * For the 32-bit on 64-bit case, for longs we need to copy the
  413. * now-converted buffer to the target and free the buffer.
  414. */
  415. if (kind == CTLTYPE_LONG || kind == CTLTYPE_ULONG) {
  416. memcpy(old_holdp, holdp, holdlen);
  417. g_free(holdp);
  418. holdp = old_holdp;
  419. }
  420. #endif
  421. }
  422. }
  423. out:
  424. *holdlenp = holdlen;
  425. return ret;
  426. }
  427. /*
  428. * This syscall was created to make sysctlbyname(3) more efficient, but we can't
  429. * really provide it in bsd-user. Notably, we must always translate the names
  430. * independently since some sysctl values have to be faked for the target
  431. * environment, so it still has to break down to two syscalls for the underlying
  432. * implementation.
  433. */
  434. abi_long do_freebsd_sysctlbyname(CPUArchState *env, abi_ulong namep,
  435. int32_t namelen, abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp,
  436. abi_ulong newlen)
  437. {
  438. abi_long ret = -TARGET_EFAULT;
  439. void *holdp = NULL, *hnewp = NULL;
  440. char *snamep = NULL;
  441. int oid[CTL_MAXNAME + 2];
  442. size_t holdlen, oidplen;
  443. abi_ulong oldlen = 0;
  444. /* oldlenp is read/write, pre-check here for write */
  445. if (oldlenp) {
  446. if (!access_ok(VERIFY_WRITE, oldlenp, sizeof(abi_ulong)) ||
  447. get_user_ual(oldlen, oldlenp)) {
  448. goto out;
  449. }
  450. }
  451. snamep = lock_user_string(namep);
  452. if (snamep == NULL) {
  453. goto out;
  454. }
  455. if (newp) {
  456. hnewp = lock_user(VERIFY_READ, newp, newlen, 1);
  457. if (hnewp == NULL) {
  458. goto out;
  459. }
  460. }
  461. if (oldp) {
  462. holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0);
  463. if (holdp == NULL) {
  464. goto out;
  465. }
  466. }
  467. holdlen = oldlen;
  468. oidplen = ARRAY_SIZE(oid);
  469. if (sysctlnametomib(snamep, oid, &oidplen) != 0) {
  470. ret = -TARGET_EINVAL;
  471. goto out;
  472. }
  473. ret = do_freebsd_sysctl_oid(env, oid, oidplen, holdp, &holdlen, hnewp,
  474. newlen);
  475. /*
  476. * writeability pre-checked above. __sysctl(2) returns ENOMEM and updates
  477. * oldlenp for the proper size to use.
  478. */
  479. if (oldlenp && (ret == 0 || ret == -TARGET_ENOMEM)) {
  480. put_user_ual(holdlen, oldlenp);
  481. }
  482. out:
  483. unlock_user(snamep, namep, 0);
  484. unlock_user(holdp, oldp, ret == 0 ? holdlen : 0);
  485. unlock_user(hnewp, newp, 0);
  486. return ret;
  487. }
  488. abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen,
  489. abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen)
  490. {
  491. abi_long ret = -TARGET_EFAULT;
  492. void *hnamep, *holdp = NULL, *hnewp = NULL;
  493. size_t holdlen;
  494. abi_ulong oldlen = 0;
  495. int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i;
  496. /* oldlenp is read/write, pre-check here for write */
  497. if (oldlenp) {
  498. if (!access_ok(VERIFY_WRITE, oldlenp, sizeof(abi_ulong)) ||
  499. get_user_ual(oldlen, oldlenp)) {
  500. goto out;
  501. }
  502. }
  503. hnamep = lock_user(VERIFY_READ, namep, namelen, 1);
  504. if (hnamep == NULL) {
  505. goto out;
  506. }
  507. if (newp) {
  508. hnewp = lock_user(VERIFY_READ, newp, newlen, 1);
  509. if (hnewp == NULL) {
  510. goto out;
  511. }
  512. }
  513. if (oldp) {
  514. holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0);
  515. if (holdp == NULL) {
  516. goto out;
  517. }
  518. }
  519. holdlen = oldlen;
  520. for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++, q++) {
  521. *q = tswap32(*p);
  522. }
  523. ret = do_freebsd_sysctl_oid(env, snamep, namelen, holdp, &holdlen, hnewp,
  524. newlen);
  525. /*
  526. * writeability pre-checked above. __sysctl(2) returns ENOMEM and updates
  527. * oldlenp for the proper size to use.
  528. */
  529. if (oldlenp && (ret == 0 || ret == -TARGET_ENOMEM)) {
  530. put_user_ual(holdlen, oldlenp);
  531. }
  532. unlock_user(hnamep, namep, 0);
  533. unlock_user(holdp, oldp, ret == 0 ? holdlen : 0);
  534. out:
  535. g_free(snamep);
  536. return ret;
  537. }
  538. /* sysarch() is architecture dependent. */
  539. abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2)
  540. {
  541. return do_freebsd_arch_sysarch(cpu_env, arg1, arg2);
  542. }