1 /* $NetBSD: darwin_sysctl.c,v 1.56.8.2 2008/11/01 21:22:25 christos Exp $ */
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: darwin_sysctl.c,v 1.56.8.2 2008/11/01 21:22:25 christos Exp $");
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/systm.h>
39 #include <sys/signal.h>
40 #include <sys/mount.h>
43 #include <sys/malloc.h>
44 #include <sys/sysctl.h>
45 #include <sys/ktrace.h>
47 #include <sys/kauth.h>
49 #include <sys/syscallargs.h>
51 #include <uvm/uvm_extern.h>
53 #include <miscfs/specfs/specdev.h>
55 #include <compat/sys/signal.h>
56 #include <compat/sys/signalvar.h>
58 #include <compat/mach/mach_types.h>
59 #include <compat/mach/mach_vm.h>
61 #include <compat/darwin/darwin_types.h>
62 #include <compat/darwin/darwin_audit.h>
63 #include <compat/darwin/darwin_exec.h>
64 #include <compat/darwin/darwin_sysctl.h>
65 #include <compat/darwin/darwin_proc.h>
66 #include <compat/darwin/darwin_route.h>
67 #include <compat/darwin/darwin_syscallargs.h>
69 pid_t darwin_init_pid
= 0;
70 int darwin_ioframebuffer_unit
= 0;
71 int darwin_ioframebuffer_screen
= 0;
72 int darwin_iohidsystem_mux
= 0;
73 static const char *darwin_sysctl_hw_machine
= "Power Macintosh";
75 static int darwin_sysctl_dokproc(SYSCTLFN_PROTO
);
76 static void darwin_fill_kproc(struct proc
*, struct darwin_kinfo_proc
*);
77 static void native_to_darwin_pflag(int *, struct proc
*);
78 static int darwin_sysctl_procargs(SYSCTLFN_PROTO
);
79 static int darwin_sysctl_net(SYSCTLFN_PROTO
);
80 static int darwin_sysctl_kdebug(SYSCTLFN_PROTO
);
82 static struct sysctlnode darwin_sysctl_root
= {
83 .sysctl_flags
= SYSCTL_VERSION
|CTLFLAG_ROOT
|CTLTYPE_NODE
,
85 sysc_init_field(_sysctl_size
, sizeof(struct sysctlnode
)),
86 .sysctl_name
= "(darwin_root)",
90 darwin_sysctl_redispatch(SYSCTLFN_ARGS
)
94 * put namelen and name back at the top
96 namelen
+= (name
- oname
);
100 * call into (via NULL) main native tree
102 return sysctl_dispatch(SYSCTLFN_CALL(NULL
));
106 * this setup routine is a complement to darwin_sys___sysctl()
108 SYSCTL_SETUP(sysctl_darwin_emul_setup
, "darwin emulated sysctl tree setup")
110 const struct sysctlnode
*_root
= &darwin_sysctl_root
;
112 sysctl_createv(clog
, 0, &_root
, NULL
,
114 CTLTYPE_NODE
, "kern", NULL
,
116 DARWIN_CTL_KERN
, CTL_EOL
);
118 sysctl_createv(clog
, 0, &_root
, NULL
,
120 CTLTYPE_STRING
, "ostype", NULL
,
121 darwin_sysctl_redispatch
, 0, NULL
, 0,
122 DARWIN_CTL_KERN
, DARWIN_KERN_OSTYPE
, CTL_EOL
);
123 sysctl_createv(clog
, 0, &_root
, NULL
,
125 CTLTYPE_STRING
, "osrelease", NULL
,
126 darwin_sysctl_redispatch
, 0, NULL
, 0,
127 DARWIN_CTL_KERN
, DARWIN_KERN_OSRELEASE
, CTL_EOL
);
128 sysctl_createv(clog
, 0, &_root
, NULL
,
130 CTLTYPE_INT
, "osrevision", NULL
,
131 darwin_sysctl_redispatch
, 0, NULL
, 0,
132 DARWIN_CTL_KERN
, DARWIN_KERN_OSREV
, CTL_EOL
);
133 sysctl_createv(clog
, 0, &_root
, NULL
,
135 CTLTYPE_STRING
, "version", NULL
,
136 darwin_sysctl_redispatch
, 0, NULL
, 0,
137 DARWIN_CTL_KERN
, DARWIN_KERN_VERSION
, CTL_EOL
);
138 sysctl_createv(clog
, 0, &_root
, NULL
,
140 CTLTYPE_INT
, "maxvnodes", NULL
,
141 darwin_sysctl_redispatch
, 0, NULL
, 0,
142 DARWIN_CTL_KERN
, DARWIN_KERN_MAXVNODES
, CTL_EOL
);
143 sysctl_createv(clog
, 0, &_root
, NULL
,
145 CTLTYPE_INT
, "maxproc", NULL
,
146 darwin_sysctl_redispatch
, 0, NULL
, 0,
147 DARWIN_CTL_KERN
, DARWIN_KERN_MAXPROC
, CTL_EOL
);
148 sysctl_createv(clog
, 0, &_root
, NULL
,
150 CTLTYPE_INT
, "maxfiles", NULL
,
151 darwin_sysctl_redispatch
, 0, NULL
, 0,
152 DARWIN_CTL_KERN
, DARWIN_KERN_MAXFILES
, CTL_EOL
);
153 sysctl_createv(clog
, 0, &_root
, NULL
,
155 CTLTYPE_INT
, "argmax", NULL
,
156 darwin_sysctl_redispatch
, 0, NULL
, 0,
157 DARWIN_CTL_KERN
, DARWIN_KERN_ARGMAX
, CTL_EOL
);
158 sysctl_createv(clog
, 0, &_root
, NULL
,
160 CTLTYPE_INT
, "securelevel", NULL
,
161 darwin_sysctl_redispatch
, 0, NULL
, 0,
162 DARWIN_CTL_KERN
, DARWIN_KERN_SECURELVL
, CTL_EOL
);
163 sysctl_createv(clog
, 0, &_root
, NULL
,
165 CTLTYPE_STRING
, "hostname", NULL
,
166 darwin_sysctl_redispatch
, 0, NULL
, 0,
167 DARWIN_CTL_KERN
, DARWIN_KERN_HOSTNAME
, CTL_EOL
);
168 sysctl_createv(clog
, 0, &_root
, NULL
,
170 CTLTYPE_INT
, "hostid", NULL
,
171 darwin_sysctl_redispatch
, 0, NULL
, 0,
172 DARWIN_CTL_KERN
, DARWIN_KERN_HOSTID
, CTL_EOL
);
173 sysctl_createv(clog
, 0, &_root
, NULL
,
175 CTLTYPE_STRUCT
, "clockrate", NULL
,
176 darwin_sysctl_redispatch
, 0, NULL
, 0,
177 DARWIN_CTL_KERN
, DARWIN_KERN_CLOCKRATE
, CTL_EOL
);
178 sysctl_createv(clog
, 0, &_root
, NULL
,
180 CTLTYPE_STRUCT
, "vnode", NULL
,
181 darwin_sysctl_redispatch
, 0, NULL
, 0,
182 DARWIN_CTL_KERN
, DARWIN_KERN_VNODE
, CTL_EOL
);
183 sysctl_createv(clog
, 0, &_root
, NULL
,
185 CTLTYPE_STRUCT
, "file", NULL
,
186 darwin_sysctl_redispatch
, 0, NULL
, 0,
187 DARWIN_CTL_KERN
, DARWIN_KERN_FILE
, CTL_EOL
);
188 sysctl_createv(clog
, 0, &_root
, NULL
,
190 CTLTYPE_NODE
, "profiling", NULL
,
191 darwin_sysctl_redispatch
, 0, NULL
, 0,
192 DARWIN_CTL_KERN
, DARWIN_KERN_PROF
, CTL_EOL
);
193 sysctl_createv(clog
, 0, &_root
, NULL
,
195 CTLTYPE_INT
, "posix1version", NULL
,
196 darwin_sysctl_redispatch
, 0, NULL
, 0,
197 DARWIN_CTL_KERN
, DARWIN_KERN_POSIX1
, CTL_EOL
);
198 sysctl_createv(clog
, 0, &_root
, NULL
,
200 CTLTYPE_INT
, "ngroups", NULL
,
201 darwin_sysctl_redispatch
, 0, NULL
, 0,
202 DARWIN_CTL_KERN
, DARWIN_KERN_NGROUPS
, CTL_EOL
);
203 sysctl_createv(clog
, 0, &_root
, NULL
,
205 CTLTYPE_INT
, "job_control", NULL
,
206 darwin_sysctl_redispatch
, 0, NULL
, 0,
207 DARWIN_CTL_KERN
, DARWIN_KERN_JOB_CONTROL
, CTL_EOL
);
208 sysctl_createv(clog
, 0, &_root
, NULL
,
210 CTLTYPE_INT
, "saved_ids", NULL
,
211 darwin_sysctl_redispatch
, 0, NULL
, 0,
212 DARWIN_CTL_KERN
, DARWIN_KERN_SAVED_IDS
, CTL_EOL
);
213 sysctl_createv(clog
, 0, &_root
, NULL
,
215 CTLTYPE_STRUCT
, "boottime", NULL
,
216 darwin_sysctl_redispatch
, 0, NULL
, 0,
217 DARWIN_CTL_KERN
, DARWIN_KERN_BOOTTIME
, CTL_EOL
);
218 sysctl_createv(clog
, 0, &_root
, NULL
,
220 CTLTYPE_STRING
, "nisdomainname", NULL
,
221 darwin_sysctl_redispatch
, 0, NULL
, 0,
222 DARWIN_CTL_KERN
, DARWIN_KERN_NISDOMAINNAME
, CTL_EOL
);
223 sysctl_createv(clog
, 0, &_root
, NULL
,
225 CTLTYPE_INT
, "maxpartitions", NULL
,
226 darwin_sysctl_redispatch
, 0, NULL
, 0,
227 DARWIN_CTL_KERN
, DARWIN_KERN_MAXPARTITIONS
, CTL_EOL
);
228 sysctl_createv(clog
, 0, &_root
, NULL
,
230 CTLTYPE_INT
, "kdebug", NULL
,
231 darwin_sysctl_kdebug
, 0, NULL
, 0,
232 DARWIN_CTL_KERN
, DARWIN_KERN_KDEBUG
, CTL_EOL
);
234 sysctl_createv(clog
, 0, &_root
, NULL
,
236 CTLTYPE_NODE
, "procargs", NULL
,
237 darwin_sysctl_procargs
, 0, NULL
, 0,
238 DARWIN_CTL_KERN
, DARWIN_KERN_PROCARGS
, CTL_EOL
);
239 sysctl_createv(clog
, 0, &_root
, NULL
,
241 CTLTYPE_INT
, "proc", NULL
,
242 darwin_sysctl_dokproc
, 0, NULL
, 0,
243 DARWIN_CTL_KERN
, DARWIN_KERN_PROC
, CTL_EOL
);
245 sysctl_createv(clog
, 0, &_root
, NULL
,
247 CTLTYPE_NODE
, "hw", NULL
,
249 DARWIN_CTL_HW
, CTL_EOL
);
251 sysctl_createv(clog
, 0, &_root
, NULL
,
253 CTLTYPE_STRING
, "machine", NULL
,
255 NULL
, 0, __UNCONST(darwin_sysctl_hw_machine
), 0,
256 DARWIN_CTL_HW
, DARWIN_HW_MACHINE
, CTL_EOL
);
257 sysctl_createv(clog
, 0, &_root
, NULL
,
259 CTLTYPE_INT
, "ncpu", NULL
,
260 darwin_sysctl_redispatch
, 0, NULL
, 0,
261 DARWIN_CTL_HW
, DARWIN_HW_NCPU
, CTL_EOL
);
262 sysctl_createv(clog
, 0, &_root
, NULL
,
263 CTLFLAG_PERMANENT
|CTLFLAG_IMMEDIATE
,
264 CTLTYPE_INT
, "vectorunit", NULL
,
266 DARWIN_CTL_HW
, DARWIN_HW_VECTORUNIT
, CTL_EOL
);
267 sysctl_createv(clog
, 0, &_root
, NULL
,
269 CTLTYPE_INT
, "pagesize", NULL
,
270 darwin_sysctl_redispatch
, 0, NULL
, 0,
271 DARWIN_CTL_HW
, DARWIN_HW_PAGESIZE
, CTL_EOL
);
273 sysctl_createv(clog
, 0, &_root
, NULL
,
275 CTLTYPE_NODE
, "net", NULL
,
276 darwin_sysctl_net
, 0, NULL
, 0,
277 DARWIN_CTL_NET
, CTL_EOL
);
282 darwin_sys___sysctl(struct lwp
*l
, const struct darwin_sys___sysctl_args
*uap
, register_t
*retval
)
284 int error
, nerror
, name
[CTL_MAXNAME
];
285 size_t savelen
= 0, oldlen
= 0;
291 if (SCARG(uap
, oldlenp
) != NULL
) {
292 error
= copyin(SCARG(uap
, oldlenp
), &oldlen
, sizeof(oldlen
));
299 * top-level sysctl names may or may not be non-terminal, but
302 if (SCARG(uap
, namelen
) > CTL_MAXNAME
|| SCARG(uap
, namelen
) < 1)
304 error
= copyin(SCARG(uap
, name
), &name
,
305 SCARG(uap
, namelen
) * sizeof(int));
309 ktrmib(name
, SCARG(uap
, namelen
));
312 * dispatch request into darwin sysctl tree
314 sysctl_lock(SCARG(uap
, newp
) != NULL
);
315 error
= sysctl_dispatch(&name
[0], SCARG(uap
, namelen
),
316 SCARG(uap
, oldp
), &oldlen
,
317 SCARG(uap
, newp
), SCARG(uap
, newlen
),
318 &name
[0], l
, &darwin_sysctl_root
);
322 * reset caller's oldlen, even if we got an error
324 if (SCARG(uap
, oldlenp
) != NULL
) {
325 nerror
= copyout(&oldlen
, SCARG(uap
, oldlenp
), sizeof(oldlen
));
331 * if the only problem is that we weren't given enough space,
332 * that's an ENOMEM error
334 if (error
== 0 && SCARG(uap
, oldp
) != NULL
&& savelen
< oldlen
)
340 SYSCTL_SETUP(sysctl_emul_darwin_setup
, "sysctl emul.darwin subtree setup")
343 sysctl_createv(clog
, 0, NULL
, NULL
,
345 CTLTYPE_NODE
, "emul", NULL
,
348 sysctl_createv(clog
, 0, NULL
, NULL
,
350 CTLTYPE_NODE
, "darwin",
351 SYSCTL_DESCR("Darwin emulation settings"),
353 CTL_EMUL
, EMUL_DARWIN
, CTL_EOL
);
354 sysctl_createv(clog
, 0, NULL
, NULL
,
356 CTLTYPE_NODE
, "init",
357 SYSCTL_DESCR("Darwin init(8) process settings"),
359 CTL_EMUL
, EMUL_DARWIN
,
360 EMUL_DARWIN_INIT
, CTL_EOL
);
361 sysctl_createv(clog
, 0, NULL
, NULL
,
363 CTLTYPE_NODE
, "ioframebuffer",
364 SYSCTL_DESCR("Darwin framebuffer settings"),
366 CTL_EMUL
, EMUL_DARWIN
,
367 EMUL_DARWIN_IOFRAMEBUFFER
, CTL_EOL
);
368 sysctl_createv(clog
, 0, NULL
, NULL
,
370 CTLTYPE_NODE
, "iohidsystem",
371 SYSCTL_DESCR("Darwin HID system settings"),
373 CTL_EMUL
, EMUL_DARWIN
,
374 EMUL_DARWIN_IOHIDSYSTEM
, CTL_EOL
);
376 * XXX - darwin_init_pid is a pid_t, not an int
378 sysctl_createv(clog
, 0, NULL
, NULL
,
379 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
381 SYSCTL_DESCR("Pid of Darwin init(8) process"),
382 NULL
, 0, &darwin_init_pid
, 0,
383 CTL_EMUL
, EMUL_DARWIN
, EMUL_DARWIN_INIT
,
384 EMUL_DARWIN_INIT_PID
, CTL_EOL
);
385 sysctl_createv(clog
, 0, NULL
, NULL
,
386 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
388 SYSCTL_DESCR("Darwin framebuffer unit number"),
389 NULL
, 0, &darwin_ioframebuffer_unit
, 0,
390 CTL_EMUL
, EMUL_DARWIN
, EMUL_DARWIN_IOFRAMEBUFFER
,
391 EMUL_DARWIN_IOFRAMEBUFFER_UNIT
, CTL_EOL
);
392 sysctl_createv(clog
, 0, NULL
, NULL
,
393 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
394 CTLTYPE_INT
, "screen",
395 SYSCTL_DESCR("Darwin framebuffer screen number"),
396 NULL
, 0, &darwin_ioframebuffer_screen
, 0,
397 CTL_EMUL
, EMUL_DARWIN
, EMUL_DARWIN_IOFRAMEBUFFER
,
398 EMUL_DARWIN_IOFRAMEBUFFER_SCREEN
, CTL_EOL
);
399 sysctl_createv(clog
, 0, NULL
, NULL
,
400 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
402 SYSCTL_DESCR("Darwin HID system mux"),
403 NULL
, 0, &darwin_iohidsystem_mux
, 0,
404 CTL_EMUL
, EMUL_DARWIN
, EMUL_DARWIN_IOHIDSYSTEM
,
405 EMUL_DARWIN_IOHIDSYSTEM_MUX
, CTL_EOL
);
409 * On Darwin, mach_init is the system bootstrap process. It is responsible
410 * for forking the traditional UNIX init(8) and it does the Mach port naming
411 * service. We need mach_init for the naming service, but unfortunately, it
412 * will only act as such if its PID is 1. We use a sysctl
413 * (emul.darwin.init.pid) to fool a given process into thinking its PID is 1.
414 * That way we can run mach_init when we want to.
416 * sysctl -w emul.darwin.init.pid=$$; exec /emul/darwin/sbin/mach_init
418 * The same problem exists after mach_init has forked init: the fork libc stub
419 * really insist on the child to have PID 2 (if PID is not 2, then the stub
420 * will issue bootstrap calls to an already running mach_init, which fails,
424 darwin_sys_getpid(struct lwp
*l
, const void *v
, register_t
*retval
)
426 struct darwin_emuldata
*ded
;
427 struct proc
*p
= l
->l_proc
;
429 ded
= (struct darwin_emuldata
*)p
->p_emuldata
;
431 printf("pid %d: fakepid = %d, mach_init_pid = %d\n",
432 p
->p_pid
, ded
->ded_fakepid
, darwin_init_pid
);
433 if (ded
->ded_fakepid
!= 0)
434 *retval
= ded
->ded_fakepid
;
441 #define DARWIN_ENTROPYMAX 65536
443 darwin_sysctl_kdebug(SYSCTLFN_ARGS
)
450 * Get random dates between now and mstimeout (miliseconds)
452 case DARWIN_KERN_KDGETENTROPY
: {
456 struct timespec
*buf
;
457 struct timeval now
, last
, timeout
;
458 unsigned long long lnow
, ltimeout
;
469 count
= *oldlenp
/ sizeof(*buf
);
470 if (count
> DARWIN_ENTROPYMAX
)
473 buf
= malloc(sizeof(*buf
) * count
, M_TEMP
, M_ZERO
|M_WAITOK
);
476 last
.tv_sec
= now
.tv_sec
;
477 last
.tv_usec
= now
.tv_usec
;
478 timeout
.tv_sec
= mstimeout
/ 1000;
479 timeout
.tv_usec
= (mstimeout
% 1000) * 1000;
480 lnow
= (now
.tv_sec
* 1000000) + now
.tv_usec
;
481 ltimeout
= (timeout
.tv_sec
* 1000000) + timeout
.tv_usec
;
483 for (i
= 0; i
< count
; i
++) {
484 unsigned long long rnd
= random();
485 struct timeval item
, new;
487 rnd
*= (ltimeout
/ count
);
490 item
.tv_sec
= rnd
/ 1000;
491 item
.tv_usec
= rnd
% 1000;
493 timeradd(&last
, &item
, &new);
494 TIMEVAL_TO_TIMESPEC(&new, &buf
[i
]);
496 last
.tv_sec
= new.tv_sec
;
497 last
.tv_usec
= new.tv_usec
;
500 tsleep(&timeout
, PZERO
|PCATCH
, "darwin_entropy",
501 (mstimeout
* hz
/ 1000));
503 /* Just in case... */
504 if (sizeof(*buf
) * count
< *oldlenp
)
505 *oldlenp
= sizeof(*buf
) * count
;
507 error
= copyout(buf
, oldp
, *oldlenp
);
511 * The return value is the number of record
512 * instead of the size of the copied data.
514 *oldlenp
= *oldlenp
/ sizeof(*buf
);
529 darwin_sysctl_net(SYSCTLFN_ARGS
)
534 * A strange thing: thrid level is zero, but I don't understand
535 * what it stands for.
536 * All nodes here are of form [net.]<address family>.<zero>.*
541 if ((af
= name
[0]) != AF_ROUTE
) {
542 printf("unimplemented sysctl net.%d\n", af
);
548 printf("sysctl net.af.%d\n", name
[1]);
555 case DARWIN_NET_RT_DUMP
:
556 printf("unimplemented sysctl DARWIN_NET_RT_DUMP\n");
560 case DARWIN_NET_RT_FLAGS
:
561 printf("unimplemented sysctl DARWIN_NET_RT_FLAGS\n");
565 case DARWIN_NET_RT_IFLIST
:
566 return darwin_ifaddrs(name
[2], oldp
, oldlenp
);
580 * This is stolen from sys/kern/kern_sysctl.c:sysctl_doeproc()
582 #define DARWIN_KERN_PROCSLOP (5 * sizeof(struct darwin_kinfo_proc))
585 darwin_sysctl_dokproc(SYSCTLFN_ARGS
)
587 struct darwin_kinfo_proc kproc
;
588 struct darwin_kinfo_proc
*dp
;
590 const struct proclist_desc
*pd
;
593 u_int elem_size
, elem_count
;
594 size_t buflen
, needed
;
602 buflen
= where
!= NULL
? *oldlenp
: 0;
605 type
= rnode
->sysctl_num
;
607 if (type
== DARWIN_KERN_PROC
) {
609 !(namelen
== 1 && name
[0] == DARWIN_KERN_PROC_ALL
))
612 if (op
!= DARWIN_KERN_PROC_ALL
)
615 arg
= 0; /* Quell compiler warning */
616 elem_size
= elem_count
= 0; /* Ditto */
623 elem_count
= name
[3];
626 mutex_enter(proc_lock
);
630 PROCLIST_FOREACH(p
, pd
->pd_list
) {
632 * Skip embryonic processes.
634 if (p
->p_stat
== SIDL
)
637 * TODO - make more efficient (see notes below).
642 case DARWIN_KERN_PROC_PID
:
643 /* could do this with just a lookup */
644 if (p
->p_pid
!= (pid_t
)arg
)
648 case DARWIN_KERN_PROC_PGRP
:
649 /* could do this by traversing pgrp */
650 if (p
->p_pgrp
->pg_id
!= (pid_t
)arg
)
654 case DARWIN_KERN_PROC_SESSION
:
655 if (p
->p_session
->s_sid
!= (pid_t
)arg
)
659 case DARWIN_KERN_PROC_TTY
:
660 if (arg
== (int) KERN_PROC_TTY_REVOKE
) {
661 if ((p
->p_lflag
& PL_CONTROLT
) == 0 ||
662 p
->p_session
->s_ttyp
== NULL
||
663 p
->p_session
->s_ttyvp
!= NULL
)
665 } else if ((p
->p_lflag
& PL_CONTROLT
) == 0 ||
666 p
->p_session
->s_ttyp
== NULL
) {
668 } else if (p
->p_session
->s_ttyp
->t_dev
!=
669 darwin_to_native_dev((dev_t
)arg
))
673 case DARWIN_KERN_PROC_UID
:
674 if (kauth_cred_geteuid(p
->p_cred
) != (uid_t
)arg
)
678 case DARWIN_KERN_PROC_RUID
:
679 if (kauth_cred_getuid(p
->p_cred
) != (uid_t
)arg
)
683 case DARWIN_KERN_PROC_ALL
:
684 /* allow everything */
691 if (buflen
>= sizeof(struct darwin_kinfo_proc
)) {
692 darwin_fill_kproc(p
, &kproc
);
693 error
= copyout((void *)&kproc
, dp
, sizeof(kproc
));
697 buflen
-= sizeof(struct darwin_kinfo_proc
);
699 needed
+= sizeof(struct darwin_kinfo_proc
);
702 if (pd
->pd_list
!= NULL
)
704 mutex_exit(proc_lock
);
707 *oldlenp
= (char *)dp
- where
;
708 if (needed
> *oldlenp
)
711 needed
+= DARWIN_KERN_PROCSLOP
;
716 mutex_exit(proc_lock
);
721 * Native struct proc to Darwin's struct kinfo_proc
724 darwin_fill_kproc(struct proc
*p
, struct darwin_kinfo_proc
*dkp
)
727 struct darwin_extern_proc
*dep
;
728 struct darwin_eproc
*de
;
730 printf("fillkproc: pid %d\n", p
->p_pid
);
731 l
= LIST_FIRST(&p
->p_lwps
);
733 (void)memset(dkp
, 0, sizeof(*dkp
));
735 dep
= (struct darwin_extern_proc
*)&dkp
->kp_proc
;
736 de
= (struct darwin_eproc
*)&dkp
->kp_eproc
;
738 /* (ptr) dep->p_un */
739 /* (ptr) dep->p_vmspace */
740 /* (ptr) dep->p_sigacts */
741 native_to_darwin_pflag(&dep
->p_flag
, p
);
742 dep
->p_stat
= p
->p_stat
; /* XXX Neary the same */
743 dep
->p_pid
= p
->p_pid
;
744 dep
->p_oppid
= p
->p_opptr
->p_pid
;
745 dep
->p_dupfd
= curlwp
->l_dupfd
; /* XXX */
747 /* dep->exit_thread */
748 /* dep->p_debugger */
750 dep
->p_estcpu
= p
->p_estcpu
;
752 dep
->p_pctcpu
= p
->p_pctcpu
;
753 /* (ptr) dep->p_wchan */
754 /* (ptr) dep->p_wmesg */
757 /* dep->p_realtimer */
758 memcpy(&dep
->p_rtime
, &p
->p_rtime
, sizeof(p
->p_rtime
));
759 dep
->p_uticks
= p
->p_uticks
;
760 dep
->p_sticks
= p
->p_sticks
;
761 dep
->p_iticks
= p
->p_iticks
;
762 dep
->p_traceflag
= p
->p_traceflag
; /* XXX */
763 /* (ptr) dep->p_tracep */
764 native_sigset13_to_sigset(&dep
->p_siglist
, &l
->l_sigpendset
->sp_set
);
765 /* (ptr) dep->p_textvp */
767 native_sigset13_to_sigset(&dep
->p_sigmask
, &l
->l_sigmask
);
768 native_sigset13_to_sigset(&dep
->p_sigignore
,
769 &p
->p_sigctx
.ps_sigignore
);
770 native_sigset13_to_sigset(&dep
->p_sigcatch
,
771 &p
->p_sigctx
.ps_sigcatch
);
772 dep
->p_priority
= l
->l_priority
;
773 dep
->p_nice
= p
->p_nice
;
774 (void)strlcpy(dep
->p_comm
, p
->p_comm
, DARWIN_MAXCOMLEN
);
775 /* (ptr) dep->p_pgrp */
776 /* (ptr) dep->p_addr */
777 dep
->p_xstat
= p
->p_xstat
;
778 dep
->p_acflag
= p
->p_acflag
; /* XXX accounting flags */
779 /* (ptr) dep->p_ru */
781 /* (ptr) */ de
->e_paddr
= (struct darwin_proc
*)p
;
782 /* (ptr) */ de
->e_sess
=
783 (struct darwin_session
*)p
->p_session
;
784 de
->e_pcred
.pc_ruid
= kauth_cred_getuid(p
->p_cred
);
785 de
->e_pcred
.pc_svuid
= kauth_cred_getsvuid(p
->p_cred
);
786 de
->e_pcred
.pc_rgid
= kauth_cred_getgid(p
->p_cred
);
787 de
->e_pcred
.pc_svgid
= kauth_cred_getsvgid(p
->p_cred
);
788 de
->e_pcred
.pc_refcnt
= kauth_cred_getrefcnt(p
->p_cred
);
789 /* XXX elad ? de->e_ucred.cr_ref = p->p_ucred->cr_ref; */
790 /* XXX elad ? de->e_ucred.cr_ref = kauth_cred_getrefcnt(p->p_cred); */
791 de
->e_ucred
.cr_uid
= kauth_cred_geteuid(p
->p_cred
);
792 de
->e_ucred
.cr_ngroups
= kauth_cred_ngroups(p
->p_cred
);
793 kauth_cred_getgroups(p
->p_cred
, de
->e_ucred
.cr_groups
,
794 sizeof(de
->e_ucred
.cr_groups
) / sizeof(de
->e_ucred
.cr_groups
[0]),
796 de
->e_vm
.vm_refcnt
= p
->p_vmspace
->vm_refcnt
;
797 de
->e_vm
.vm_rssize
= p
->p_vmspace
->vm_rssize
;
798 de
->e_vm
.vm_swrss
= p
->p_vmspace
->vm_swrss
;
799 de
->e_vm
.vm_tsize
= p
->p_vmspace
->vm_tsize
;
800 de
->e_vm
.vm_dsize
= p
->p_vmspace
->vm_dsize
;
801 de
->e_vm
.vm_ssize
= p
->p_vmspace
->vm_ssize
;
802 de
->e_vm
.vm_taddr
= p
->p_vmspace
->vm_taddr
;
803 de
->e_vm
.vm_daddr
= p
->p_vmspace
->vm_daddr
;
804 de
->e_vm
.vm_maxsaddr
= p
->p_vmspace
->vm_maxsaddr
;
805 de
->e_ppid
= p
->p_pptr
->p_pid
;
806 de
->e_pgid
= p
->p_pgid
;
807 de
->e_jobc
= p
->p_pgrp
->pg_jobc
;
808 if ((p
->p_lflag
& PL_CONTROLT
) && (p
->p_session
->s_ttyp
!= NULL
)) {
810 native_to_darwin_dev(p
->p_session
->s_ttyp
->t_dev
);
811 de
->e_tpgid
= p
->p_session
->s_ttyp
->t_pgrp
?
812 p
->p_session
->s_ttyp
->t_pgrp
->pg_id
: NO_PGID
;
813 /* (ptr) */ de
->e_tsess
= (struct darwin_session
*)
814 p
->p_session
->s_ttyp
->t_session
;
816 de
->e_tdev
= (darwin_dev_t
)NODEV
;
818 /* (ptr) de->e_tsess */
820 if (l
->l_wchan
&& l
->l_wmesg
)
821 strlcpy(de
->e_wmesg
, l
->l_wmesg
, DARWIN_WMESGLEN
);
826 de
->e_flag
= p
->p_session
->s_ttyvp
? DARWIN_EPROC_CTTY
: 0;
829 de
->e_flag
|= DARWIN_EPROC_SLEADER
;
830 (void)strlcpy(de
->e_login
,
831 p
->p_session
->s_login
, DARWIN_COMAPT_MAXLOGNAME
);
838 native_to_darwin_pflag(int *dfp
, struct proc
*p
)
842 int bsf
= p
->p_sflag
;
843 int bslf
= p
->p_slflag
;
847 l
= LIST_FIRST(&p
->p_lwps
);
852 df
|= DARWIN_P_ADVLOCK
;
853 if (bf
& PL_CONTROLT
) /* XXXAD */
854 df
|= DARWIN_P_CONTROLT
;
855 if (bsf
& PS_NOCLDSTOP
)
856 df
|= DARWIN_P_NOCLDSTOP
;
857 if (p
->p_lflag
& PL_PPWAIT
)
858 df
|= DARWIN_P_PPWAIT
;
859 if (bsf
& PST_PROFIL
)
860 df
|= DARWIN_P_PROFIL
;
862 df
|= DARWIN_P_SUGID
;
864 df
|= DARWIN_P_SYSTEM
;
865 if (bslf
& PSL_TRACED
)
866 df
|= DARWIN_P_TRACED
;
869 df
|= DARWIN_P_WAITED
;
872 df
|= DARWIN_P_WEXIT
;
876 df
|= DARWIN_P_OWEUPC
;
877 if (bslf
& PSL_FSTRACE
)
878 df
|= DARWIN_P_FSTRACE
;
879 if (bf
& PK_NOCLDWAIT
)
880 df
|= DARWIN_P_NOCLDWAIT
;
885 /* Derived from sys/kern/kern_sysctl.c:sysctl_procargs() */
887 darwin_sysctl_procargs(SYSCTLFN_ARGS
)
889 struct ps_strings pss
;
891 size_t len
, upper_bound
, xlen
, i
;
896 int nargv
, nenv
, nstr
, error
;
905 if ((p
= pfind(pid
)) == NULL
)
908 /* only root or same user change look at the environment */
909 if (kauth_cred_geteuid(l
->l_cred
) != 0) {
910 if (kauth_cred_getuid(l
->l_cred
) !=
911 kauth_cred_getuid(p
->p_cred
) ||
912 kauth_cred_getuid(l
->l_cred
) !=
913 kauth_cred_getsvuid(p
->p_cred
))
918 *oldlenp
= ARG_MAX
; /* XXX XXX XXX */
923 * Zombies don't have a stack, so we can't read their psstrings.
924 * System processes also don't have a user stack.
926 if (P_ZOMBIE(p
) || (p
->p_flag
& PK_SYSTEM
) != 0)
930 * Lock the process down in memory.
932 /* XXXCDC: how should locking work here? */
933 if ((p
->p_sflag
& PS_WEXIT
) || (p
->p_vmspace
->vm_refcnt
< 1))
936 p
->p_vmspace
->vm_refcnt
++; /* XXX */
939 * Allocate a temporary buffer to hold the arguments.
941 arg
= malloc(PAGE_SIZE
, M_TEMP
, M_WAITOK
);
944 * Zero fill the destination buffer.
946 (void)memset(arg
, 0, PAGE_SIZE
);
947 upper_bound
= *oldlenp
;
949 while (len
< upper_bound
) {
950 if (len
+ PAGE_SIZE
> upper_bound
)
951 xlen
= len
- upper_bound
;
955 if ((error
= copyout(arg
, (char *)oldp
+ len
, xlen
)) != 0)
962 * Read in the ps_strings structure.
964 aiov
.iov_base
= &pss
;
965 aiov
.iov_len
= sizeof(pss
);
966 auio
.uio_iov
= &aiov
;
968 auio
.uio_offset
= (vaddr_t
)p
->p_psstr
;
969 auio
.uio_resid
= sizeof(pss
);
970 auio
.uio_rw
= UIO_READ
;
971 UIO_SETUP_SYSSPACE(&auio
);
972 if ((error
= uvm_io(&p
->p_vmspace
->vm_map
, &auio
)) != 0)
976 * Get argument vector address and length. Since we want to
977 * copy argv and env at the same time, we add their lengths.
979 memcpy(&nargv
, (char *)&pss
+ p
->p_psnargv
, sizeof(nargv
));
980 memcpy(&nenv
, (char *)&pss
+ p
->p_psnenv
, sizeof(nargv
));
982 memcpy(&tmp
, (char *)&pss
+ p
->p_psargv
, sizeof(tmp
));
984 auio
.uio_offset
= (off_t
)(long)tmp
;
985 aiov
.iov_base
= &argv
;
986 aiov
.iov_len
= sizeof(argv
);
987 auio
.uio_iov
= &aiov
;
989 auio
.uio_resid
= sizeof(argv
);
990 auio
.uio_rw
= UIO_READ
;
991 UIO_SETUP_SYSSPACE(&auio
);
992 if ((error
= uvm_io(&p
->p_vmspace
->vm_map
, &auio
)) != 0)
997 * Check the whole argument vector to discover its size
998 * We have to do this since Darwin's ps insist about having
999 * the data at the end of the buffer.
1002 upper_bound
= *oldlenp
;
1003 for (; nstr
!= 0 && len
< upper_bound
; len
+= xlen
) {
1004 aiov
.iov_base
= arg
;
1005 aiov
.iov_len
= PAGE_SIZE
;
1006 auio
.uio_iov
= &aiov
;
1007 auio
.uio_iovcnt
= 1;
1008 auio
.uio_offset
= argv
+ len
;
1009 xlen
= PAGE_SIZE
- ((argv
+ len
) & PAGE_MASK
);
1010 auio
.uio_resid
= xlen
;
1011 auio
.uio_rw
= UIO_READ
;
1012 UIO_SETUP_SYSSPACE(&auio
);
1013 error
= uvm_io(&p
->p_vmspace
->vm_map
, &auio
);
1017 for (i
= 0;i
< xlen
&& nstr
!= 0; i
++) {
1019 nstr
--; /* one full string */
1023 * Make sure we don't reach the
1024 * end of the user's buffer.
1026 if (len
+ i
> upper_bound
)
1027 i
= upper_bound
- len
;
1036 * Try to keep one null word at the
1037 * end, and align on a word boundary
1039 len
= (((u_long
)oldp
+ len
- 5) & ~0x3UL
) - (u_long
)oldp
;
1040 len
= upper_bound
- len
;
1043 * Align to a word boundary, and copy the program name
1045 len
= (((u_long
)oldp
+ len
- 1) & ~0x3UL
) - (u_long
)oldp
;
1046 len
= len
- strlen(p
->p_comm
);
1047 if (len
> upper_bound
)
1050 error
= copyout(p
->p_comm
, (char *)oldp
+ len
, strlen(p
->p_comm
) + 1);
1054 len
= len
+ strlen(p
->p_comm
);
1055 len
= (((u_long
)oldp
+ len
+ 5) & ~0x3UL
) - (u_long
)oldp
;
1058 * Now copy in the actual argument vector, one page at a time,
1059 * since we don't know how long the vector is (though, we do
1060 * know how many NUL-terminated strings are in the vector).
1062 upper_bound
= *oldlenp
;
1063 nstr
= nargv
+ nenv
;
1064 for (; nstr
!= 0 && len
< upper_bound
; len
+= xlen
) {
1065 aiov
.iov_base
= arg
;
1066 aiov
.iov_len
= PAGE_SIZE
;
1067 auio
.uio_iov
= &aiov
;
1068 auio
.uio_iovcnt
= 1;
1069 auio
.uio_offset
= argv
+ len
;
1070 xlen
= PAGE_SIZE
- ((argv
+ len
) & PAGE_MASK
);
1071 auio
.uio_resid
= xlen
;
1072 auio
.uio_rw
= UIO_READ
;
1073 UIO_SETUP_SYSSPACE(&auio
);
1074 error
= uvm_io(&p
->p_vmspace
->vm_map
, &auio
);
1078 for (i
= 0;i
< xlen
&& nstr
!= 0; i
++) {
1080 nstr
--; /* one full string */
1084 * Make sure we don't copyout past the end of the user's
1087 if (len
+ i
> upper_bound
)
1088 i
= upper_bound
- len
;
1090 if ((error
= copyout(arg
, (char *)oldp
+ len
, i
)) != 0)
1100 uvmspace_free(p
->p_vmspace
);