1 /* $NetBSD: kern_sysctl.c,v 1.118 2002/11/24 11:37:56 scw Exp $ */ 2 3 /*- 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Mike Karels at Berkeley Software Design, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_sysctl.c 8.9 (Berkeley) 5/20/95 39 */ 40 41 /* 42 * sysctl system call. 43 */ 44 45 #include <sys/cdefs.h> 46 __KERNEL_RCSID(0, "$NetBSD: kern_sysctl.c,v 1.118 2002/11/24 11:37:56 scw Exp $"); 47 48 #include "opt_ddb.h" 49 #include "opt_insecure.h" 50 #include "opt_defcorename.h" 51 #include "opt_pipe.h" 52 #include "opt_sysv.h" 53 #include "pty.h" 54 #include "rnd.h" 55 56 #include <sys/param.h> 57 #include <sys/systm.h> 58 #include <sys/kernel.h> 59 #include <sys/buf.h> 60 #include <sys/device.h> 61 #include <sys/disklabel.h> 62 #include <sys/dkstat.h> 63 #include <sys/exec.h> 64 #include <sys/file.h> 65 #include <sys/ioctl.h> 66 #include <sys/malloc.h> 67 #include <sys/mount.h> 68 #include <sys/msgbuf.h> 69 #include <sys/pool.h> 70 #include <sys/proc.h> 71 #include <sys/resource.h> 72 #include <sys/resourcevar.h> 73 #include <sys/syscallargs.h> 74 #include <sys/tty.h> 75 #include <sys/unistd.h> 76 #include <sys/vnode.h> 77 #include <sys/socketvar.h> 78 #define __SYSCTL_PRIVATE 79 #include <sys/sysctl.h> 80 #include <sys/lock.h> 81 #include <sys/namei.h> 82 83 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 84 #include <sys/ipc.h> 85 #endif 86 #ifdef SYSVMSG 87 #include <sys/msg.h> 88 #endif 89 #ifdef SYSVSEM 90 #include <sys/sem.h> 91 #endif 92 #ifdef SYSVSHM 93 #include <sys/shm.h> 94 #endif 95 96 #include <dev/cons.h> 97 98 #if defined(DDB) 99 #include <ddb/ddbvar.h> 100 #endif 101 102 #ifndef PIPE_SOCKETPAIR 103 #include <sys/pipe.h> 104 #endif 105 106 #if NRND > 0 107 #include <sys/rnd.h> 108 #endif 109 110 #define PTRTOINT64(foo) ((u_int64_t)(uintptr_t)(foo)) 111 112 static int sysctl_file(void *, size_t *); 113 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 114 static int sysctl_sysvipc(int *, u_int, void *, size_t *); 115 #endif 116 static int sysctl_msgbuf(void *, size_t *); 117 static int sysctl_doeproc(int *, u_int, void *, size_t *); 118 static int sysctl_dotkstat(int *, u_int, void *, size_t *, void *); 119 #ifdef MULTIPROCESSOR 120 static int sysctl_docptime(void *, size_t *, void *); 121 static int sysctl_ncpus(void); 122 #endif 123 static void fill_kproc2(struct proc *, struct kinfo_proc2 *); 124 static int sysctl_procargs(int *, u_int, void *, size_t *, struct proc *); 125 #if NPTY > 0 126 static int sysctl_pty(void *, size_t *, void *, size_t); 127 #endif 128 129 /* 130 * The `sysctl_memlock' is intended to keep too many processes from 131 * locking down memory by doing sysctls at once. Whether or not this 132 * is really a good idea to worry about it probably a subject of some 133 * debate. 134 */ 135 struct lock sysctl_memlock; 136 137 void 138 sysctl_init(void) 139 { 140 141 lockinit(&sysctl_memlock, PRIBIO|PCATCH, "sysctl", 0, 0); 142 } 143 144 int 145 sys___sysctl(struct proc *p, void *v, register_t *retval) 146 { 147 struct sys___sysctl_args /* { 148 syscallarg(int *) name; 149 syscallarg(u_int) namelen; 150 syscallarg(void *) old; 151 syscallarg(size_t *) oldlenp; 152 syscallarg(void *) new; 153 syscallarg(size_t) newlen; 154 } */ *uap = v; 155 int error; 156 size_t savelen = 0, oldlen = 0; 157 sysctlfn *fn; 158 int name[CTL_MAXNAME]; 159 size_t *oldlenp; 160 161 /* 162 * all top-level sysctl names are non-terminal 163 */ 164 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) 165 return (EINVAL); 166 error = copyin(SCARG(uap, name), &name, 167 SCARG(uap, namelen) * sizeof(int)); 168 if (error) 169 return (error); 170 171 /* 172 * For all but CTL_PROC, must be root to change a value. 173 * For CTL_PROC, must be root, or owner of the proc (and not suid), 174 * this is checked in proc_sysctl() (once we know the targer proc). 175 */ 176 if (SCARG(uap, new) != NULL && name[0] != CTL_PROC && 177 (error = suser(p->p_ucred, &p->p_acflag))) 178 return error; 179 180 switch (name[0]) { 181 case CTL_KERN: 182 fn = kern_sysctl; 183 break; 184 case CTL_HW: 185 fn = hw_sysctl; 186 break; 187 case CTL_VM: 188 fn = uvm_sysctl; 189 break; 190 case CTL_NET: 191 fn = net_sysctl; 192 break; 193 case CTL_VFS: 194 fn = vfs_sysctl; 195 break; 196 case CTL_MACHDEP: 197 fn = cpu_sysctl; 198 break; 199 #ifdef DEBUG 200 case CTL_DEBUG: 201 fn = debug_sysctl; 202 break; 203 #endif 204 #ifdef DDB 205 case CTL_DDB: 206 fn = ddb_sysctl; 207 break; 208 #endif 209 case CTL_PROC: 210 fn = proc_sysctl; 211 break; 212 213 case CTL_EMUL: 214 fn = emul_sysctl; 215 break; 216 default: 217 return (EOPNOTSUPP); 218 } 219 220 /* 221 * XXX Hey, we wire `old', but what about `new'? 222 */ 223 224 oldlenp = SCARG(uap, oldlenp); 225 if (oldlenp) { 226 if ((error = copyin(oldlenp, &oldlen, sizeof(oldlen)))) 227 return (error); 228 oldlenp = &oldlen; 229 } 230 if (SCARG(uap, old) != NULL) { 231 error = lockmgr(&sysctl_memlock, LK_EXCLUSIVE, NULL); 232 if (error) 233 return (error); 234 error = uvm_vslock(p, SCARG(uap, old), oldlen, VM_PROT_WRITE); 235 if (error) { 236 (void) lockmgr(&sysctl_memlock, LK_RELEASE, NULL); 237 return error; 238 } 239 savelen = oldlen; 240 } 241 error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old), 242 oldlenp, SCARG(uap, new), SCARG(uap, newlen), p); 243 if (SCARG(uap, old) != NULL) { 244 uvm_vsunlock(p, SCARG(uap, old), savelen); 245 (void) lockmgr(&sysctl_memlock, LK_RELEASE, NULL); 246 } 247 if (error) 248 return (error); 249 if (SCARG(uap, oldlenp)) 250 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen)); 251 return (error); 252 } 253 254 /* 255 * Attributes stored in the kernel. 256 */ 257 char hostname[MAXHOSTNAMELEN]; 258 int hostnamelen; 259 260 char domainname[MAXHOSTNAMELEN]; 261 int domainnamelen; 262 263 long hostid; 264 265 #ifdef INSECURE 266 int securelevel = -1; 267 #else 268 int securelevel = 0; 269 #endif 270 271 #ifndef DEFCORENAME 272 #define DEFCORENAME "%n.core" 273 #endif 274 char defcorename[MAXPATHLEN] = DEFCORENAME; 275 int defcorenamelen = sizeof(DEFCORENAME); 276 277 extern int kern_logsigexit; 278 extern fixpt_t ccpu; 279 280 #ifndef MULTIPROCESSOR 281 #define sysctl_ncpus() 1 282 #endif 283 284 #ifdef MULTIPROCESSOR 285 286 #ifndef CPU_INFO_FOREACH 287 #define CPU_INFO_ITERATOR int 288 #define CPU_INFO_FOREACH(cii, ci) cii = 0, ci = curcpu(); ci != NULL; ci = NULL 289 #endif 290 291 static int 292 sysctl_docptime(void *oldp, size_t *oldlenp, void *newp) 293 { 294 u_int64_t cp_time[CPUSTATES]; 295 int i; 296 struct cpu_info *ci; 297 CPU_INFO_ITERATOR cii; 298 299 for (i = 0; i < CPUSTATES; i++) 300 cp_time[i] = 0; 301 302 for (CPU_INFO_FOREACH(cii, ci)) { 303 for (i = 0; i < CPUSTATES; i++) 304 cp_time[i] += ci->ci_schedstate.spc_cp_time[i]; 305 } 306 return (sysctl_rdstruct(oldp, oldlenp, newp, 307 cp_time, sizeof(cp_time))); 308 } 309 310 static int 311 sysctl_ncpus(void) 312 { 313 struct cpu_info *ci; 314 CPU_INFO_ITERATOR cii; 315 316 int ncpus = 0; 317 for (CPU_INFO_FOREACH(cii, ci)) 318 ncpus++; 319 return ncpus; 320 } 321 322 #endif 323 324 /* 325 * kernel related system variables. 326 */ 327 int 328 kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 329 void *newp, size_t newlen, struct proc *p) 330 { 331 int error, level, inthostid; 332 int old_autonicetime; 333 int old_vnodes; 334 dev_t consdev; 335 #if NRND > 0 336 int v; 337 #endif 338 339 /* All sysctl names at this level, except for a few, are terminal. */ 340 switch (name[0]) { 341 case KERN_PROC: 342 case KERN_PROC2: 343 case KERN_PROF: 344 case KERN_MBUF: 345 case KERN_PROC_ARGS: 346 case KERN_SYSVIPC_INFO: 347 case KERN_PIPE: 348 case KERN_TKSTAT: 349 /* Not terminal. */ 350 break; 351 default: 352 if (namelen != 1) 353 return (ENOTDIR); /* overloaded */ 354 } 355 356 switch (name[0]) { 357 case KERN_OSTYPE: 358 return (sysctl_rdstring(oldp, oldlenp, newp, ostype)); 359 case KERN_OSRELEASE: 360 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease)); 361 case KERN_OSREV: 362 return (sysctl_rdint(oldp, oldlenp, newp, __NetBSD_Version__)); 363 case KERN_VERSION: 364 return (sysctl_rdstring(oldp, oldlenp, newp, version)); 365 case KERN_MAXVNODES: 366 old_vnodes = desiredvnodes; 367 error = sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes); 368 if (newp && !error) { 369 if (old_vnodes > desiredvnodes) { 370 desiredvnodes = old_vnodes; 371 return (EINVAL); 372 } 373 vfs_reinit(); 374 nchreinit(); 375 } 376 return (error); 377 case KERN_MAXPROC: 378 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc)); 379 case KERN_MAXFILES: 380 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles)); 381 case KERN_ARGMAX: 382 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX)); 383 case KERN_SECURELVL: 384 level = securelevel; 385 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) || 386 newp == NULL) 387 return (error); 388 if (level < securelevel && p->p_pid != 1) 389 return (EPERM); 390 securelevel = level; 391 return (0); 392 case KERN_HOSTNAME: 393 error = sysctl_string(oldp, oldlenp, newp, newlen, 394 hostname, sizeof(hostname)); 395 if (newp && !error) 396 hostnamelen = newlen; 397 return (error); 398 case KERN_DOMAINNAME: 399 error = sysctl_string(oldp, oldlenp, newp, newlen, 400 domainname, sizeof(domainname)); 401 if (newp && !error) 402 domainnamelen = newlen; 403 return (error); 404 case KERN_HOSTID: 405 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */ 406 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid); 407 if (newp && !error) 408 hostid = inthostid; 409 return (error); 410 case KERN_CLOCKRATE: 411 return (sysctl_clockrate(oldp, oldlenp)); 412 case KERN_BOOTTIME: 413 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime, 414 sizeof(struct timeval))); 415 case KERN_VNODE: 416 return (sysctl_vnode(oldp, oldlenp, p)); 417 case KERN_PROC: 418 case KERN_PROC2: 419 return (sysctl_doeproc(name, namelen, oldp, oldlenp)); 420 case KERN_PROC_ARGS: 421 return (sysctl_procargs(name + 1, namelen - 1, 422 oldp, oldlenp, p)); 423 case KERN_FILE: 424 return (sysctl_file(oldp, oldlenp)); 425 #ifdef GPROF 426 case KERN_PROF: 427 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp, 428 newp, newlen)); 429 #endif 430 case KERN_POSIX1: 431 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION)); 432 case KERN_NGROUPS: 433 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX)); 434 case KERN_JOB_CONTROL: 435 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 436 case KERN_SAVED_IDS: 437 #ifdef _POSIX_SAVED_IDS 438 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 439 #else 440 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 441 #endif 442 case KERN_MAXPARTITIONS: 443 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS)); 444 case KERN_RAWPARTITION: 445 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART)); 446 #ifdef NTP 447 case KERN_NTPTIME: 448 return (sysctl_ntptime(oldp, oldlenp)); 449 #endif 450 case KERN_AUTONICETIME: 451 old_autonicetime = autonicetime; 452 error = sysctl_int(oldp, oldlenp, newp, newlen, &autonicetime); 453 if (autonicetime < 0) 454 autonicetime = old_autonicetime; 455 return (error); 456 case KERN_AUTONICEVAL: 457 error = sysctl_int(oldp, oldlenp, newp, newlen, &autoniceval); 458 if (autoniceval < PRIO_MIN) 459 autoniceval = PRIO_MIN; 460 if (autoniceval > PRIO_MAX) 461 autoniceval = PRIO_MAX; 462 return (error); 463 case KERN_RTC_OFFSET: 464 return (sysctl_rdint(oldp, oldlenp, newp, rtc_offset)); 465 case KERN_ROOT_DEVICE: 466 return (sysctl_rdstring(oldp, oldlenp, newp, 467 root_device->dv_xname)); 468 case KERN_MSGBUFSIZE: 469 /* 470 * deal with cases where the message buffer has 471 * become corrupted. 472 */ 473 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 474 msgbufenabled = 0; 475 return (ENXIO); 476 } 477 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs)); 478 case KERN_FSYNC: 479 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 480 case KERN_SYSVMSG: 481 #ifdef SYSVMSG 482 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 483 #else 484 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 485 #endif 486 case KERN_SYSVSEM: 487 #ifdef SYSVSEM 488 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 489 #else 490 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 491 #endif 492 case KERN_SYSVSHM: 493 #ifdef SYSVSHM 494 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 495 #else 496 return (sysctl_rdint(oldp, oldlenp, newp, 0)); 497 #endif 498 case KERN_DEFCORENAME: 499 if (newp && newlen < 1) 500 return (EINVAL); 501 error = sysctl_string(oldp, oldlenp, newp, newlen, 502 defcorename, sizeof(defcorename)); 503 if (newp && !error) 504 defcorenamelen = newlen; 505 return (error); 506 case KERN_SYNCHRONIZED_IO: 507 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 508 case KERN_IOV_MAX: 509 return (sysctl_rdint(oldp, oldlenp, newp, IOV_MAX)); 510 case KERN_MBUF: 511 return (sysctl_dombuf(name + 1, namelen - 1, oldp, oldlenp, 512 newp, newlen)); 513 case KERN_MAPPED_FILES: 514 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 515 case KERN_MEMLOCK: 516 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 517 case KERN_MEMLOCK_RANGE: 518 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 519 case KERN_MEMORY_PROTECTION: 520 return (sysctl_rdint(oldp, oldlenp, newp, 1)); 521 case KERN_LOGIN_NAME_MAX: 522 return (sysctl_rdint(oldp, oldlenp, newp, LOGIN_NAME_MAX)); 523 case KERN_LOGSIGEXIT: 524 return (sysctl_int(oldp, oldlenp, newp, newlen, 525 &kern_logsigexit)); 526 case KERN_FSCALE: 527 return (sysctl_rdint(oldp, oldlenp, newp, FSCALE)); 528 case KERN_CCPU: 529 return (sysctl_rdint(oldp, oldlenp, newp, ccpu)); 530 case KERN_CP_TIME: 531 #ifndef MULTIPROCESSOR 532 return (sysctl_rdstruct(oldp, oldlenp, newp, 533 curcpu()->ci_schedstate.spc_cp_time, 534 sizeof(curcpu()->ci_schedstate.spc_cp_time))); 535 #else 536 return (sysctl_docptime(oldp, oldlenp, newp)); 537 #endif 538 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 539 case KERN_SYSVIPC_INFO: 540 return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp)); 541 #endif 542 case KERN_MSGBUF: 543 return (sysctl_msgbuf(oldp, oldlenp)); 544 case KERN_CONSDEV: 545 if (cn_tab != NULL) 546 consdev = cn_tab->cn_dev; 547 else 548 consdev = NODEV; 549 return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev, 550 sizeof consdev)); 551 #if NPTY > 0 552 case KERN_MAXPTYS: 553 return sysctl_pty(oldp, oldlenp, newp, newlen); 554 #endif 555 #ifndef PIPE_SOCKETPAIR 556 case KERN_PIPE: 557 return (sysctl_dopipe(name + 1, namelen - 1, oldp, oldlenp, 558 newp, newlen)); 559 #endif 560 case KERN_MAXPHYS: 561 return (sysctl_rdint(oldp, oldlenp, newp, MAXPHYS)); 562 case KERN_SBMAX: 563 { 564 int new_sbmax = sb_max; 565 566 error = sysctl_int(oldp, oldlenp, newp, newlen, &new_sbmax); 567 if (newp && !error) { 568 if (new_sbmax < (16 * 1024)) /* sanity */ 569 return (EINVAL); 570 sb_max = new_sbmax; 571 } 572 return (error); 573 } 574 case KERN_TKSTAT: 575 return (sysctl_dotkstat(name + 1, namelen - 1, oldp, oldlenp, 576 newp)); 577 case KERN_MONOTONIC_CLOCK: /* XXX _POSIX_VERSION */ 578 return (sysctl_rdint(oldp, oldlenp, newp, 200112)); 579 case KERN_URND: 580 #if NRND > 0 581 if (rnd_extract_data(&v, sizeof(v), RND_EXTRACT_ANY) == 582 sizeof(v)) 583 return (sysctl_rdint(oldp, oldlenp, newp, v)); 584 else 585 return (EIO); /*XXX*/ 586 #else 587 return (EOPNOTSUPP); 588 #endif 589 default: 590 return (EOPNOTSUPP); 591 } 592 /* NOTREACHED */ 593 } 594 595 /* 596 * hardware related system variables. 597 */ 598 int 599 hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 600 void *newp, size_t newlen, struct proc *p) 601 { 602 603 /* All sysctl names at this level, except for a few, are terminal. */ 604 switch (name[0]) { 605 case HW_DISKSTATS: 606 /* Not terminal. */ 607 break; 608 default: 609 if (namelen != 1) 610 return (ENOTDIR); /* overloaded */ 611 } 612 613 switch (name[0]) { 614 case HW_MACHINE: 615 return (sysctl_rdstring(oldp, oldlenp, newp, machine)); 616 case HW_MACHINE_ARCH: 617 return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch)); 618 case HW_MODEL: 619 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model)); 620 case HW_NCPU: 621 return (sysctl_rdint(oldp, oldlenp, newp, sysctl_ncpus())); 622 case HW_BYTEORDER: 623 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER)); 624 case HW_PHYSMEM: 625 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem))); 626 case HW_USERMEM: 627 return (sysctl_rdint(oldp, oldlenp, newp, 628 ctob(physmem - uvmexp.wired))); 629 case HW_PAGESIZE: 630 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE)); 631 case HW_ALIGNBYTES: 632 return (sysctl_rdint(oldp, oldlenp, newp, ALIGNBYTES)); 633 case HW_DISKNAMES: 634 return (sysctl_disknames(oldp, oldlenp)); 635 case HW_DISKSTATS: 636 return (sysctl_diskstats(name + 1, namelen - 1, oldp, oldlenp)); 637 case HW_CNMAGIC: { 638 char magic[CNS_LEN]; 639 int error; 640 641 if (oldp) 642 cn_get_magic(magic, CNS_LEN); 643 error = sysctl_string(oldp, oldlenp, newp, newlen, 644 magic, sizeof(magic)); 645 if (newp && !error) { 646 error = cn_set_magic(magic); 647 } 648 return (error); 649 } 650 default: 651 return (EOPNOTSUPP); 652 } 653 /* NOTREACHED */ 654 } 655 656 #ifdef DEBUG 657 /* 658 * Debugging related system variables. 659 */ 660 struct ctldebug /* debug0, */ /* debug1, */ debug2, debug3, debug4; 661 struct ctldebug debug5, debug6, debug7, debug8, debug9; 662 struct ctldebug debug10, debug11, debug12, debug13, debug14; 663 struct ctldebug debug15, debug16, debug17, debug18, debug19; 664 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 665 &debug0, &debug1, &debug2, &debug3, &debug4, 666 &debug5, &debug6, &debug7, &debug8, &debug9, 667 &debug10, &debug11, &debug12, &debug13, &debug14, 668 &debug15, &debug16, &debug17, &debug18, &debug19, 669 }; 670 671 int 672 debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 673 void *newp, size_t newlen, struct proc *p) 674 { 675 struct ctldebug *cdp; 676 677 /* all sysctl names at this level are name and field */ 678 if (namelen != 2) 679 return (ENOTDIR); /* overloaded */ 680 if (name[0] >= CTL_DEBUG_MAXID) 681 return (EOPNOTSUPP); 682 cdp = debugvars[name[0]]; 683 if (cdp->debugname == 0) 684 return (EOPNOTSUPP); 685 switch (name[1]) { 686 case CTL_DEBUG_NAME: 687 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname)); 688 case CTL_DEBUG_VALUE: 689 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar)); 690 default: 691 return (EOPNOTSUPP); 692 } 693 /* NOTREACHED */ 694 } 695 #endif /* DEBUG */ 696 697 int 698 proc_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 699 void *newp, size_t newlen, struct proc *p) 700 { 701 struct proc *ptmp = NULL; 702 const struct proclist_desc *pd; 703 int error = 0; 704 struct rlimit alim; 705 struct plimit *newplim; 706 char *tmps = NULL; 707 size_t len, curlen; 708 u_int i; 709 710 if (namelen < 2) 711 return EINVAL; 712 713 if (name[0] == PROC_CURPROC) { 714 ptmp = p; 715 } else { 716 proclist_lock_read(); 717 for (pd = proclists; pd->pd_list != NULL; pd++) { 718 for (ptmp = LIST_FIRST(pd->pd_list); ptmp != NULL; 719 ptmp = LIST_NEXT(ptmp, p_list)) { 720 /* Skip embryonic processes. */ 721 if (ptmp->p_stat == SIDL) 722 continue; 723 if (ptmp->p_pid == (pid_t)name[0]) 724 break; 725 } 726 if (ptmp != NULL) 727 break; 728 } 729 proclist_unlock_read(); 730 if (ptmp == NULL) 731 return(ESRCH); 732 if (p->p_ucred->cr_uid != 0) { 733 if(p->p_cred->p_ruid != ptmp->p_cred->p_ruid || 734 p->p_cred->p_ruid != ptmp->p_cred->p_svuid) 735 return EPERM; 736 if (ptmp->p_cred->p_rgid != ptmp->p_cred->p_svgid) 737 return EPERM; /* sgid proc */ 738 for (i = 0; i < p->p_ucred->cr_ngroups; i++) { 739 if (p->p_ucred->cr_groups[i] == 740 ptmp->p_cred->p_rgid) 741 break; 742 } 743 if (i == p->p_ucred->cr_ngroups) 744 return EPERM; 745 } 746 } 747 switch(name[1]) { 748 case PROC_PID_STOPFORK: 749 if (namelen != 2) 750 return EINVAL; 751 i = ((ptmp->p_flag & P_STOPFORK) != 0); 752 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &i)) != 0) 753 return error; 754 if (i != 0) 755 ptmp->p_flag |= P_STOPFORK; 756 else 757 ptmp->p_flag &= ~P_STOPFORK; 758 return 0; 759 break; 760 761 case PROC_PID_STOPEXEC: 762 if (namelen != 2) 763 return EINVAL; 764 i = ((ptmp->p_flag & P_STOPEXEC) != 0); 765 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &i)) != 0) 766 return error; 767 if (i != 0) 768 ptmp->p_flag |= P_STOPEXEC; 769 else 770 ptmp->p_flag &= ~P_STOPEXEC; 771 return 0; 772 break; 773 774 case PROC_PID_CORENAME: 775 if (namelen != 2) 776 return EINVAL; 777 /* 778 * Can't use sysctl_string() here because we may malloc a new 779 * area during the process, so we have to do it by hand. 780 */ 781 curlen = strlen(ptmp->p_limit->pl_corename) + 1; 782 if (oldlenp && *oldlenp < curlen) { 783 if (!oldp) 784 *oldlenp = curlen; 785 return (ENOMEM); 786 } 787 if (newp) { 788 if (securelevel > 2) 789 return EPERM; 790 if (newlen > MAXPATHLEN) 791 return ENAMETOOLONG; 792 tmps = malloc(newlen + 1, M_TEMP, M_WAITOK); 793 if (tmps == NULL) 794 return ENOMEM; 795 error = copyin(newp, tmps, newlen + 1); 796 tmps[newlen] = '\0'; 797 if (error) 798 goto cleanup; 799 /* Enforce to be either 'core' for end with '.core' */ 800 if (newlen < 4) { /* c.o.r.e */ 801 error = EINVAL; 802 goto cleanup; 803 } 804 len = newlen - 4; 805 if (len > 0) { 806 if (tmps[len - 1] != '.' && 807 tmps[len - 1] != '/') { 808 error = EINVAL; 809 goto cleanup; 810 } 811 } 812 if (strcmp(&tmps[len], "core") != 0) { 813 error = EINVAL; 814 goto cleanup; 815 } 816 } 817 if (oldp && oldlenp) { 818 *oldlenp = curlen; 819 error = copyout(ptmp->p_limit->pl_corename, oldp, 820 curlen); 821 } 822 if (newp && error == 0) { 823 /* if the 2 strings are identical, don't limcopy() */ 824 if (strcmp(tmps, ptmp->p_limit->pl_corename) == 0) { 825 error = 0; 826 goto cleanup; 827 } 828 if (ptmp->p_limit->p_refcnt > 1 && 829 (ptmp->p_limit->p_lflags & PL_SHAREMOD) == 0) { 830 newplim = limcopy(ptmp->p_limit); 831 limfree(ptmp->p_limit); 832 ptmp->p_limit = newplim; 833 } 834 if (ptmp->p_limit->pl_corename != defcorename) { 835 free(ptmp->p_limit->pl_corename, M_TEMP); 836 } 837 ptmp->p_limit->pl_corename = tmps; 838 return (0); 839 } 840 cleanup: 841 if (tmps) 842 free(tmps, M_TEMP); 843 return (error); 844 break; 845 846 case PROC_PID_LIMIT: 847 if (namelen != 4 || name[2] >= PROC_PID_LIMIT_MAXID) 848 return EINVAL; 849 memcpy(&alim, &ptmp->p_rlimit[name[2] - 1], sizeof(alim)); 850 if (name[3] == PROC_PID_LIMIT_TYPE_HARD) 851 error = sysctl_quad(oldp, oldlenp, newp, newlen, 852 &alim.rlim_max); 853 else if (name[3] == PROC_PID_LIMIT_TYPE_SOFT) 854 error = sysctl_quad(oldp, oldlenp, newp, newlen, 855 &alim.rlim_cur); 856 else 857 error = EINVAL; 858 859 if (error) 860 return error; 861 862 if (newp) 863 error = dosetrlimit(ptmp, p->p_cred, 864 name[2] - 1, &alim); 865 return error; 866 break; 867 868 default: 869 return (EINVAL); 870 break; 871 } 872 /* NOTREACHED */ 873 return (EINVAL); 874 } 875 876 int 877 emul_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 878 void *newp, size_t newlen, struct proc *p) 879 { 880 static struct { 881 const char *name; 882 int type; 883 } emulations[] = CTL_EMUL_NAMES; 884 const struct emul *e; 885 const char *ename; 886 #ifdef LKM 887 extern struct lock exec_lock; /* XXX */ 888 int error; 889 #else 890 extern int nexecs_builtin; 891 extern const struct execsw execsw_builtin[]; 892 int i; 893 #endif 894 895 /* all sysctl names at this level are name and field */ 896 if (namelen < 2) 897 return (ENOTDIR); /* overloaded */ 898 899 if ((u_int) name[0] >= EMUL_MAXID || name[0] == 0) 900 return (EOPNOTSUPP); 901 902 ename = emulations[name[0]].name; 903 904 #ifdef LKM 905 lockmgr(&exec_lock, LK_SHARED, NULL); 906 if ((e = emul_search(ename))) { 907 error = (*e->e_sysctl)(name + 1, namelen - 1, oldp, oldlenp, 908 newp, newlen, p); 909 } else 910 error = EOPNOTSUPP; 911 lockmgr(&exec_lock, LK_RELEASE, NULL); 912 913 return (error); 914 #else 915 for (i = 0; i < nexecs_builtin; i++) { 916 e = execsw_builtin[i].es_emul; 917 /* 918 * In order to match e.g. e->e_name "irix o32" with ename "irix", 919 * we limit the comparison to the length of ename. 920 */ 921 if (e == NULL || strncmp(ename, e->e_name, strlen(ename)) != 0 || 922 e->e_sysctl == NULL) 923 continue; 924 925 return (*e->e_sysctl)(name + 1, namelen - 1, oldp, oldlenp, 926 newp, newlen, p); 927 } 928 929 return (EOPNOTSUPP); 930 #endif 931 } 932 /* 933 * Convenience macros. 934 */ 935 936 #define SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, valp, len) \ 937 if (oldlenp) { \ 938 if (!oldp) \ 939 *oldlenp = len; \ 940 else { \ 941 if (*oldlenp < len) \ 942 return(ENOMEM); \ 943 *oldlenp = len; \ 944 error = copyout((caddr_t)valp, oldp, len); \ 945 } \ 946 } 947 948 #define SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, typ) \ 949 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, valp, sizeof(typ)) 950 951 #define SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, len) \ 952 if (newp && newlen != len) \ 953 return (EINVAL); 954 955 #define SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, typ) \ 956 SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, sizeof(typ)) 957 958 #define SYSCTL_SCALAR_NEWPCOP_LEN(newp, valp, len) \ 959 if (error == 0 && newp) \ 960 error = copyin(newp, valp, len); 961 962 #define SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, typ) \ 963 SYSCTL_SCALAR_NEWPCOP_LEN(newp, valp, sizeof(typ)) 964 965 #define SYSCTL_STRING_CORE(oldp, oldlenp, str) \ 966 if (oldlenp) { \ 967 len = strlen(str) + 1; \ 968 if (!oldp) \ 969 *oldlenp = len; \ 970 else { \ 971 if (*oldlenp < len) { \ 972 err2 = ENOMEM; \ 973 len = *oldlenp; \ 974 } else \ 975 *oldlenp = len; \ 976 error = copyout(str, oldp, len);\ 977 if (error == 0) \ 978 error = err2; \ 979 } \ 980 } 981 982 /* 983 * Validate parameters and get old / set new parameters 984 * for an integer-valued sysctl function. 985 */ 986 int 987 sysctl_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp) 988 { 989 int error = 0; 990 991 SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, int) 992 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, int) 993 SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, int) 994 995 return (error); 996 } 997 998 999 /* 1000 * As above, but read-only. 1001 */ 1002 int 1003 sysctl_rdint(void *oldp, size_t *oldlenp, void *newp, int val) 1004 { 1005 int error = 0; 1006 1007 if (newp) 1008 return (EPERM); 1009 1010 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &val, int) 1011 1012 return (error); 1013 } 1014 1015 /* 1016 * Validate parameters and get old / set new parameters 1017 * for an quad-valued sysctl function. 1018 */ 1019 int 1020 sysctl_quad(void *oldp, size_t *oldlenp, void *newp, size_t newlen, 1021 quad_t *valp) 1022 { 1023 int error = 0; 1024 1025 SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, quad_t) 1026 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, valp, quad_t) 1027 SYSCTL_SCALAR_NEWPCOP_TYP(newp, valp, quad_t) 1028 1029 return (error); 1030 } 1031 1032 /* 1033 * As above, but read-only. 1034 */ 1035 int 1036 sysctl_rdquad(void *oldp, size_t *oldlenp, void *newp, quad_t val) 1037 { 1038 int error = 0; 1039 1040 if (newp) 1041 return (EPERM); 1042 1043 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &val, quad_t) 1044 1045 return (error); 1046 } 1047 1048 /* 1049 * Validate parameters and get old / set new parameters 1050 * for a string-valued sysctl function. 1051 */ 1052 int 1053 sysctl_string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str, 1054 size_t maxlen) 1055 { 1056 int error = 0, err2 = 0; 1057 size_t len; 1058 1059 if (newp && newlen >= maxlen) 1060 return (EINVAL); 1061 1062 SYSCTL_STRING_CORE(oldp, oldlenp, str); 1063 1064 if (error == 0 && newp) { 1065 error = copyin(newp, str, newlen); 1066 str[newlen] = 0; 1067 } 1068 return (error); 1069 } 1070 1071 /* 1072 * As above, but read-only. 1073 */ 1074 int 1075 sysctl_rdstring(void *oldp, size_t *oldlenp, void *newp, const char *str) 1076 { 1077 int error = 0, err2 = 0; 1078 size_t len; 1079 1080 if (newp) 1081 return (EPERM); 1082 1083 SYSCTL_STRING_CORE(oldp, oldlenp, str); 1084 1085 return (error); 1086 } 1087 1088 /* 1089 * Validate parameters and get old / set new parameters 1090 * for a structure oriented sysctl function. 1091 */ 1092 int 1093 sysctl_struct(void *oldp, size_t *oldlenp, void *newp, size_t newlen, void *sp, 1094 size_t len) 1095 { 1096 int error = 0; 1097 1098 SYSCTL_SCALAR_NEWPCHECK_LEN(newp, newlen, len) 1099 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len) 1100 SYSCTL_SCALAR_NEWPCOP_LEN(newp, sp, len) 1101 1102 return (error); 1103 } 1104 1105 /* 1106 * Validate parameters and get old parameters 1107 * for a structure oriented sysctl function. 1108 */ 1109 int 1110 sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp, 1111 size_t len) 1112 { 1113 int error = 0; 1114 1115 if (newp) 1116 return (EPERM); 1117 1118 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len) 1119 1120 return (error); 1121 } 1122 1123 /* 1124 * As above, but can return a truncated result. 1125 */ 1126 int 1127 sysctl_rdminstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp, 1128 size_t len) 1129 { 1130 int error = 0; 1131 1132 if (newp) 1133 return (EPERM); 1134 1135 len = min(*oldlenp, len); 1136 SYSCTL_SCALAR_CORE_LEN(oldp, oldlenp, sp, len) 1137 1138 return (error); 1139 } 1140 1141 /* 1142 * Get file structures. 1143 */ 1144 static int 1145 sysctl_file(void *vwhere, size_t *sizep) 1146 { 1147 int error; 1148 size_t buflen; 1149 struct file *fp; 1150 char *start, *where; 1151 1152 start = where = vwhere; 1153 buflen = *sizep; 1154 if (where == NULL) { 1155 /* 1156 * overestimate by 10 files 1157 */ 1158 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 1159 return (0); 1160 } 1161 1162 /* 1163 * first copyout filehead 1164 */ 1165 if (buflen < sizeof(filehead)) { 1166 *sizep = 0; 1167 return (0); 1168 } 1169 error = copyout((caddr_t)&filehead, where, sizeof(filehead)); 1170 if (error) 1171 return (error); 1172 buflen -= sizeof(filehead); 1173 where += sizeof(filehead); 1174 1175 /* 1176 * followed by an array of file structures 1177 */ 1178 LIST_FOREACH(fp, &filehead, f_list) { 1179 if (buflen < sizeof(struct file)) { 1180 *sizep = where - start; 1181 return (ENOMEM); 1182 } 1183 error = copyout((caddr_t)fp, where, sizeof(struct file)); 1184 if (error) 1185 return (error); 1186 buflen -= sizeof(struct file); 1187 where += sizeof(struct file); 1188 } 1189 *sizep = where - start; 1190 return (0); 1191 } 1192 1193 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 1194 #define FILL_PERM(src, dst) do { \ 1195 (dst)._key = (src)._key; \ 1196 (dst).uid = (src).uid; \ 1197 (dst).gid = (src).gid; \ 1198 (dst).cuid = (src).cuid; \ 1199 (dst).cgid = (src).cgid; \ 1200 (dst).mode = (src).mode; \ 1201 (dst)._seq = (src)._seq; \ 1202 } while (/*CONSTCOND*/ 0); 1203 #define FILL_MSG(src, dst) do { \ 1204 FILL_PERM((src).msg_perm, (dst).msg_perm); \ 1205 (dst).msg_qnum = (src).msg_qnum; \ 1206 (dst).msg_qbytes = (src).msg_qbytes; \ 1207 (dst)._msg_cbytes = (src)._msg_cbytes; \ 1208 (dst).msg_lspid = (src).msg_lspid; \ 1209 (dst).msg_lrpid = (src).msg_lrpid; \ 1210 (dst).msg_stime = (src).msg_stime; \ 1211 (dst).msg_rtime = (src).msg_rtime; \ 1212 (dst).msg_ctime = (src).msg_ctime; \ 1213 } while (/*CONSTCOND*/ 0) 1214 #define FILL_SEM(src, dst) do { \ 1215 FILL_PERM((src).sem_perm, (dst).sem_perm); \ 1216 (dst).sem_nsems = (src).sem_nsems; \ 1217 (dst).sem_otime = (src).sem_otime; \ 1218 (dst).sem_ctime = (src).sem_ctime; \ 1219 } while (/*CONSTCOND*/ 0) 1220 #define FILL_SHM(src, dst) do { \ 1221 FILL_PERM((src).shm_perm, (dst).shm_perm); \ 1222 (dst).shm_segsz = (src).shm_segsz; \ 1223 (dst).shm_lpid = (src).shm_lpid; \ 1224 (dst).shm_cpid = (src).shm_cpid; \ 1225 (dst).shm_atime = (src).shm_atime; \ 1226 (dst).shm_dtime = (src).shm_dtime; \ 1227 (dst).shm_ctime = (src).shm_ctime; \ 1228 (dst).shm_nattch = (src).shm_nattch; \ 1229 } while (/*CONSTCOND*/ 0) 1230 1231 static int 1232 sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep) 1233 { 1234 #ifdef SYSVMSG 1235 struct msg_sysctl_info *msgsi = NULL; 1236 #endif 1237 #ifdef SYSVSEM 1238 struct sem_sysctl_info *semsi = NULL; 1239 #endif 1240 #ifdef SYSVSHM 1241 struct shm_sysctl_info *shmsi = NULL; 1242 #endif 1243 size_t infosize, dssize, tsize, buflen; 1244 void *buf = NULL; 1245 char *start; 1246 int32_t nds; 1247 int i, error, ret; 1248 1249 if (namelen != 1) 1250 return (EINVAL); 1251 1252 start = where; 1253 buflen = *sizep; 1254 1255 switch (*name) { 1256 case KERN_SYSVIPC_MSG_INFO: 1257 #ifdef SYSVMSG 1258 infosize = sizeof(msgsi->msginfo); 1259 nds = msginfo.msgmni; 1260 dssize = sizeof(msgsi->msgids[0]); 1261 break; 1262 #else 1263 return (EINVAL); 1264 #endif 1265 case KERN_SYSVIPC_SEM_INFO: 1266 #ifdef SYSVSEM 1267 infosize = sizeof(semsi->seminfo); 1268 nds = seminfo.semmni; 1269 dssize = sizeof(semsi->semids[0]); 1270 break; 1271 #else 1272 return (EINVAL); 1273 #endif 1274 case KERN_SYSVIPC_SHM_INFO: 1275 #ifdef SYSVSHM 1276 infosize = sizeof(shmsi->shminfo); 1277 nds = shminfo.shmmni; 1278 dssize = sizeof(shmsi->shmids[0]); 1279 break; 1280 #else 1281 return (EINVAL); 1282 #endif 1283 default: 1284 return (EINVAL); 1285 } 1286 /* 1287 * Round infosize to 64 bit boundary if requesting more than just 1288 * the info structure or getting the total data size. 1289 */ 1290 if (where == NULL || *sizep > infosize) 1291 infosize = ((infosize + 7) / 8) * 8; 1292 tsize = infosize + nds * dssize; 1293 1294 /* Return just the total size required. */ 1295 if (where == NULL) { 1296 *sizep = tsize; 1297 return (0); 1298 } 1299 1300 /* Not enough room for even the info struct. */ 1301 if (buflen < infosize) { 1302 *sizep = 0; 1303 return (ENOMEM); 1304 } 1305 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK); 1306 memset(buf, 0, min(tsize, buflen)); 1307 1308 switch (*name) { 1309 #ifdef SYSVMSG 1310 case KERN_SYSVIPC_MSG_INFO: 1311 msgsi = (struct msg_sysctl_info *)buf; 1312 msgsi->msginfo = msginfo; 1313 break; 1314 #endif 1315 #ifdef SYSVSEM 1316 case KERN_SYSVIPC_SEM_INFO: 1317 semsi = (struct sem_sysctl_info *)buf; 1318 semsi->seminfo = seminfo; 1319 break; 1320 #endif 1321 #ifdef SYSVSHM 1322 case KERN_SYSVIPC_SHM_INFO: 1323 shmsi = (struct shm_sysctl_info *)buf; 1324 shmsi->shminfo = shminfo; 1325 break; 1326 #endif 1327 } 1328 buflen -= infosize; 1329 1330 ret = 0; 1331 if (buflen > 0) { 1332 /* Fill in the IPC data structures. */ 1333 for (i = 0; i < nds; i++) { 1334 if (buflen < dssize) { 1335 ret = ENOMEM; 1336 break; 1337 } 1338 switch (*name) { 1339 #ifdef SYSVMSG 1340 case KERN_SYSVIPC_MSG_INFO: 1341 FILL_MSG(msqids[i], msgsi->msgids[i]); 1342 break; 1343 #endif 1344 #ifdef SYSVSEM 1345 case KERN_SYSVIPC_SEM_INFO: 1346 FILL_SEM(sema[i], semsi->semids[i]); 1347 break; 1348 #endif 1349 #ifdef SYSVSHM 1350 case KERN_SYSVIPC_SHM_INFO: 1351 FILL_SHM(shmsegs[i], shmsi->shmids[i]); 1352 break; 1353 #endif 1354 } 1355 buflen -= dssize; 1356 } 1357 } 1358 *sizep -= buflen; 1359 error = copyout(buf, start, *sizep); 1360 /* If copyout succeeded, use return code set earlier. */ 1361 if (error == 0) 1362 error = ret; 1363 if (buf) 1364 free(buf, M_TEMP); 1365 return (error); 1366 } 1367 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */ 1368 1369 static int 1370 sysctl_msgbuf(void *vwhere, size_t *sizep) 1371 { 1372 char *where = vwhere; 1373 size_t len, maxlen = *sizep; 1374 long beg, end; 1375 int error; 1376 1377 /* 1378 * deal with cases where the message buffer has 1379 * become corrupted. 1380 */ 1381 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 1382 msgbufenabled = 0; 1383 return (ENXIO); 1384 } 1385 1386 if (where == NULL) { 1387 /* always return full buffer size */ 1388 *sizep = msgbufp->msg_bufs; 1389 return (0); 1390 } 1391 1392 error = 0; 1393 maxlen = min(msgbufp->msg_bufs, maxlen); 1394 1395 /* 1396 * First, copy from the write pointer to the end of 1397 * message buffer. 1398 */ 1399 beg = msgbufp->msg_bufx; 1400 end = msgbufp->msg_bufs; 1401 while (maxlen > 0) { 1402 len = min(end - beg, maxlen); 1403 if (len == 0) 1404 break; 1405 error = copyout(&msgbufp->msg_bufc[beg], where, len); 1406 if (error) 1407 break; 1408 where += len; 1409 maxlen -= len; 1410 1411 /* 1412 * ... then, copy from the beginning of message buffer to 1413 * the write pointer. 1414 */ 1415 beg = 0; 1416 end = msgbufp->msg_bufx; 1417 } 1418 return (error); 1419 } 1420 1421 /* 1422 * try over estimating by 5 procs 1423 */ 1424 #define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc)) 1425 1426 static int 1427 sysctl_doeproc(int *name, u_int namelen, void *vwhere, size_t *sizep) 1428 { 1429 struct eproc eproc; 1430 struct kinfo_proc2 kproc2; 1431 struct kinfo_proc *dp; 1432 struct proc *p; 1433 const struct proclist_desc *pd; 1434 char *where, *dp2; 1435 int type, op, arg; 1436 u_int elem_size, elem_count; 1437 size_t buflen, needed; 1438 int error; 1439 1440 dp = vwhere; 1441 dp2 = where = vwhere; 1442 buflen = where != NULL ? *sizep : 0; 1443 error = 0; 1444 needed = 0; 1445 type = name[0]; 1446 1447 if (type == KERN_PROC) { 1448 if (namelen != 3 && !(namelen == 2 && name[1] == KERN_PROC_ALL)) 1449 return (EINVAL); 1450 op = name[1]; 1451 if (op != KERN_PROC_ALL) 1452 arg = name[2]; 1453 else 1454 arg = 0; /* Quell compiler warning */ 1455 elem_size = elem_count = 0; /* Ditto */ 1456 } else { 1457 if (namelen != 5) 1458 return (EINVAL); 1459 op = name[1]; 1460 arg = name[2]; 1461 elem_size = name[3]; 1462 elem_count = name[4]; 1463 } 1464 1465 proclist_lock_read(); 1466 1467 pd = proclists; 1468 again: 1469 for (p = LIST_FIRST(pd->pd_list); p != NULL; p = LIST_NEXT(p, p_list)) { 1470 /* 1471 * Skip embryonic processes. 1472 */ 1473 if (p->p_stat == SIDL) 1474 continue; 1475 /* 1476 * TODO - make more efficient (see notes below). 1477 * do by session. 1478 */ 1479 switch (op) { 1480 1481 case KERN_PROC_PID: 1482 /* could do this with just a lookup */ 1483 if (p->p_pid != (pid_t)arg) 1484 continue; 1485 break; 1486 1487 case KERN_PROC_PGRP: 1488 /* could do this by traversing pgrp */ 1489 if (p->p_pgrp->pg_id != (pid_t)arg) 1490 continue; 1491 break; 1492 1493 case KERN_PROC_SESSION: 1494 if (p->p_session->s_sid != (pid_t)arg) 1495 continue; 1496 break; 1497 1498 case KERN_PROC_TTY: 1499 if (arg == (int) KERN_PROC_TTY_REVOKE) { 1500 if ((p->p_flag & P_CONTROLT) == 0 || 1501 p->p_session->s_ttyp == NULL || 1502 p->p_session->s_ttyvp != NULL) 1503 continue; 1504 } else if ((p->p_flag & P_CONTROLT) == 0 || 1505 p->p_session->s_ttyp == NULL) { 1506 if ((dev_t)arg != KERN_PROC_TTY_NODEV) 1507 continue; 1508 } else if (p->p_session->s_ttyp->t_dev != (dev_t)arg) 1509 continue; 1510 break; 1511 1512 case KERN_PROC_UID: 1513 if (p->p_ucred->cr_uid != (uid_t)arg) 1514 continue; 1515 break; 1516 1517 case KERN_PROC_RUID: 1518 if (p->p_cred->p_ruid != (uid_t)arg) 1519 continue; 1520 break; 1521 1522 case KERN_PROC_GID: 1523 if (p->p_ucred->cr_gid != (uid_t)arg) 1524 continue; 1525 break; 1526 1527 case KERN_PROC_RGID: 1528 if (p->p_cred->p_rgid != (uid_t)arg) 1529 continue; 1530 break; 1531 1532 case KERN_PROC_ALL: 1533 /* allow everything */ 1534 break; 1535 1536 default: 1537 error = EINVAL; 1538 goto cleanup; 1539 } 1540 if (type == KERN_PROC) { 1541 if (buflen >= sizeof(struct kinfo_proc)) { 1542 fill_eproc(p, &eproc); 1543 error = copyout((caddr_t)p, &dp->kp_proc, 1544 sizeof(struct proc)); 1545 if (error) 1546 goto cleanup; 1547 error = copyout((caddr_t)&eproc, &dp->kp_eproc, 1548 sizeof(eproc)); 1549 if (error) 1550 goto cleanup; 1551 dp++; 1552 buflen -= sizeof(struct kinfo_proc); 1553 } 1554 needed += sizeof(struct kinfo_proc); 1555 } else { /* KERN_PROC2 */ 1556 if (buflen >= elem_size && elem_count > 0) { 1557 fill_kproc2(p, &kproc2); 1558 /* 1559 * Copy out elem_size, but not larger than 1560 * the size of a struct kinfo_proc2. 1561 */ 1562 error = copyout(&kproc2, dp2, 1563 min(sizeof(kproc2), elem_size)); 1564 if (error) 1565 goto cleanup; 1566 dp2 += elem_size; 1567 buflen -= elem_size; 1568 elem_count--; 1569 } 1570 needed += elem_size; 1571 } 1572 } 1573 pd++; 1574 if (pd->pd_list != NULL) 1575 goto again; 1576 proclist_unlock_read(); 1577 1578 if (where != NULL) { 1579 if (type == KERN_PROC) 1580 *sizep = (caddr_t)dp - where; 1581 else 1582 *sizep = dp2 - where; 1583 if (needed > *sizep) 1584 return (ENOMEM); 1585 } else { 1586 needed += KERN_PROCSLOP; 1587 *sizep = needed; 1588 } 1589 return (0); 1590 cleanup: 1591 proclist_unlock_read(); 1592 return (error); 1593 } 1594 1595 /* 1596 * Fill in an eproc structure for the specified process. 1597 */ 1598 void 1599 fill_eproc(struct proc *p, struct eproc *ep) 1600 { 1601 struct tty *tp; 1602 1603 ep->e_paddr = p; 1604 ep->e_sess = p->p_session; 1605 ep->e_pcred = *p->p_cred; 1606 ep->e_ucred = *p->p_ucred; 1607 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1608 ep->e_vm.vm_rssize = 0; 1609 ep->e_vm.vm_tsize = 0; 1610 ep->e_vm.vm_dsize = 0; 1611 ep->e_vm.vm_ssize = 0; 1612 /* ep->e_vm.vm_pmap = XXX; */ 1613 } else { 1614 struct vmspace *vm = p->p_vmspace; 1615 1616 ep->e_vm.vm_rssize = vm_resident_count(vm); 1617 ep->e_vm.vm_tsize = vm->vm_tsize; 1618 ep->e_vm.vm_dsize = vm->vm_dsize; 1619 ep->e_vm.vm_ssize = vm->vm_ssize; 1620 } 1621 if (p->p_pptr) 1622 ep->e_ppid = p->p_pptr->p_pid; 1623 else 1624 ep->e_ppid = 0; 1625 ep->e_pgid = p->p_pgrp->pg_id; 1626 ep->e_sid = ep->e_sess->s_sid; 1627 ep->e_jobc = p->p_pgrp->pg_jobc; 1628 if ((p->p_flag & P_CONTROLT) && 1629 (tp = ep->e_sess->s_ttyp)) { 1630 ep->e_tdev = tp->t_dev; 1631 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1632 ep->e_tsess = tp->t_session; 1633 } else 1634 ep->e_tdev = NODEV; 1635 if (p->p_wmesg) 1636 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN); 1637 ep->e_xsize = ep->e_xrssize = 0; 1638 ep->e_xccount = ep->e_xswrss = 0; 1639 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 1640 if (SESS_LEADER(p)) 1641 ep->e_flag |= EPROC_SLEADER; 1642 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME); 1643 } 1644 1645 /* 1646 * Fill in an eproc structure for the specified process. 1647 */ 1648 static void 1649 fill_kproc2(struct proc *p, struct kinfo_proc2 *ki) 1650 { 1651 struct tty *tp; 1652 1653 memset(ki, 0, sizeof(*ki)); 1654 1655 ki->p_forw = PTRTOINT64(p->p_forw); 1656 ki->p_back = PTRTOINT64(p->p_back); 1657 ki->p_paddr = PTRTOINT64(p); 1658 1659 ki->p_addr = PTRTOINT64(p->p_addr); 1660 ki->p_fd = PTRTOINT64(p->p_fd); 1661 ki->p_cwdi = PTRTOINT64(p->p_cwdi); 1662 ki->p_stats = PTRTOINT64(p->p_stats); 1663 ki->p_limit = PTRTOINT64(p->p_limit); 1664 ki->p_vmspace = PTRTOINT64(p->p_vmspace); 1665 ki->p_sigacts = PTRTOINT64(p->p_sigacts); 1666 ki->p_sess = PTRTOINT64(p->p_session); 1667 ki->p_tsess = 0; /* may be changed if controlling tty below */ 1668 ki->p_ru = PTRTOINT64(p->p_ru); 1669 1670 ki->p_eflag = 0; 1671 ki->p_exitsig = p->p_exitsig; 1672 ki->p_flag = p->p_flag; 1673 1674 ki->p_pid = p->p_pid; 1675 if (p->p_pptr) 1676 ki->p_ppid = p->p_pptr->p_pid; 1677 else 1678 ki->p_ppid = 0; 1679 ki->p_sid = p->p_session->s_sid; 1680 ki->p__pgid = p->p_pgrp->pg_id; 1681 1682 ki->p_tpgid = NO_PID; /* may be changed if controlling tty below */ 1683 1684 ki->p_uid = p->p_ucred->cr_uid; 1685 ki->p_ruid = p->p_cred->p_ruid; 1686 ki->p_gid = p->p_ucred->cr_gid; 1687 ki->p_rgid = p->p_cred->p_rgid; 1688 1689 memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups, 1690 min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups))); 1691 ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups; 1692 1693 ki->p_jobc = p->p_pgrp->pg_jobc; 1694 if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) { 1695 ki->p_tdev = tp->t_dev; 1696 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 1697 ki->p_tsess = PTRTOINT64(tp->t_session); 1698 } else { 1699 ki->p_tdev = NODEV; 1700 } 1701 1702 ki->p_estcpu = p->p_estcpu; 1703 ki->p_rtime_sec = p->p_rtime.tv_sec; 1704 ki->p_rtime_usec = p->p_rtime.tv_usec; 1705 ki->p_cpticks = p->p_cpticks; 1706 ki->p_pctcpu = p->p_pctcpu; 1707 ki->p_swtime = p->p_swtime; 1708 ki->p_slptime = p->p_slptime; 1709 if (p->p_stat == SONPROC) { 1710 KDASSERT(p->p_cpu != NULL); 1711 ki->p_schedflags = p->p_cpu->ci_schedstate.spc_flags; 1712 } else 1713 ki->p_schedflags = 0; 1714 1715 ki->p_uticks = p->p_uticks; 1716 ki->p_sticks = p->p_sticks; 1717 ki->p_iticks = p->p_iticks; 1718 1719 ki->p_tracep = PTRTOINT64(p->p_tracep); 1720 ki->p_traceflag = p->p_traceflag; 1721 1722 ki->p_holdcnt = p->p_holdcnt; 1723 1724 memcpy(&ki->p_siglist, &p->p_sigctx.ps_siglist, sizeof(ki_sigset_t)); 1725 memcpy(&ki->p_sigmask, &p->p_sigctx.ps_sigmask, sizeof(ki_sigset_t)); 1726 memcpy(&ki->p_sigignore, &p->p_sigctx.ps_sigignore,sizeof(ki_sigset_t)); 1727 memcpy(&ki->p_sigcatch, &p->p_sigctx.ps_sigcatch, sizeof(ki_sigset_t)); 1728 1729 ki->p_stat = p->p_stat; 1730 ki->p_priority = p->p_priority; 1731 ki->p_usrpri = p->p_usrpri; 1732 ki->p_nice = p->p_nice; 1733 1734 ki->p_xstat = p->p_xstat; 1735 ki->p_acflag = p->p_acflag; 1736 1737 strncpy(ki->p_comm, p->p_comm, 1738 min(sizeof(ki->p_comm), sizeof(p->p_comm))); 1739 1740 if (p->p_wmesg) 1741 strncpy(ki->p_wmesg, p->p_wmesg, sizeof(ki->p_wmesg)); 1742 ki->p_wchan = PTRTOINT64(p->p_wchan); 1743 1744 strncpy(ki->p_login, p->p_session->s_login, sizeof(ki->p_login)); 1745 1746 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 1747 ki->p_vm_rssize = 0; 1748 ki->p_vm_tsize = 0; 1749 ki->p_vm_dsize = 0; 1750 ki->p_vm_ssize = 0; 1751 } else { 1752 struct vmspace *vm = p->p_vmspace; 1753 1754 ki->p_vm_rssize = vm_resident_count(vm); 1755 ki->p_vm_tsize = vm->vm_tsize; 1756 ki->p_vm_dsize = vm->vm_dsize; 1757 ki->p_vm_ssize = vm->vm_ssize; 1758 } 1759 1760 if (p->p_session->s_ttyvp) 1761 ki->p_eflag |= EPROC_CTTY; 1762 if (SESS_LEADER(p)) 1763 ki->p_eflag |= EPROC_SLEADER; 1764 1765 /* XXX Is this double check necessary? */ 1766 if ((p->p_flag & P_INMEM) == 0 || P_ZOMBIE(p)) { 1767 ki->p_uvalid = 0; 1768 } else { 1769 ki->p_uvalid = 1; 1770 1771 ki->p_ustart_sec = p->p_stats->p_start.tv_sec; 1772 ki->p_ustart_usec = p->p_stats->p_start.tv_usec; 1773 1774 ki->p_uutime_sec = p->p_stats->p_ru.ru_utime.tv_sec; 1775 ki->p_uutime_usec = p->p_stats->p_ru.ru_utime.tv_usec; 1776 ki->p_ustime_sec = p->p_stats->p_ru.ru_stime.tv_sec; 1777 ki->p_ustime_usec = p->p_stats->p_ru.ru_stime.tv_usec; 1778 1779 ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss; 1780 ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss; 1781 ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss; 1782 ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss; 1783 ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt; 1784 ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt; 1785 ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap; 1786 ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock; 1787 ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock; 1788 ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd; 1789 ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv; 1790 ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals; 1791 ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw; 1792 ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw; 1793 1794 ki->p_uctime_sec = p->p_stats->p_cru.ru_utime.tv_sec + 1795 p->p_stats->p_cru.ru_stime.tv_sec; 1796 ki->p_uctime_usec = p->p_stats->p_cru.ru_utime.tv_usec + 1797 p->p_stats->p_cru.ru_stime.tv_usec; 1798 } 1799 #ifdef MULTIPROCESSOR 1800 if (p->p_cpu != NULL) 1801 ki->p_cpuid = p->p_cpu->ci_cpuid; 1802 else 1803 #endif 1804 ki->p_cpuid = KI_NOCPU; 1805 } 1806 1807 int 1808 sysctl_procargs(int *name, u_int namelen, void *where, size_t *sizep, 1809 struct proc *up) 1810 { 1811 struct ps_strings pss; 1812 struct proc *p; 1813 size_t len, upper_bound, xlen, i; 1814 struct uio auio; 1815 struct iovec aiov; 1816 vaddr_t argv; 1817 pid_t pid; 1818 int nargv, type, error; 1819 char *arg; 1820 char *tmp; 1821 1822 if (namelen != 2) 1823 return (EINVAL); 1824 pid = name[0]; 1825 type = name[1]; 1826 1827 switch (type) { 1828 case KERN_PROC_ARGV: 1829 case KERN_PROC_NARGV: 1830 case KERN_PROC_ENV: 1831 case KERN_PROC_NENV: 1832 /* ok */ 1833 break; 1834 default: 1835 return (EINVAL); 1836 } 1837 1838 /* check pid */ 1839 if ((p = pfind(pid)) == NULL) 1840 return (EINVAL); 1841 1842 /* only root or same user change look at the environment */ 1843 if (type == KERN_PROC_ENV || type == KERN_PROC_NENV) { 1844 if (up->p_ucred->cr_uid != 0) { 1845 if (up->p_cred->p_ruid != p->p_cred->p_ruid || 1846 up->p_cred->p_ruid != p->p_cred->p_svuid) 1847 return (EPERM); 1848 } 1849 } 1850 1851 if (sizep != NULL && where == NULL) { 1852 if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) 1853 *sizep = sizeof (int); 1854 else 1855 *sizep = ARG_MAX; /* XXX XXX XXX */ 1856 return (0); 1857 } 1858 if (where == NULL || sizep == NULL) 1859 return (EINVAL); 1860 1861 /* 1862 * Zombies don't have a stack, so we can't read their psstrings. 1863 * System processes also don't have a user stack. 1864 */ 1865 if (P_ZOMBIE(p) || (p->p_flag & P_SYSTEM) != 0) 1866 return (EINVAL); 1867 1868 /* 1869 * Lock the process down in memory. 1870 */ 1871 /* XXXCDC: how should locking work here? */ 1872 if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) 1873 return (EFAULT); 1874 p->p_vmspace->vm_refcnt++; /* XXX */ 1875 1876 /* 1877 * Allocate a temporary buffer to hold the arguments. 1878 */ 1879 arg = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 1880 1881 /* 1882 * Read in the ps_strings structure. 1883 */ 1884 aiov.iov_base = &pss; 1885 aiov.iov_len = sizeof(pss); 1886 auio.uio_iov = &aiov; 1887 auio.uio_iovcnt = 1; 1888 auio.uio_offset = (vaddr_t)p->p_psstr; 1889 auio.uio_resid = sizeof(pss); 1890 auio.uio_segflg = UIO_SYSSPACE; 1891 auio.uio_rw = UIO_READ; 1892 auio.uio_procp = NULL; 1893 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1894 if (error) 1895 goto done; 1896 1897 if (type == KERN_PROC_ARGV || type == KERN_PROC_NARGV) 1898 memcpy(&nargv, (char *)&pss + p->p_psnargv, sizeof(nargv)); 1899 else 1900 memcpy(&nargv, (char *)&pss + p->p_psnenv, sizeof(nargv)); 1901 if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) { 1902 error = copyout(&nargv, where, sizeof(nargv)); 1903 *sizep = sizeof(nargv); 1904 goto done; 1905 } 1906 /* 1907 * Now read the address of the argument vector. 1908 */ 1909 switch (type) { 1910 case KERN_PROC_ARGV: 1911 /* XXX compat32 stuff here */ 1912 memcpy(&tmp, (char *)&pss + p->p_psargv, sizeof(tmp)); 1913 break; 1914 case KERN_PROC_ENV: 1915 memcpy(&tmp, (char *)&pss + p->p_psenv, sizeof(tmp)); 1916 break; 1917 default: 1918 return (EINVAL); 1919 } 1920 auio.uio_offset = (off_t)(long)tmp; 1921 aiov.iov_base = &argv; 1922 aiov.iov_len = sizeof(argv); 1923 auio.uio_iov = &aiov; 1924 auio.uio_iovcnt = 1; 1925 auio.uio_resid = sizeof(argv); 1926 auio.uio_segflg = UIO_SYSSPACE; 1927 auio.uio_rw = UIO_READ; 1928 auio.uio_procp = NULL; 1929 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1930 if (error) 1931 goto done; 1932 1933 /* 1934 * Now copy in the actual argument vector, one page at a time, 1935 * since we don't know how long the vector is (though, we do 1936 * know how many NUL-terminated strings are in the vector). 1937 */ 1938 len = 0; 1939 upper_bound = *sizep; 1940 for (; nargv != 0 && len < upper_bound; len += xlen) { 1941 aiov.iov_base = arg; 1942 aiov.iov_len = PAGE_SIZE; 1943 auio.uio_iov = &aiov; 1944 auio.uio_iovcnt = 1; 1945 auio.uio_offset = argv + len; 1946 xlen = PAGE_SIZE - ((argv + len) & PAGE_MASK); 1947 auio.uio_resid = xlen; 1948 auio.uio_segflg = UIO_SYSSPACE; 1949 auio.uio_rw = UIO_READ; 1950 auio.uio_procp = NULL; 1951 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1952 if (error) 1953 goto done; 1954 1955 for (i = 0; i < xlen && nargv != 0; i++) { 1956 if (arg[i] == '\0') 1957 nargv--; /* one full string */ 1958 } 1959 1960 /* 1961 * Make sure we don't copyout past the end of the user's 1962 * buffer. 1963 */ 1964 if (len + i > upper_bound) 1965 i = upper_bound - len; 1966 1967 error = copyout(arg, (char *)where + len, i); 1968 if (error) 1969 break; 1970 1971 if (nargv == 0) { 1972 len += i; 1973 break; 1974 } 1975 } 1976 *sizep = len; 1977 1978 done: 1979 uvmspace_free(p->p_vmspace); 1980 1981 free(arg, M_TEMP); 1982 return (error); 1983 } 1984 1985 #if NPTY > 0 1986 int pty_maxptys(int, int); /* defined in kern/tty_pty.c */ 1987 1988 /* 1989 * Validate parameters and get old / set new parameters 1990 * for pty sysctl function. 1991 */ 1992 static int 1993 sysctl_pty(void *oldp, size_t *oldlenp, void *newp, size_t newlen) 1994 { 1995 int error = 0; 1996 int oldmax = 0, newmax = 0; 1997 1998 /* get current value of maxptys */ 1999 oldmax = pty_maxptys(0, 0); 2000 2001 SYSCTL_SCALAR_CORE_TYP(oldp, oldlenp, &oldmax, int) 2002 2003 if (!error && newp) { 2004 SYSCTL_SCALAR_NEWPCHECK_TYP(newp, newlen, int) 2005 SYSCTL_SCALAR_NEWPCOP_TYP(newp, &newmax, int) 2006 2007 if (newmax != pty_maxptys(newmax, (newp != NULL))) 2008 return (EINVAL); 2009 2010 } 2011 2012 return (error); 2013 } 2014 #endif /* NPTY > 0 */ 2015 2016 static int 2017 sysctl_dotkstat(name, namelen, where, sizep, newp) 2018 int *name; 2019 u_int namelen; 2020 void *where; 2021 size_t *sizep; 2022 void *newp; 2023 { 2024 /* all sysctl names at this level are terminal */ 2025 if (namelen != 1) 2026 return (ENOTDIR); /* overloaded */ 2027 2028 switch (name[0]) { 2029 case KERN_TKSTAT_NIN: 2030 return (sysctl_rdquad(where, sizep, newp, tk_nin)); 2031 case KERN_TKSTAT_NOUT: 2032 return (sysctl_rdquad(where, sizep, newp, tk_nout)); 2033 case KERN_TKSTAT_CANCC: 2034 return (sysctl_rdquad(where, sizep, newp, tk_cancc)); 2035 case KERN_TKSTAT_RAWCC: 2036 return (sysctl_rdquad(where, sizep, newp, tk_rawcc)); 2037 default: 2038 return (EOPNOTSUPP); 2039 } 2040 } 2041