This source file includes following definitions.
- sys___sysctl
- kern_sysctl
- hw_sysctl
- debug_sysctl
- sysctl_int_lower
- sysctl_int
- sysctl_rdint
- sysctl_int_arr
- sysctl_quad
- sysctl_rdquad
- sysctl_string
- sysctl_tstring
- sysctl__string
- sysctl_rdstring
- sysctl_struct
- sysctl_rdstruct
- sysctl_file
- sysctl_doproc
- fill_eproc
- fill_kproc2
- sysctl_proc_args
- sysctl_diskinit
- sysctl_sysvipc
- sysctl_intrcnt
- sysctl_sensors
- sysctl_emul
- sysctl_cptime2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/proc.h>
47 #include <sys/resourcevar.h>
48 #include <sys/file.h>
49 #include <sys/vnode.h>
50 #include <sys/unistd.h>
51 #include <sys/buf.h>
52 #include <sys/ioctl.h>
53 #include <sys/tty.h>
54 #include <sys/disklabel.h>
55 #include <sys/disk.h>
56 #include <uvm/uvm_extern.h>
57 #include <sys/sysctl.h>
58 #include <sys/msgbuf.h>
59 #include <sys/dkstat.h>
60 #include <sys/vmmeter.h>
61 #include <sys/namei.h>
62 #include <sys/exec.h>
63 #include <sys/mbuf.h>
64 #include <sys/sensors.h>
65 #ifdef __HAVE_TIMECOUNTER
66 #include <sys/timetc.h>
67 #endif
68 #include <sys/evcount.h>
69
70 #include <sys/mount.h>
71 #include <sys/syscallargs.h>
72 #include <dev/rndvar.h>
73
74 #ifdef DDB
75 #include <ddb/db_var.h>
76 #endif
77
78 #ifdef SYSVMSG
79 #include <sys/msg.h>
80 #endif
81 #ifdef SYSVSEM
82 #include <sys/sem.h>
83 #endif
84 #ifdef SYSVSHM
85 #include <sys/shm.h>
86 #endif
87
88 #define PTRTOINT64(_x) ((u_int64_t)(u_long)(_x))
89
90 extern struct forkstat forkstat;
91 extern struct nchstats nchstats;
92 extern int nselcoll, fscale;
93 extern struct disklist_head disklist;
94 extern fixpt_t ccpu;
95 extern long numvnodes;
96
97 extern void nmbclust_update(void);
98
99 int sysctl_diskinit(int, struct proc *);
100 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
101 int sysctl_intrcnt(int *, u_int, void *, size_t *);
102 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t);
103 int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t);
104 int sysctl_cptime2(int *, u_int, void *, size_t *, void *, size_t);
105
106 int (*cpu_cpuspeed)(int *);
107 void (*cpu_setperf)(int);
108 int perflevel = 100;
109
110
111
112
113
114 struct rwlock sysctl_lock = RWLOCK_INITIALIZER("sysctllk");
115 struct rwlock sysctl_disklock = RWLOCK_INITIALIZER("sysctldlk");
116
117 int
118 sys___sysctl(struct proc *p, void *v, register_t *retval)
119 {
120 struct sys___sysctl_args
121
122
123
124
125
126
127 *uap = v;
128 int error, dolock = 1;
129 size_t savelen = 0, oldlen = 0;
130 sysctlfn *fn;
131 int name[CTL_MAXNAME];
132
133 if (SCARG(uap, new) != NULL &&
134 (error = suser(p, 0)))
135 return (error);
136
137
138
139 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
140 return (EINVAL);
141 error = copyin(SCARG(uap, name), name,
142 SCARG(uap, namelen) * sizeof(int));
143 if (error)
144 return (error);
145
146 switch (name[0]) {
147 case CTL_KERN:
148 fn = kern_sysctl;
149 if (name[1] == KERN_VNODE)
150 dolock = 0;
151 break;
152 case CTL_HW:
153 fn = hw_sysctl;
154 break;
155 case CTL_VM:
156 fn = uvm_sysctl;
157 break;
158 case CTL_NET:
159 fn = net_sysctl;
160 break;
161 case CTL_FS:
162 fn = fs_sysctl;
163 break;
164 case CTL_VFS:
165 fn = vfs_sysctl;
166 break;
167 case CTL_MACHDEP:
168 fn = cpu_sysctl;
169 break;
170 #ifdef DEBUG
171 case CTL_DEBUG:
172 fn = debug_sysctl;
173 break;
174 #endif
175 #ifdef DDB
176 case CTL_DDB:
177 fn = ddb_sysctl;
178 break;
179 #endif
180 default:
181 return (EOPNOTSUPP);
182 }
183
184 if (SCARG(uap, oldlenp) &&
185 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
186 return (error);
187 if (SCARG(uap, old) != NULL) {
188 if ((error = rw_enter(&sysctl_lock, RW_WRITE|RW_INTR)) != 0)
189 return (error);
190 if (dolock) {
191 if (atop(oldlen) > uvmexp.wiredmax - uvmexp.wired) {
192 rw_exit_write(&sysctl_lock);
193 return (ENOMEM);
194 }
195 error = uvm_vslock(p, SCARG(uap, old), oldlen,
196 VM_PROT_READ|VM_PROT_WRITE);
197 if (error) {
198 rw_exit_write(&sysctl_lock);
199 return (error);
200 }
201 }
202 savelen = oldlen;
203 }
204 error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old),
205 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
206 if (SCARG(uap, old) != NULL) {
207 if (dolock)
208 uvm_vsunlock(p, SCARG(uap, old), savelen);
209 rw_exit_write(&sysctl_lock);
210 }
211 if (error)
212 return (error);
213 if (SCARG(uap, oldlenp))
214 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
215 return (error);
216 }
217
218
219
220
221 char hostname[MAXHOSTNAMELEN];
222 int hostnamelen;
223 char domainname[MAXHOSTNAMELEN];
224 int domainnamelen;
225 long hostid;
226 char *disknames = NULL;
227 struct diskstats *diskstats = NULL;
228 #ifdef INSECURE
229 int securelevel = -1;
230 #else
231 int securelevel;
232 #endif
233
234
235
236
237 int
238 kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
239 size_t newlen, struct proc *p)
240 {
241 int error, level, inthostid, stackgap;
242 extern int somaxconn, sominconn;
243 extern int usermount, nosuidcoredump;
244 extern long cp_time[CPUSTATES];
245 extern int stackgap_random;
246 #ifdef CRYPTO
247 extern int usercrypto;
248 extern int userasymcrypto;
249 extern int cryptodevallowsoft;
250 #endif
251 extern int maxlocksperuid;
252
253
254 if (namelen != 1) {
255 switch (name[0]) {
256 case KERN_PROC:
257 case KERN_PROC2:
258 case KERN_PROF:
259 case KERN_MALLOCSTATS:
260 case KERN_TTY:
261 case KERN_POOL:
262 case KERN_PROC_ARGS:
263 case KERN_SYSVIPC_INFO:
264 case KERN_SEMINFO:
265 case KERN_SHMINFO:
266 case KERN_INTRCNT:
267 case KERN_WATCHDOG:
268 case KERN_EMUL:
269 case KERN_EVCOUNT:
270 #ifdef __HAVE_TIMECOUNTER
271 case KERN_TIMECOUNTER:
272 #endif
273 case KERN_CPTIME2:
274 break;
275 default:
276 return (ENOTDIR);
277 }
278 }
279
280 switch (name[0]) {
281 case KERN_OSTYPE:
282 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
283 case KERN_OSRELEASE:
284 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
285 case KERN_OSREV:
286 return (sysctl_rdint(oldp, oldlenp, newp, OpenBSD));
287 case KERN_OSVERSION:
288 return (sysctl_rdstring(oldp, oldlenp, newp, osversion));
289 case KERN_VERSION:
290 return (sysctl_rdstring(oldp, oldlenp, newp, version));
291 case KERN_MAXVNODES:
292 return(sysctl_int(oldp, oldlenp, newp, newlen, &maxvnodes));
293 case KERN_MAXPROC:
294 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
295 case KERN_MAXFILES:
296 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
297 case KERN_NFILES:
298 return (sysctl_rdint(oldp, oldlenp, newp, nfiles));
299 case KERN_TTYCOUNT:
300 return (sysctl_rdint(oldp, oldlenp, newp, tty_count));
301 case KERN_NUMVNODES:
302 return (sysctl_rdint(oldp, oldlenp, newp, numvnodes));
303 case KERN_ARGMAX:
304 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
305 case KERN_NSELCOLL:
306 return (sysctl_rdint(oldp, oldlenp, newp, nselcoll));
307 case KERN_SECURELVL:
308 level = securelevel;
309 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
310 newp == NULL)
311 return (error);
312 if ((securelevel > 0 || level < -1) &&
313 level < securelevel && p->p_pid != 1)
314 return (EPERM);
315 securelevel = level;
316 return (0);
317 case KERN_HOSTNAME:
318 error = sysctl_tstring(oldp, oldlenp, newp, newlen,
319 hostname, sizeof(hostname));
320 if (newp && !error)
321 hostnamelen = newlen;
322 return (error);
323 case KERN_DOMAINNAME:
324 error = sysctl_tstring(oldp, oldlenp, newp, newlen,
325 domainname, sizeof(domainname));
326 if (newp && !error)
327 domainnamelen = newlen;
328 return (error);
329 case KERN_HOSTID:
330 inthostid = hostid;
331 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
332 hostid = inthostid;
333 return (error);
334 case KERN_CLOCKRATE:
335 return (sysctl_clockrate(oldp, oldlenp));
336 case KERN_BOOTTIME:
337 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
338 sizeof(struct timeval)));
339 case KERN_VNODE:
340 return (sysctl_vnode(oldp, oldlenp, p));
341 #ifndef SMALL_KERNEL
342 case KERN_PROC:
343 case KERN_PROC2:
344 return (sysctl_doproc(name, namelen, oldp, oldlenp));
345 case KERN_PROC_ARGS:
346 return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp,
347 p));
348 #endif
349 case KERN_FILE:
350 return (sysctl_file(oldp, oldlenp));
351 case KERN_MBSTAT:
352 return (sysctl_rdstruct(oldp, oldlenp, newp, &mbstat,
353 sizeof(mbstat)));
354 #ifdef GPROF
355 case KERN_PROF:
356 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
357 newp, newlen));
358 #endif
359 case KERN_POSIX1:
360 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
361 case KERN_NGROUPS:
362 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
363 case KERN_JOB_CONTROL:
364 return (sysctl_rdint(oldp, oldlenp, newp, 1));
365 case KERN_SAVED_IDS:
366 #ifdef _POSIX_SAVED_IDS
367 return (sysctl_rdint(oldp, oldlenp, newp, 1));
368 #else
369 return (sysctl_rdint(oldp, oldlenp, newp, 0));
370 #endif
371 case KERN_MAXPARTITIONS:
372 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
373 case KERN_RAWPARTITION:
374 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
375 case KERN_SOMAXCONN:
376 return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn));
377 case KERN_SOMINCONN:
378 return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn));
379 case KERN_USERMOUNT:
380 return (sysctl_int(oldp, oldlenp, newp, newlen, &usermount));
381 case KERN_RND:
382 return (sysctl_rdstruct(oldp, oldlenp, newp, &rndstats,
383 sizeof(rndstats)));
384 case KERN_ARND: {
385 char buf[256];
386
387 if (*oldlenp > sizeof(buf))
388 *oldlenp = sizeof(buf);
389 if (oldp) {
390 arc4random_bytes(buf, *oldlenp);
391 if ((error = copyout(buf, oldp, *oldlenp)))
392 return (error);
393 }
394 return (0);
395 }
396 case KERN_NOSUIDCOREDUMP:
397 return (sysctl_int(oldp, oldlenp, newp, newlen, &nosuidcoredump));
398 case KERN_FSYNC:
399 return (sysctl_rdint(oldp, oldlenp, newp, 1));
400 case KERN_SYSVMSG:
401 #ifdef SYSVMSG
402 return (sysctl_rdint(oldp, oldlenp, newp, 1));
403 #else
404 return (sysctl_rdint(oldp, oldlenp, newp, 0));
405 #endif
406 case KERN_SYSVSEM:
407 #ifdef SYSVSEM
408 return (sysctl_rdint(oldp, oldlenp, newp, 1));
409 #else
410 return (sysctl_rdint(oldp, oldlenp, newp, 0));
411 #endif
412 case KERN_SYSVSHM:
413 #ifdef SYSVSHM
414 return (sysctl_rdint(oldp, oldlenp, newp, 1));
415 #else
416 return (sysctl_rdint(oldp, oldlenp, newp, 0));
417 #endif
418 case KERN_MSGBUFSIZE:
419
420
421
422
423 if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
424 return (ENXIO);
425 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs));
426 case KERN_MSGBUF:
427
428 if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
429 return (ENXIO);
430 return (sysctl_rdstruct(oldp, oldlenp, newp, msgbufp,
431 msgbufp->msg_bufs + offsetof(struct msgbuf, msg_bufc)));
432 case KERN_MALLOCSTATS:
433 return (sysctl_malloc(name + 1, namelen - 1, oldp, oldlenp,
434 newp, newlen, p));
435 case KERN_CPTIME:
436 {
437 CPU_INFO_ITERATOR cii;
438 struct cpu_info *ci;
439 int i;
440
441 bzero(cp_time, sizeof(cp_time));
442
443 CPU_INFO_FOREACH(cii, ci) {
444 for (i = 0; i < CPUSTATES; i++)
445 cp_time[i] += ci->ci_schedstate.spc_cp_time[i];
446 }
447
448 return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time,
449 sizeof(cp_time)));
450 }
451 case KERN_NCHSTATS:
452 return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats,
453 sizeof(struct nchstats)));
454 case KERN_FORKSTAT:
455 return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat,
456 sizeof(struct forkstat)));
457 case KERN_TTY:
458 return (sysctl_tty(name + 1, namelen - 1, oldp, oldlenp,
459 newp, newlen));
460 case KERN_FSCALE:
461 return (sysctl_rdint(oldp, oldlenp, newp, fscale));
462 case KERN_CCPU:
463 return (sysctl_rdint(oldp, oldlenp, newp, ccpu));
464 case KERN_NPROCS:
465 return (sysctl_rdint(oldp, oldlenp, newp, nprocs));
466 case KERN_POOL:
467 return (sysctl_dopool(name + 1, namelen - 1, oldp, oldlenp));
468 case KERN_STACKGAPRANDOM:
469 stackgap = stackgap_random;
470 error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap);
471 if (error)
472 return (error);
473
474
475
476 if ((stackgap < ALIGNBYTES && stackgap != 0) ||
477 !powerof2(stackgap) || stackgap >= MAXSSIZ)
478 return (EINVAL);
479 stackgap_random = stackgap;
480 return (0);
481 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
482 case KERN_SYSVIPC_INFO:
483 return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp));
484 #endif
485 #ifdef CRYPTO
486 case KERN_USERCRYPTO:
487 return (sysctl_int(oldp, oldlenp, newp, newlen, &usercrypto));
488 case KERN_USERASYMCRYPTO:
489 return (sysctl_int(oldp, oldlenp, newp, newlen,
490 &userasymcrypto));
491 case KERN_CRYPTODEVALLOWSOFT:
492 return (sysctl_int(oldp, oldlenp, newp, newlen,
493 &cryptodevallowsoft));
494 #endif
495 case KERN_SPLASSERT:
496 return (sysctl_int(oldp, oldlenp, newp, newlen,
497 &splassert_ctl));
498 #ifdef SYSVSEM
499 case KERN_SEMINFO:
500 return (sysctl_sysvsem(name + 1, namelen - 1, oldp, oldlenp,
501 newp, newlen));
502 #endif
503 #ifdef SYSVSHM
504 case KERN_SHMINFO:
505 return (sysctl_sysvshm(name + 1, namelen - 1, oldp, oldlenp,
506 newp, newlen));
507 #endif
508 #ifndef SMALL_KERNEL
509 case KERN_INTRCNT:
510 return (sysctl_intrcnt(name + 1, namelen - 1, oldp, oldlenp));
511 case KERN_WATCHDOG:
512 return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp,
513 newp, newlen));
514 case KERN_EMUL:
515 return (sysctl_emul(name + 1, namelen - 1, oldp, oldlenp,
516 newp, newlen));
517 #endif
518 case KERN_MAXCLUSTERS:
519 error = sysctl_int(oldp, oldlenp, newp, newlen, &nmbclust);
520 if (!error)
521 nmbclust_update();
522 return (error);
523 #ifndef SMALL_KERNEL
524 case KERN_EVCOUNT:
525 return (evcount_sysctl(name + 1, namelen - 1, oldp, oldlenp,
526 newp, newlen));
527 #endif
528 #ifdef __HAVE_TIMECOUNTER
529 case KERN_TIMECOUNTER:
530 return (sysctl_tc(name + 1, namelen - 1, oldp, oldlenp,
531 newp, newlen));
532 #endif
533 case KERN_MAXLOCKSPERUID:
534 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxlocksperuid));
535 case KERN_CPTIME2:
536 return (sysctl_cptime2(name + 1, namelen -1, oldp, oldlenp,
537 newp, newlen));
538 default:
539 return (EOPNOTSUPP);
540 }
541
542 }
543
544
545
546
547 char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver;
548
549 int
550 hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
551 size_t newlen, struct proc *p)
552 {
553 extern char machine[], cpu_model[];
554 int err, cpuspeed;
555
556
557 if (name[0] != HW_SENSORS && namelen != 1)
558 return (ENOTDIR);
559
560 switch (name[0]) {
561 case HW_MACHINE:
562 return (sysctl_rdstring(oldp, oldlenp, newp, machine));
563 case HW_MODEL:
564 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
565 case HW_NCPU:
566 return (sysctl_rdint(oldp, oldlenp, newp, ncpus));
567 case HW_BYTEORDER:
568 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
569 case HW_PHYSMEM:
570 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
571 case HW_USERMEM:
572 return (sysctl_rdint(oldp, oldlenp, newp,
573 ctob(physmem - uvmexp.wired)));
574 case HW_PAGESIZE:
575 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
576 case HW_DISKNAMES:
577 err = sysctl_diskinit(0, p);
578 if (err)
579 return err;
580 if (disknames)
581 return (sysctl_rdstring(oldp, oldlenp, newp,
582 disknames));
583 else
584 return (sysctl_rdstring(oldp, oldlenp, newp, ""));
585 case HW_DISKSTATS:
586 err = sysctl_diskinit(1, p);
587 if (err)
588 return err;
589 return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats,
590 disk_count * sizeof(struct diskstats)));
591 case HW_DISKCOUNT:
592 return (sysctl_rdint(oldp, oldlenp, newp, disk_count));
593 #ifndef SMALL_KERNEL
594 case HW_SENSORS:
595 return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp,
596 newp, newlen));
597 #endif
598 case HW_CPUSPEED:
599 if (!cpu_cpuspeed)
600 return (EOPNOTSUPP);
601 err = cpu_cpuspeed(&cpuspeed);
602 if (err)
603 return err;
604 return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed));
605 case HW_SETPERF:
606 if (!cpu_setperf)
607 return (EOPNOTSUPP);
608 err = sysctl_int(oldp, oldlenp, newp, newlen, &perflevel);
609 if (err)
610 return err;
611 if (perflevel > 100)
612 perflevel = 100;
613 if (perflevel < 0)
614 perflevel = 0;
615 if (newp)
616 cpu_setperf(perflevel);
617 return (0);
618 case HW_VENDOR:
619 if (hw_vendor)
620 return (sysctl_rdstring(oldp, oldlenp, newp,
621 hw_vendor));
622 else
623 return (EOPNOTSUPP);
624 case HW_PRODUCT:
625 if (hw_prod)
626 return (sysctl_rdstring(oldp, oldlenp, newp, hw_prod));
627 else
628 return (EOPNOTSUPP);
629 case HW_VERSION:
630 if (hw_ver)
631 return (sysctl_rdstring(oldp, oldlenp, newp, hw_ver));
632 else
633 return (EOPNOTSUPP);
634 case HW_SERIALNO:
635 if (hw_serial)
636 return (sysctl_rdstring(oldp, oldlenp, newp,
637 hw_serial));
638 else
639 return (EOPNOTSUPP);
640 case HW_UUID:
641 if (hw_uuid)
642 return (sysctl_rdstring(oldp, oldlenp, newp, hw_uuid));
643 else
644 return (EOPNOTSUPP);
645 default:
646 return (EOPNOTSUPP);
647 }
648
649 }
650
651 #ifdef DEBUG
652
653
654
655 extern struct ctldebug debug0, debug1;
656 struct ctldebug debug2, debug3, debug4;
657 struct ctldebug debug5, debug6, debug7, debug8, debug9;
658 struct ctldebug debug10, debug11, debug12, debug13, debug14;
659 struct ctldebug debug15, debug16, debug17, debug18, debug19;
660 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
661 &debug0, &debug1, &debug2, &debug3, &debug4,
662 &debug5, &debug6, &debug7, &debug8, &debug9,
663 &debug10, &debug11, &debug12, &debug13, &debug14,
664 &debug15, &debug16, &debug17, &debug18, &debug19,
665 };
666 int
667 debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
668 size_t newlen, struct proc *p)
669 {
670 struct ctldebug *cdp;
671
672
673 if (namelen != 2)
674 return (ENOTDIR);
675 cdp = debugvars[name[0]];
676 if (cdp->debugname == 0)
677 return (EOPNOTSUPP);
678 switch (name[1]) {
679 case CTL_DEBUG_NAME:
680 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
681 case CTL_DEBUG_VALUE:
682 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
683 default:
684 return (EOPNOTSUPP);
685 }
686
687 }
688 #endif
689
690
691
692
693 int
694 sysctl_int_lower(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp)
695 {
696 unsigned int oval = *valp, val = *valp;
697 int error;
698
699 if (newp == NULL)
700 return (sysctl_rdint(oldp, oldlenp, newp, *valp));
701
702 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val)))
703 return (error);
704 if (val > oval)
705 return (EPERM);
706 *(unsigned int *)valp = val;
707 return (0);
708 }
709
710
711
712
713
714 int
715 sysctl_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp)
716 {
717 int error = 0;
718
719 if (oldp && *oldlenp < sizeof(int))
720 return (ENOMEM);
721 if (newp && newlen != sizeof(int))
722 return (EINVAL);
723 *oldlenp = sizeof(int);
724 if (oldp)
725 error = copyout(valp, oldp, sizeof(int));
726 if (error == 0 && newp)
727 error = copyin(newp, valp, sizeof(int));
728 return (error);
729 }
730
731
732
733
734 int
735 sysctl_rdint(void *oldp, size_t *oldlenp, void *newp, int val)
736 {
737 int error = 0;
738
739 if (oldp && *oldlenp < sizeof(int))
740 return (ENOMEM);
741 if (newp)
742 return (EPERM);
743 *oldlenp = sizeof(int);
744 if (oldp)
745 error = copyout((caddr_t)&val, oldp, sizeof(int));
746 return (error);
747 }
748
749
750
751
752 int
753 sysctl_int_arr(int **valpp, int *name, u_int namelen, void *oldp,
754 size_t *oldlenp, void *newp, size_t newlen)
755 {
756 if (namelen > 1)
757 return (ENOTDIR);
758 if (name[0] < 0 || valpp[name[0]] == NULL)
759 return (EOPNOTSUPP);
760 return (sysctl_int(oldp, oldlenp, newp, newlen, valpp[name[0]]));
761 }
762
763
764
765
766
767 int
768 sysctl_quad(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
769 int64_t *valp)
770 {
771 int error = 0;
772
773 if (oldp && *oldlenp < sizeof(int64_t))
774 return (ENOMEM);
775 if (newp && newlen != sizeof(int64_t))
776 return (EINVAL);
777 *oldlenp = sizeof(int64_t);
778 if (oldp)
779 error = copyout(valp, oldp, sizeof(int64_t));
780 if (error == 0 && newp)
781 error = copyin(newp, valp, sizeof(int64_t));
782 return (error);
783 }
784
785
786
787
788 int
789 sysctl_rdquad(void *oldp, size_t *oldlenp, void *newp, int64_t val)
790 {
791 int error = 0;
792
793 if (oldp && *oldlenp < sizeof(int64_t))
794 return (ENOMEM);
795 if (newp)
796 return (EPERM);
797 *oldlenp = sizeof(int64_t);
798 if (oldp)
799 error = copyout((caddr_t)&val, oldp, sizeof(int64_t));
800 return (error);
801 }
802
803
804
805
806
807 int
808 sysctl_string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str,
809 int maxlen)
810 {
811 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0);
812 }
813
814 int
815 sysctl_tstring(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
816 char *str, int maxlen)
817 {
818 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1);
819 }
820
821 int
822 sysctl__string(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
823 char *str, int maxlen, int trunc)
824 {
825 int len, error = 0;
826 char c;
827
828 len = strlen(str) + 1;
829 if (oldp && *oldlenp < len) {
830 if (trunc == 0 || *oldlenp == 0)
831 return (ENOMEM);
832 }
833 if (newp && newlen >= maxlen)
834 return (EINVAL);
835 if (oldp) {
836 if (trunc && *oldlenp < len) {
837
838 c = str[*oldlenp-1];
839 str[*oldlenp-1] = '\0';
840 error = copyout(str, oldp, *oldlenp);
841 str[*oldlenp-1] = c;
842 } else {
843 *oldlenp = len;
844 error = copyout(str, oldp, len);
845 }
846 }
847 if (error == 0 && newp) {
848 error = copyin(newp, str, newlen);
849 str[newlen] = 0;
850 }
851 return (error);
852 }
853
854
855
856
857 int
858 sysctl_rdstring(void *oldp, size_t *oldlenp, void *newp, const char *str)
859 {
860 int len, error = 0;
861
862 len = strlen(str) + 1;
863 if (oldp && *oldlenp < len)
864 return (ENOMEM);
865 if (newp)
866 return (EPERM);
867 *oldlenp = len;
868 if (oldp)
869 error = copyout(str, oldp, len);
870 return (error);
871 }
872
873
874
875
876
877 int
878 sysctl_struct(void *oldp, size_t *oldlenp, void *newp, size_t newlen, void *sp,
879 int len)
880 {
881 int error = 0;
882
883 if (oldp && *oldlenp < len)
884 return (ENOMEM);
885 if (newp && newlen > len)
886 return (EINVAL);
887 if (oldp) {
888 *oldlenp = len;
889 error = copyout(sp, oldp, len);
890 }
891 if (error == 0 && newp)
892 error = copyin(newp, sp, len);
893 return (error);
894 }
895
896
897
898
899
900 int
901 sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp,
902 int len)
903 {
904 int error = 0;
905
906 if (oldp && *oldlenp < len)
907 return (ENOMEM);
908 if (newp)
909 return (EPERM);
910 *oldlenp = len;
911 if (oldp)
912 error = copyout(sp, oldp, len);
913 return (error);
914 }
915
916
917
918
919 int
920 sysctl_file(char *where, size_t *sizep)
921 {
922 int buflen, error;
923 struct file *fp;
924 char *start = where;
925
926 buflen = *sizep;
927 if (where == NULL) {
928
929
930
931 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
932 return (0);
933 }
934
935
936
937
938 if (buflen < sizeof(filehead)) {
939 *sizep = 0;
940 return (0);
941 }
942 error = copyout((caddr_t)&filehead, where, sizeof(filehead));
943 if (error)
944 return (error);
945 buflen -= sizeof(filehead);
946 where += sizeof(filehead);
947
948
949
950
951 LIST_FOREACH(fp, &filehead, f_list) {
952 if (buflen < sizeof(struct file)) {
953 *sizep = where - start;
954 return (ENOMEM);
955 }
956 error = copyout((caddr_t)fp, where, sizeof (struct file));
957 if (error)
958 return (error);
959 buflen -= sizeof(struct file);
960 where += sizeof(struct file);
961 }
962 *sizep = where - start;
963 return (0);
964 }
965
966 #ifndef SMALL_KERNEL
967
968
969
970
971 #define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
972
973 int
974 sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep)
975 {
976 struct kinfo_proc2 *kproc2 = NULL;
977 struct eproc *eproc = NULL;
978 struct proc *p;
979 char *dp;
980 int arg, buflen, doingzomb, elem_size, elem_count;
981 int error, needed, type, op;
982
983 dp = where;
984 buflen = where != NULL ? *sizep : 0;
985 needed = error = 0;
986 type = name[0];
987
988 if (type == KERN_PROC) {
989 if (namelen != 3 && !(namelen == 2 &&
990 (name[1] == KERN_PROC_ALL || name[1] == KERN_PROC_KTHREAD)))
991 return (EINVAL);
992 op = name[1];
993 arg = op == KERN_PROC_ALL ? 0 : name[2];
994 elem_size = elem_count = 0;
995 eproc = malloc(sizeof(struct eproc), M_TEMP, M_WAITOK);
996 } else {
997 if (namelen != 5 || name[3] < 0 || name[4] < 0)
998 return (EINVAL);
999 op = name[1];
1000 arg = name[2];
1001 elem_size = name[3];
1002 elem_count = name[4];
1003 kproc2 = malloc(sizeof(struct kinfo_proc2), M_TEMP, M_WAITOK);
1004 }
1005 p = LIST_FIRST(&allproc);
1006 doingzomb = 0;
1007 again:
1008 for (; p != 0; p = LIST_NEXT(p, p_list)) {
1009
1010
1011
1012 if (p->p_stat == SIDL)
1013 continue;
1014
1015
1016
1017 switch (op) {
1018
1019 case KERN_PROC_PID:
1020
1021 if (p->p_pid != (pid_t)arg)
1022 continue;
1023 break;
1024
1025 case KERN_PROC_PGRP:
1026
1027 if (p->p_pgrp->pg_id != (pid_t)arg)
1028 continue;
1029 break;
1030
1031 case KERN_PROC_SESSION:
1032 if (p->p_session->s_leader == NULL ||
1033 p->p_session->s_leader->p_pid != (pid_t)arg)
1034 continue;
1035 break;
1036
1037 case KERN_PROC_TTY:
1038 if ((p->p_flag & P_CONTROLT) == 0 ||
1039 p->p_session->s_ttyp == NULL ||
1040 p->p_session->s_ttyp->t_dev != (dev_t)arg)
1041 continue;
1042 break;
1043
1044 case KERN_PROC_UID:
1045 if (p->p_ucred->cr_uid != (uid_t)arg)
1046 continue;
1047 break;
1048
1049 case KERN_PROC_RUID:
1050 if (p->p_cred->p_ruid != (uid_t)arg)
1051 continue;
1052 break;
1053
1054 case KERN_PROC_ALL:
1055 if (p->p_flag & P_SYSTEM)
1056 continue;
1057 break;
1058 case KERN_PROC_KTHREAD:
1059
1060 break;
1061 default:
1062 error = EINVAL;
1063 goto err;
1064 }
1065 if (type == KERN_PROC) {
1066 if (buflen >= sizeof(struct kinfo_proc)) {
1067 fill_eproc(p, eproc);
1068 error = copyout((caddr_t)p,
1069 &((struct kinfo_proc *)dp)->kp_proc,
1070 sizeof(struct proc));
1071 if (error)
1072 goto err;
1073 error = copyout((caddr_t)eproc,
1074 &((struct kinfo_proc *)dp)->kp_eproc,
1075 sizeof(*eproc));
1076 if (error)
1077 goto err;
1078 dp += sizeof(struct kinfo_proc);
1079 buflen -= sizeof(struct kinfo_proc);
1080 }
1081 needed += sizeof(struct kinfo_proc);
1082 } else {
1083 if (buflen >= elem_size && elem_count > 0) {
1084 fill_kproc2(p, kproc2);
1085
1086
1087
1088
1089 error = copyout(kproc2, dp,
1090 min(sizeof(*kproc2), elem_size));
1091 if (error)
1092 goto err;
1093 dp += elem_size;
1094 buflen -= elem_size;
1095 elem_count--;
1096 }
1097 needed += elem_size;
1098 }
1099 }
1100 if (doingzomb == 0) {
1101 p = LIST_FIRST(&zombproc);
1102 doingzomb++;
1103 goto again;
1104 }
1105 if (where != NULL) {
1106 *sizep = dp - where;
1107 if (needed > *sizep) {
1108 error = ENOMEM;
1109 goto err;
1110 }
1111 } else {
1112 needed += KERN_PROCSLOP;
1113 *sizep = needed;
1114 }
1115 err:
1116 if (eproc)
1117 free(eproc, M_TEMP);
1118 if (kproc2)
1119 free(kproc2, M_TEMP);
1120 return (error);
1121 }
1122
1123 #endif
1124
1125
1126
1127
1128 void
1129 fill_eproc(struct proc *p, struct eproc *ep)
1130 {
1131 struct tty *tp;
1132
1133 ep->e_paddr = p;
1134 ep->e_sess = p->p_pgrp->pg_session;
1135 ep->e_pcred = *p->p_cred;
1136 ep->e_ucred = *p->p_ucred;
1137 if (p->p_stat == SIDL || P_ZOMBIE(p)) {
1138 ep->e_vm.vm_rssize = 0;
1139 ep->e_vm.vm_tsize = 0;
1140 ep->e_vm.vm_dsize = 0;
1141 ep->e_vm.vm_ssize = 0;
1142 bzero(&ep->e_pstats, sizeof(ep->e_pstats));
1143 ep->e_pstats_valid = 0;
1144 } else {
1145 struct vmspace *vm = p->p_vmspace;
1146
1147 ep->e_vm.vm_rssize = vm_resident_count(vm);
1148 ep->e_vm.vm_tsize = vm->vm_tsize;
1149 ep->e_vm.vm_dsize = vm->vm_dused;
1150 ep->e_vm.vm_ssize = vm->vm_ssize;
1151 ep->e_pstats = *p->p_stats;
1152 ep->e_pstats_valid = 1;
1153 }
1154 if (p->p_pptr)
1155 ep->e_ppid = p->p_pptr->p_pid;
1156 else
1157 ep->e_ppid = 0;
1158 ep->e_pgid = p->p_pgrp->pg_id;
1159 ep->e_jobc = p->p_pgrp->pg_jobc;
1160 if ((p->p_flag & P_CONTROLT) &&
1161 (tp = ep->e_sess->s_ttyp)) {
1162 ep->e_tdev = tp->t_dev;
1163 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1164 ep->e_tsess = tp->t_session;
1165 } else
1166 ep->e_tdev = NODEV;
1167 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
1168 if (SESS_LEADER(p))
1169 ep->e_flag |= EPROC_SLEADER;
1170 strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN);
1171 ep->e_wmesg[WMESGLEN] = '\0';
1172 ep->e_xsize = ep->e_xrssize = 0;
1173 ep->e_xccount = ep->e_xswrss = 0;
1174 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1);
1175 ep->e_login[MAXLOGNAME-1] = '\0';
1176 strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN);
1177 ep->e_emul[EMULNAMELEN] = '\0';
1178 ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0;
1179 ep->e_limit = p->p_p->ps_limit;
1180 }
1181
1182 #ifndef SMALL_KERNEL
1183
1184
1185
1186
1187 void
1188 fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
1189 {
1190 struct tty *tp;
1191 struct timeval ut, st;
1192
1193 bzero(ki, sizeof(*ki));
1194
1195 ki->p_paddr = PTRTOINT64(p);
1196 ki->p_fd = PTRTOINT64(p->p_fd);
1197 ki->p_stats = PTRTOINT64(p->p_stats);
1198 ki->p_limit = PTRTOINT64(p->p_p->ps_limit);
1199 ki->p_vmspace = PTRTOINT64(p->p_vmspace);
1200 ki->p_sigacts = PTRTOINT64(p->p_sigacts);
1201 ki->p_sess = PTRTOINT64(p->p_session);
1202 ki->p_tsess = 0;
1203 ki->p_ru = PTRTOINT64(p->p_ru);
1204
1205 ki->p_eflag = 0;
1206 ki->p_exitsig = p->p_exitsig;
1207 ki->p_flag = p->p_flag | P_INMEM;
1208
1209 ki->p_pid = p->p_pid;
1210 if (p->p_pptr)
1211 ki->p_ppid = p->p_pptr->p_pid;
1212 else
1213 ki->p_ppid = 0;
1214 if (p->p_session->s_leader)
1215 ki->p_sid = p->p_session->s_leader->p_pid;
1216 else
1217 ki->p_sid = 0;
1218 ki->p__pgid = p->p_pgrp->pg_id;
1219
1220 ki->p_tpgid = -1;
1221
1222 ki->p_uid = p->p_ucred->cr_uid;
1223 ki->p_ruid = p->p_cred->p_ruid;
1224 ki->p_gid = p->p_ucred->cr_gid;
1225 ki->p_rgid = p->p_cred->p_rgid;
1226 ki->p_svuid = p->p_cred->p_svuid;
1227 ki->p_svgid = p->p_cred->p_svgid;
1228
1229 memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups,
1230 min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups)));
1231 ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups;
1232
1233 ki->p_jobc = p->p_pgrp->pg_jobc;
1234 if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) {
1235 ki->p_tdev = tp->t_dev;
1236 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1;
1237 ki->p_tsess = PTRTOINT64(tp->t_session);
1238 } else {
1239 ki->p_tdev = NODEV;
1240 }
1241
1242 ki->p_estcpu = p->p_estcpu;
1243 ki->p_rtime_sec = p->p_rtime.tv_sec;
1244 ki->p_rtime_usec = p->p_rtime.tv_usec;
1245 ki->p_cpticks = p->p_cpticks;
1246 ki->p_pctcpu = p->p_pctcpu;
1247
1248 ki->p_uticks = p->p_uticks;
1249 ki->p_sticks = p->p_sticks;
1250 ki->p_iticks = p->p_iticks;
1251
1252 ki->p_tracep = PTRTOINT64(p->p_tracep);
1253 ki->p_traceflag = p->p_traceflag;
1254
1255 ki->p_siglist = p->p_siglist;
1256 ki->p_sigmask = p->p_sigmask;
1257 ki->p_sigignore = p->p_sigignore;
1258 ki->p_sigcatch = p->p_sigcatch;
1259
1260 ki->p_stat = p->p_stat;
1261 ki->p_nice = p->p_nice;
1262
1263 ki->p_xstat = p->p_xstat;
1264 ki->p_acflag = p->p_acflag;
1265
1266 strlcpy(ki->p_emul, p->p_emul->e_name, sizeof(ki->p_emul));
1267 strlcpy(ki->p_comm, p->p_comm, sizeof(ki->p_comm));
1268 strncpy(ki->p_login, p->p_session->s_login,
1269 min(sizeof(ki->p_login) - 1, sizeof(p->p_session->s_login)));
1270
1271 if (p->p_stat == SIDL || P_ZOMBIE(p)) {
1272 ki->p_vm_rssize = 0;
1273 ki->p_vm_tsize = 0;
1274 ki->p_vm_dsize = 0;
1275 ki->p_vm_ssize = 0;
1276 } else {
1277 struct vmspace *vm = p->p_vmspace;
1278
1279 ki->p_vm_rssize = vm_resident_count(vm);
1280 ki->p_vm_tsize = vm->vm_tsize;
1281 ki->p_vm_dsize = vm->vm_dused;
1282 ki->p_vm_ssize = vm->vm_ssize;
1283
1284 ki->p_forw = PTRTOINT64(p->p_forw);
1285 ki->p_back = PTRTOINT64(p->p_back);
1286 ki->p_addr = PTRTOINT64(p->p_addr);
1287 ki->p_stat = p->p_stat;
1288 ki->p_swtime = p->p_swtime;
1289 ki->p_slptime = p->p_slptime;
1290 ki->p_schedflags = 0;
1291 ki->p_holdcnt = 1;
1292 ki->p_priority = p->p_priority;
1293 ki->p_usrpri = p->p_usrpri;
1294 if (p->p_wmesg)
1295 strlcpy(ki->p_wmesg, p->p_wmesg, sizeof(ki->p_wmesg));
1296 ki->p_wchan = PTRTOINT64(p->p_wchan);
1297
1298 }
1299
1300 if (p->p_session->s_ttyvp)
1301 ki->p_eflag |= EPROC_CTTY;
1302 if (SESS_LEADER(p))
1303 ki->p_eflag |= EPROC_SLEADER;
1304 if (p->p_rlimit)
1305 ki->p_rlim_rss_cur = p->p_rlimit[RLIMIT_RSS].rlim_cur;
1306
1307
1308 if (P_ZOMBIE(p)) {
1309 ki->p_uvalid = 0;
1310 } else {
1311 ki->p_uvalid = 1;
1312
1313 ki->p_ustart_sec = p->p_stats->p_start.tv_sec;
1314 ki->p_ustart_usec = p->p_stats->p_start.tv_usec;
1315
1316 calcru(p, &ut, &st, 0);
1317 ki->p_uutime_sec = ut.tv_sec;
1318 ki->p_uutime_usec = ut.tv_usec;
1319 ki->p_ustime_sec = st.tv_sec;
1320 ki->p_ustime_usec = st.tv_usec;
1321
1322 ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss;
1323 ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss;
1324 ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss;
1325 ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss;
1326 ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt;
1327 ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt;
1328 ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap;
1329 ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock;
1330 ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock;
1331 ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd;
1332 ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv;
1333 ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals;
1334 ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw;
1335 ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw;
1336
1337 timeradd(&p->p_stats->p_cru.ru_utime,
1338 &p->p_stats->p_cru.ru_stime, &ut);
1339 ki->p_uctime_sec = ut.tv_sec;
1340 ki->p_uctime_usec = ut.tv_usec;
1341 ki->p_cpuid = KI_NOCPU;
1342 #ifdef MULTIPROCESSOR
1343 if (p->p_cpu != NULL)
1344 ki->p_cpuid = CPU_INFO_UNIT(p->p_cpu);
1345 #endif
1346 }
1347 }
1348
1349 int
1350 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1351 struct proc *cp)
1352 {
1353 struct proc *vp;
1354 pid_t pid;
1355 int op;
1356 struct ps_strings pss;
1357 struct iovec iov;
1358 struct uio uio;
1359 int error;
1360 size_t limit;
1361 int cnt;
1362 char **rargv, **vargv;
1363 char *rarg, *varg;
1364 char *buf;
1365
1366 if (namelen > 2)
1367 return (ENOTDIR);
1368 if (namelen < 2)
1369 return (EINVAL);
1370
1371 pid = name[0];
1372 op = name[1];
1373
1374 switch (op) {
1375 case KERN_PROC_ARGV:
1376 case KERN_PROC_NARGV:
1377 case KERN_PROC_ENV:
1378 case KERN_PROC_NENV:
1379 break;
1380 default:
1381 return (EOPNOTSUPP);
1382 }
1383
1384 if ((vp = pfind(pid)) == NULL)
1385 return (ESRCH);
1386
1387 if (oldp == NULL) {
1388 if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV)
1389 *oldlenp = sizeof(int);
1390 else
1391 *oldlenp = ARG_MAX;
1392 return (0);
1393 }
1394
1395 if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM))
1396 return (EINVAL);
1397
1398
1399 if ((vp->p_flag & P_WEXIT))
1400 return (ESRCH);
1401
1402
1403 if ((vp->p_flag & P_INEXEC))
1404 return (EBUSY);
1405
1406 vp->p_vmspace->vm_refcnt++;
1407 buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
1408
1409 iov.iov_base = &pss;
1410 iov.iov_len = sizeof(pss);
1411 uio.uio_iov = &iov;
1412 uio.uio_iovcnt = 1;
1413 uio.uio_offset = (off_t)PS_STRINGS;
1414 uio.uio_resid = sizeof(pss);
1415 uio.uio_segflg = UIO_SYSSPACE;
1416 uio.uio_rw = UIO_READ;
1417 uio.uio_procp = cp;
1418
1419 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio, 0)) != 0)
1420 goto out;
1421
1422 if (op == KERN_PROC_NARGV) {
1423 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr);
1424 goto out;
1425 }
1426 if (op == KERN_PROC_NENV) {
1427 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr);
1428 goto out;
1429 }
1430
1431 if (op == KERN_PROC_ARGV) {
1432 cnt = pss.ps_nargvstr;
1433 vargv = pss.ps_argvstr;
1434 } else {
1435 cnt = pss.ps_nenvstr;
1436 vargv = pss.ps_envstr;
1437 }
1438
1439
1440 limit = *oldlenp - 1;
1441 *oldlenp = 0;
1442
1443 rargv = oldp;
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456 rarg = (char *)(rargv + cnt + 1);
1457 *oldlenp += (cnt + 1) * sizeof(char **);
1458
1459 while (cnt > 0 && *oldlenp < limit) {
1460 size_t len, vstrlen;
1461
1462
1463 if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0)
1464 goto out;
1465
1466
1467 iov.iov_base = &varg;
1468 iov.iov_len = sizeof(varg);
1469 uio.uio_iov = &iov;
1470 uio.uio_iovcnt = 1;
1471 uio.uio_offset = (off_t)(vaddr_t)vargv;
1472 uio.uio_resid = sizeof(varg);
1473 uio.uio_segflg = UIO_SYSSPACE;
1474 uio.uio_rw = UIO_READ;
1475 uio.uio_procp = cp;
1476 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio, 0)) != 0)
1477 goto out;
1478
1479 if (varg == NULL)
1480 break;
1481
1482
1483
1484
1485
1486 more:
1487 len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK);
1488
1489 iov.iov_base = buf;
1490 iov.iov_len = len;
1491 uio.uio_iov = &iov;
1492 uio.uio_iovcnt = 1;
1493 uio.uio_offset = (off_t)(vaddr_t)varg;
1494 uio.uio_resid = len;
1495 uio.uio_segflg = UIO_SYSSPACE;
1496 uio.uio_rw = UIO_READ;
1497 uio.uio_procp = cp;
1498 if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio, 0)) != 0)
1499 goto out;
1500
1501 for (vstrlen = 0; vstrlen < len; vstrlen++) {
1502 if (buf[vstrlen] == '\0')
1503 break;
1504 }
1505
1506
1507 if (*oldlenp + vstrlen + 1 >= limit) {
1508 error = ENOMEM;
1509 goto out;
1510 }
1511
1512 if ((error = copyout(buf, rarg, vstrlen)) != 0)
1513 goto out;
1514
1515 *oldlenp += vstrlen;
1516 rarg += vstrlen;
1517
1518
1519 if (vstrlen == len) {
1520 varg += vstrlen;
1521 goto more;
1522 }
1523
1524
1525 buf[0] = '\0';
1526 if ((error = copyout(buf, rarg, 1)) != 0)
1527 goto out;
1528 *oldlenp += 1;
1529 rarg += 1;
1530
1531 vargv++;
1532 rargv++;
1533 cnt--;
1534 }
1535
1536 if (*oldlenp >= limit) {
1537 error = ENOMEM;
1538 goto out;
1539 }
1540
1541
1542 rarg = NULL;
1543 error = copyout(&rarg, rargv, sizeof(rarg));
1544
1545 out:
1546 uvmspace_free(vp->p_vmspace);
1547 free(buf, M_TEMP);
1548 return (error);
1549 }
1550
1551 #endif
1552
1553
1554
1555
1556
1557 int
1558 sysctl_diskinit(int update, struct proc *p)
1559 {
1560 struct diskstats *sdk;
1561 struct disk *dk;
1562 int i, tlen, l;
1563
1564 if ((i = rw_enter(&sysctl_disklock, RW_WRITE|RW_INTR)) != 0)
1565 return i;
1566
1567 if (disk_change) {
1568 for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk;
1569 dk = TAILQ_NEXT(dk, dk_link))
1570 tlen += strlen(dk->dk_name) + 1;
1571 tlen++;
1572
1573 if (disknames)
1574 free(disknames, M_SYSCTL);
1575 if (diskstats)
1576 free(diskstats, M_SYSCTL);
1577 diskstats = NULL;
1578 disknames = NULL;
1579 diskstats = malloc(disk_count * sizeof(struct diskstats),
1580 M_SYSCTL, M_WAITOK);
1581 disknames = malloc(tlen, M_SYSCTL, M_WAITOK);
1582 disknames[0] = '\0';
1583
1584 for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk;
1585 dk = TAILQ_NEXT(dk, dk_link), i++) {
1586 snprintf(disknames + l, tlen - l, "%s,",
1587 dk->dk_name ? dk->dk_name : "");
1588 l += strlen(disknames + l);
1589 sdk = diskstats + i;
1590 strlcpy(sdk->ds_name, dk->dk_name,
1591 sizeof(sdk->ds_name));
1592 sdk->ds_busy = dk->dk_busy;
1593 sdk->ds_rxfer = dk->dk_rxfer;
1594 sdk->ds_wxfer = dk->dk_wxfer;
1595 sdk->ds_seek = dk->dk_seek;
1596 sdk->ds_rbytes = dk->dk_rbytes;
1597 sdk->ds_wbytes = dk->dk_wbytes;
1598 sdk->ds_attachtime = dk->dk_attachtime;
1599 sdk->ds_timestamp = dk->dk_timestamp;
1600 sdk->ds_time = dk->dk_time;
1601 }
1602
1603
1604 if (l != 0)
1605 disknames[l - 1] = '\0';
1606 disk_change = 0;
1607 } else if (update) {
1608
1609 for (dk = TAILQ_FIRST(&disklist), i = 0; dk;
1610 dk = TAILQ_NEXT(dk, dk_link), i++) {
1611 sdk = diskstats + i;
1612 strlcpy(sdk->ds_name, dk->dk_name,
1613 sizeof(sdk->ds_name));
1614 sdk->ds_busy = dk->dk_busy;
1615 sdk->ds_rxfer = dk->dk_rxfer;
1616 sdk->ds_wxfer = dk->dk_wxfer;
1617 sdk->ds_seek = dk->dk_seek;
1618 sdk->ds_rbytes = dk->dk_rbytes;
1619 sdk->ds_wbytes = dk->dk_wbytes;
1620 sdk->ds_attachtime = dk->dk_attachtime;
1621 sdk->ds_timestamp = dk->dk_timestamp;
1622 sdk->ds_time = dk->dk_time;
1623 }
1624 }
1625 rw_exit_write(&sysctl_disklock);
1626 return 0;
1627 }
1628
1629 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
1630 int
1631 sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep)
1632 {
1633 #ifdef SYSVMSG
1634 struct msg_sysctl_info *msgsi;
1635 #endif
1636 #ifdef SYSVSEM
1637 struct sem_sysctl_info *semsi;
1638 #endif
1639 #ifdef SYSVSHM
1640 struct shm_sysctl_info *shmsi;
1641 #endif
1642 size_t infosize, dssize, tsize, buflen;
1643 int i, nds, error, ret;
1644 void *buf;
1645
1646 if (namelen != 1)
1647 return (EINVAL);
1648
1649 buflen = *sizep;
1650
1651 switch (*name) {
1652 case KERN_SYSVIPC_MSG_INFO:
1653 #ifdef SYSVMSG
1654 infosize = sizeof(msgsi->msginfo);
1655 nds = msginfo.msgmni;
1656 dssize = sizeof(msgsi->msgids[0]);
1657 break;
1658 #else
1659 return (EOPNOTSUPP);
1660 #endif
1661 case KERN_SYSVIPC_SEM_INFO:
1662 #ifdef SYSVSEM
1663 infosize = sizeof(semsi->seminfo);
1664 nds = seminfo.semmni;
1665 dssize = sizeof(semsi->semids[0]);
1666 break;
1667 #else
1668 return (EOPNOTSUPP);
1669 #endif
1670 case KERN_SYSVIPC_SHM_INFO:
1671 #ifdef SYSVSHM
1672 infosize = sizeof(shmsi->shminfo);
1673 nds = shminfo.shmmni;
1674 dssize = sizeof(shmsi->shmids[0]);
1675 break;
1676 #else
1677 return (EOPNOTSUPP);
1678 #endif
1679 default:
1680 return (EINVAL);
1681 }
1682 tsize = infosize + (nds * dssize);
1683
1684
1685 if (where == NULL) {
1686 *sizep = tsize;
1687 return (0);
1688 }
1689
1690
1691 if (buflen < infosize) {
1692 *sizep = 0;
1693 return (ENOMEM);
1694 }
1695 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK);
1696 bzero(buf, min(tsize, buflen));
1697
1698 switch (*name) {
1699 #ifdef SYSVMSG
1700 case KERN_SYSVIPC_MSG_INFO:
1701 msgsi = (struct msg_sysctl_info *)buf;
1702 msgsi->msginfo = msginfo;
1703 break;
1704 #endif
1705 #ifdef SYSVSEM
1706 case KERN_SYSVIPC_SEM_INFO:
1707 semsi = (struct sem_sysctl_info *)buf;
1708 semsi->seminfo = seminfo;
1709 break;
1710 #endif
1711 #ifdef SYSVSHM
1712 case KERN_SYSVIPC_SHM_INFO:
1713 shmsi = (struct shm_sysctl_info *)buf;
1714 shmsi->shminfo = shminfo;
1715 break;
1716 #endif
1717 }
1718 buflen -= infosize;
1719
1720 ret = 0;
1721 if (buflen > 0) {
1722
1723 for (i = 0; i < nds; i++) {
1724 if (buflen < dssize) {
1725 ret = ENOMEM;
1726 break;
1727 }
1728 switch (*name) {
1729 #ifdef SYSVMSG
1730 case KERN_SYSVIPC_MSG_INFO:
1731 bcopy(&msqids[i], &msgsi->msgids[i], dssize);
1732 break;
1733 #endif
1734 #ifdef SYSVSEM
1735 case KERN_SYSVIPC_SEM_INFO:
1736 if (sema[i] != NULL)
1737 bcopy(sema[i], &semsi->semids[i],
1738 dssize);
1739 else
1740 bzero(&semsi->semids[i], dssize);
1741 break;
1742 #endif
1743 #ifdef SYSVSHM
1744 case KERN_SYSVIPC_SHM_INFO:
1745 if (shmsegs[i] != NULL)
1746 bcopy(shmsegs[i], &shmsi->shmids[i],
1747 dssize);
1748 else
1749 bzero(&shmsi->shmids[i], dssize);
1750 break;
1751 #endif
1752 }
1753 buflen -= dssize;
1754 }
1755 }
1756 *sizep -= buflen;
1757 error = copyout(buf, where, *sizep);
1758 free(buf, M_TEMP);
1759
1760 return (error ? error : ret);
1761 }
1762 #endif
1763
1764 #ifndef SMALL_KERNEL
1765
1766 int
1767 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp)
1768 {
1769 return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0));
1770 }
1771
1772
1773 int
1774 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1775 void *newp, size_t newlen)
1776 {
1777 struct ksensor *ks;
1778 struct sensor *us;
1779 struct ksensordev *ksd;
1780 struct sensordev *usd;
1781 int dev, numt, ret;
1782 enum sensor_type type;
1783
1784 if (namelen != 1 && namelen != 3)
1785 return (ENOTDIR);
1786
1787 dev = name[0];
1788 if (namelen == 1) {
1789 ksd = sensordev_get(dev);
1790 if (ksd == NULL)
1791 return (ENOENT);
1792
1793
1794 usd = malloc(sizeof(*usd), M_TEMP, M_WAITOK);
1795 bzero(usd, sizeof(*usd));
1796 usd->num = ksd->num;
1797 strlcpy(usd->xname, ksd->xname, sizeof(usd->xname));
1798 memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt));
1799 usd->sensors_count = ksd->sensors_count;
1800
1801 ret = sysctl_rdstruct(oldp, oldlenp, newp, usd,
1802 sizeof(struct sensordev));
1803
1804 free(usd, M_TEMP);
1805 return (ret);
1806 }
1807
1808 type = name[1];
1809 numt = name[2];
1810
1811 ks = sensor_find(dev, type, numt);
1812 if (ks == NULL)
1813 return (ENOENT);
1814
1815
1816 us = malloc(sizeof(*us), M_TEMP, M_WAITOK);
1817 bzero(us, sizeof(*us));
1818 memcpy(us->desc, ks->desc, sizeof(us->desc));
1819 us->tv = ks->tv;
1820 us->value = ks->value;
1821 us->type = ks->type;
1822 us->status = ks->status;
1823 us->numt = ks->numt;
1824 us->flags = ks->flags;
1825
1826 ret = sysctl_rdstruct(oldp, oldlenp, newp, us,
1827 sizeof(struct sensor));
1828 free(us, M_TEMP);
1829 return (ret);
1830 }
1831
1832 int
1833 sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1834 void *newp, size_t newlen)
1835 {
1836 int enabled, error;
1837 struct emul *e;
1838
1839 if (name[0] == KERN_EMUL_NUM) {
1840 if (namelen != 1)
1841 return (ENOTDIR);
1842 return (sysctl_rdint(oldp, oldlenp, newp, nexecs));
1843 }
1844
1845 if (namelen != 2)
1846 return (ENOTDIR);
1847 if (name[0] > nexecs || name[0] < 0)
1848 return (EINVAL);
1849 e = execsw[name[0] - 1].es_emul;
1850 if (e == NULL)
1851 return (EINVAL);
1852
1853 switch (name[1]) {
1854 case KERN_EMUL_NAME:
1855 return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name));
1856 case KERN_EMUL_ENABLED:
1857 enabled = (e->e_flags & EMUL_ENABLED);
1858 error = sysctl_int(oldp, oldlenp, newp, newlen,
1859 &enabled);
1860 e->e_flags = (enabled & EMUL_ENABLED);
1861 return (error);
1862 default:
1863 return (EINVAL);
1864 }
1865 }
1866
1867 #endif
1868
1869 int
1870 sysctl_cptime2(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1871 void *newp, size_t newlen)
1872 {
1873 CPU_INFO_ITERATOR cii;
1874 struct cpu_info *ci;
1875 int i;
1876
1877 if (namelen != 1)
1878 return (ENOTDIR);
1879
1880 i = name[0];
1881
1882 CPU_INFO_FOREACH(cii, ci) {
1883 if (i-- == 0)
1884 break;
1885 }
1886 if (i > 0)
1887 return (ENOENT);
1888
1889 return (sysctl_rdstruct(oldp, oldlenp, newp,
1890 &ci->ci_schedstate.spc_cp_time,
1891 sizeof(ci->ci_schedstate.spc_cp_time)));
1892 }