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