* This is used from various compatibility syscalls too. That's why name * must be in kernel space. */
| 2361 | * must be in kernel space. |
| 2362 | */ |
| 2363 | int |
| 2364 | userland_sysctl(struct thread *td, int *name, u_int namelen, void *old, |
| 2365 | size_t *oldlenp, int inkernel, const void *new, size_t newlen, |
| 2366 | size_t *retval, int flags) |
| 2367 | { |
| 2368 | int error = 0, memlocked; |
| 2369 | struct sysctl_req req; |
| 2370 | |
| 2371 | bzero(&req, sizeof req); |
| 2372 | |
| 2373 | req.td = td; |
| 2374 | req.flags = flags; |
| 2375 | |
| 2376 | if (oldlenp) { |
| 2377 | if (inkernel) { |
| 2378 | req.oldlen = *oldlenp; |
| 2379 | } else { |
| 2380 | error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp)); |
| 2381 | if (error) |
| 2382 | return (error); |
| 2383 | } |
| 2384 | } |
| 2385 | req.validlen = req.oldlen; |
| 2386 | req.oldptr = old; |
| 2387 | |
| 2388 | if (new != NULL) { |
| 2389 | req.newlen = newlen; |
| 2390 | req.newptr = new; |
| 2391 | } |
| 2392 | |
| 2393 | req.oldfunc = sysctl_old_user; |
| 2394 | req.newfunc = sysctl_new_user; |
| 2395 | req.lock = REQ_UNWIRED; |
| 2396 | |
| 2397 | #ifdef KTRACE |
| 2398 | if (KTRPOINT(curthread, KTR_SYSCTL)) |
| 2399 | ktrsysctl(name, namelen); |
| 2400 | #endif |
| 2401 | memlocked = 0; |
| 2402 | if (req.oldptr && req.oldlen > 4 * PAGE_SIZE) { |
| 2403 | memlocked = 1; |
| 2404 | sx_xlock(&sysctlmemlock); |
| 2405 | } |
| 2406 | CURVNET_SET(TD_TO_VNET(td)); |
| 2407 | |
| 2408 | for (;;) { |
| 2409 | req.oldidx = 0; |
| 2410 | req.newidx = 0; |
| 2411 | error = sysctl_root(0, name, namelen, &req); |
| 2412 | if (error != EAGAIN) |
| 2413 | break; |
| 2414 | kern_yield(PRI_USER); |
| 2415 | } |
| 2416 | |
| 2417 | CURVNET_RESTORE(); |
| 2418 | |
| 2419 | if (req.lock == REQ_WIRED && req.validlen > 0) |
| 2420 | vsunlock(req.oldptr, req.validlen); |
no test coverage detected