]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/proc_info.c
xnu-1699.24.8.tar.gz
[apple/xnu.git] / bsd / kern / proc_info.c
CommitLineData
0c530ab8 1/*
6d2010ae 2 * Copyright (c) 2005, 2010 Apple Computer, Inc. All rights reserved.
0c530ab8 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0c530ab8 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
0c530ab8 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
0c530ab8
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
0c530ab8 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
0c530ab8
A
27 */
28
29/*
30 * sysctl system call.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/malloc.h>
37#include <sys/proc_internal.h>
38#include <sys/kauth.h>
39#include <sys/file_internal.h>
40#include <sys/vnode_internal.h>
41#include <sys/unistd.h>
42#include <sys/buf.h>
43#include <sys/ioctl.h>
44#include <sys/namei.h>
45#include <sys/tty.h>
46#include <sys/disklabel.h>
47#include <sys/vm.h>
48#include <sys/sysctl.h>
49#include <sys/user.h>
50#include <sys/aio_kern.h>
51
b0d623f7 52#include <security/audit/audit.h>
0c530ab8
A
53
54#include <mach/machine.h>
55#include <mach/mach_types.h>
56#include <mach/vm_param.h>
57#include <kern/task.h>
58#include <kern/lock.h>
59#include <kern/kalloc.h>
6d2010ae 60#include <kern/assert.h>
0c530ab8
A
61#include <vm/vm_kern.h>
62#include <vm/vm_map.h>
63#include <mach/host_info.h>
64#include <mach/task_info.h>
65#include <mach/thread_info.h>
66#include <mach/vm_region.h>
67
68#include <sys/mount_internal.h>
69#include <sys/proc_info.h>
70#include <sys/bsdtask_info.h>
71#include <sys/kdebug.h>
72#include <sys/sysproto.h>
73#include <sys/msgbuf.h>
74
2d21ac55 75#include <sys/msgbuf.h>
0c530ab8
A
76
77#include <machine/machine_routines.h>
78
6d2010ae
A
79#include <kern/ipc_misc.h>
80
0c530ab8
A
81#include <vm/vm_protos.h>
82
83struct pshmnode;
84struct psemnode;
85struct pipe;
86struct kqueue;
87struct atalk;
88
b0d623f7
A
89uint64_t get_dispatchqueue_offset_from_proc(void *);
90int proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
0c530ab8
A
91
92/* protos for proc_info calls */
b0d623f7
A
93int proc_listpids(uint32_t type, uint32_t tyoneinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
94int proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
95int proc_pidfdinfo(int pid, int flavor,int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
96int proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval);
97int proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
6d2010ae 98int proc_pidfileportinfo(int pid, int flavor, mach_port_name_t name, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
0c530ab8
A
99
100/* protos for procpidinfo calls */
b0d623f7
A
101int proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
102int proc_pidbsdinfo(proc_t p, struct proc_bsdinfo *pbsd, int zombie);
6d2010ae 103int proc_pidshortbsdinfo(proc_t p, struct proc_bsdshortinfo *pbsd_shortp, int zombie);
0c530ab8 104int proc_pidtaskinfo(proc_t p, struct proc_taskinfo *ptinfo);
b0d623f7 105int proc_pidallinfo(proc_t p, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
0c530ab8 106int proc_pidthreadinfo(proc_t p, uint64_t arg, struct proc_threadinfo *pthinfo);
2d21ac55 107int proc_pidthreadpathinfo(proc_t p, uint64_t arg, struct proc_threadwithpathinfo *pinfo);
b0d623f7
A
108int proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
109int proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
110int proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
111int proc_pidvnodepathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
112int proc_pidpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
113int proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo);
6d2010ae 114int proc_pidfileportlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
0c530ab8
A
115
116
117/* protos for proc_pidfdinfo calls */
b0d623f7
A
118int pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
119int pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
120int pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
121int pid_pseminfo(struct psemnode * psem, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
122int pid_pshminfo(struct pshmnode * pshm, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
123int pid_pipeinfo(struct pipe * p, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
124int pid_kqueueinfo(struct kqueue * kq, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
125int pid_atalkinfo(struct atalk * at, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
0c530ab8
A
126
127
128/* protos for misc */
129
130int fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo);
2d21ac55 131void fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * finfo);
0c530ab8 132static int proc_security_policy(proc_t p);
2d21ac55 133static void munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp);
0c530ab8 134
b0d623f7
A
135uint64_t get_dispatchqueue_offset_from_proc(void *p)
136{
137 if(p != NULL) {
138 proc_t pself = (proc_t)p;
139 return (pself->p_dispatchqueue_offset);
140 } else {
141 return (uint64_t)0;
142 }
143}
144
0c530ab8
A
145/***************************** proc_info ********************/
146
147int
b0d623f7 148proc_info(__unused struct proc *p, struct proc_info_args * uap, int32_t *retval)
0c530ab8
A
149{
150 return(proc_info_internal(uap->callnum, uap->pid, uap->flavor, uap->arg, uap->buffer, uap->buffersize, retval));
151}
152
153
154int
b0d623f7 155proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8
A
156{
157
158 switch(callnum) {
159 case 1: /* proc_listpids */
160 /* pid contains type and flavor contains typeinfo */
161 return(proc_listpids(pid, flavor, buffer, buffersize, retval));
162 case 2: /* proc_pidinfo */
163 return(proc_pidinfo(pid, flavor, arg, buffer, buffersize, retval));
164 case 3: /* proc_pidfdinfo */
165 return(proc_pidfdinfo(pid, flavor, (int)arg, buffer, buffersize, retval));
166 case 4: /* proc_kernmsgbuf */
2d21ac55 167 return(proc_kernmsgbuf(buffer, buffersize, retval));
b0d623f7
A
168 case 5: /* set on self properties proc_setcontrol */
169 return(proc_setcontrol(pid, flavor, arg, buffer, buffersize, retval));
6d2010ae
A
170 case 6: /* proc_pidfileportinfo */
171 return(proc_pidfileportinfo(pid, flavor, (mach_port_name_t)arg, buffer, buffersize, retval));
172
0c530ab8
A
173 default:
174 return(EINVAL);
175 }
176
177 return(EINVAL);
178}
179
180/******************* proc_listpids routine ****************/
181int
b0d623f7 182proc_listpids(uint32_t type, uint32_t typeinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8 183{
0c530ab8
A
184 int numprocs, wantpids;
185 char * kbuf;
186 int * ptr;
187 int n, skip;
188 struct proc * p;
b0d623f7 189 struct tty * tp;
0c530ab8 190 int error = 0;
6d2010ae 191 struct proclist *current_list;
0c530ab8
A
192
193 /* if the buffer is null, return num of procs */
194 if (buffer == (user_addr_t)0) {
195 *retval = ((nprocs+20) * sizeof(int));
196 return(0);
197 }
198
199 if (buffersize < sizeof(int)) {
200 return(ENOMEM);
201 }
202 wantpids = buffersize/sizeof(int);
203 numprocs = nprocs+20;
204 if (numprocs > wantpids)
205 numprocs = wantpids;
206
207 kbuf = (char *)kalloc((vm_size_t)(numprocs * sizeof(int)));
2d21ac55
A
208 if (kbuf == NULL)
209 return(ENOMEM);
0c530ab8
A
210 bzero(kbuf, sizeof(int));
211
2d21ac55
A
212 proc_list_lock();
213
0c530ab8
A
214
215 n = 0;
216 ptr = (int *)kbuf;
6d2010ae
A
217 current_list = &allproc;
218proc_loop:
219 LIST_FOREACH(p, current_list, p_list) {
0c530ab8
A
220 skip = 0;
221 switch (type) {
222 case PROC_PGRP_ONLY:
2d21ac55 223 if (p->p_pgrpid != (pid_t)typeinfo)
0c530ab8
A
224 skip = 1;
225 break;
6d2010ae
A
226 case PROC_PPID_ONLY:
227 if ((p->p_ppid != (pid_t)typeinfo) && (((p->p_lflag & P_LTRACED) == 0) || (p->p_oppid != (pid_t)typeinfo)))
228 skip = 1;
229 break;
230
0c530ab8
A
231 case PROC_ALL_PIDS:
232 skip = 0;
233 break;
234 case PROC_TTY_ONLY:
2d21ac55 235 /* racy but list lock is held */
0c530ab8 236 if ((p->p_flag & P_CONTROLT) == 0 ||
2d21ac55 237 (p->p_pgrp == NULL) || (p->p_pgrp->pg_session == NULL) ||
b0d623f7
A
238 (tp = SESSION_TP(p->p_pgrp->pg_session)) == TTY_NULL ||
239 tp->t_dev != (dev_t)typeinfo)
0c530ab8
A
240 skip = 1;
241 break;
242 case PROC_UID_ONLY:
2d21ac55 243 if (p->p_ucred == NULL)
0c530ab8 244 skip = 1;
2d21ac55
A
245 else {
246 kauth_cred_t my_cred;
247 uid_t uid;
248
249 my_cred = kauth_cred_proc_ref(p);
250 uid = kauth_cred_getuid(my_cred);
251 kauth_cred_unref(&my_cred);
252 if (uid != (uid_t)typeinfo)
253 skip = 1;
254 }
0c530ab8
A
255 break;
256 case PROC_RUID_ONLY:
2d21ac55
A
257 if (p->p_ucred == NULL)
258 skip = 1;
259 else {
260 kauth_cred_t my_cred;
261 uid_t uid;
262
263 my_cred = kauth_cred_proc_ref(p);
6d2010ae 264 uid = kauth_cred_getruid(my_cred);
2d21ac55
A
265 kauth_cred_unref(&my_cred);
266 if (uid != (uid_t)typeinfo)
267 skip = 1;
268 }
0c530ab8
A
269 break;
270 default:
271 skip = 1;
272 break;
273 };
274
0c530ab8
A
275 if(skip == 0) {
276 *ptr++ = p->p_pid;
277 n++;
278 }
279 if (n >= numprocs)
280 break;
281 }
282
6d2010ae
A
283 if ((n < numprocs) && (current_list == &allproc)) {
284 current_list = &zombproc;
285 goto proc_loop;
0c530ab8 286 }
2d21ac55
A
287
288 proc_list_unlock();
0c530ab8
A
289
290 ptr = (int *)kbuf;
291 error = copyout((caddr_t)ptr, buffer, n * sizeof(int));
292 if (error == 0)
293 *retval = (n * sizeof(int));
294 kfree((void *)kbuf, (vm_size_t)(numprocs * sizeof(int)));
295
296 return(error);
297}
298
299
300/********************************** proc_pidinfo routines ********************************/
301
302int
b0d623f7 303proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval)
0c530ab8
A
304{
305 int numfds, needfds;
306 char * kbuf;
307 struct proc_fdinfo * pfd;
308 struct fileproc * fp;
309 int n;
310 int count = 0;
311 int error = 0;
312
313 numfds = p->p_fd->fd_nfiles;
314
315 if (buffer == (user_addr_t) 0) {
316 numfds += 20;
317 *retval = (numfds * sizeof(struct proc_fdinfo));
318 return(0);
319 }
320
321 /* buffersize is big enough atleast for one struct */
322 needfds = buffersize/sizeof(struct proc_fdinfo);
323
324 if (numfds > needfds)
325 numfds = needfds;
326
327 kbuf = (char *)kalloc((vm_size_t)(numfds * sizeof(struct proc_fdinfo)));
2d21ac55
A
328 if (kbuf == NULL)
329 return(ENOMEM);
0c530ab8
A
330 bzero(kbuf, numfds * sizeof(struct proc_fdinfo));
331
332 proc_fdlock(p);
333
334 pfd = (struct proc_fdinfo *)kbuf;
335
336 for (n = 0; ((n < numfds) && (n < p->p_fd->fd_nfiles)); n++) {
337 if (((fp = p->p_fd->fd_ofiles[n]) != 0)
338 && ((p->p_fd->fd_ofileflags[n] & UF_RESERVED) == 0)) {
339 pfd->proc_fd = n;
340 pfd->proc_fdtype = fp->f_fglob->fg_type;
341 count++;
342 pfd++;
343 }
344 }
345 proc_fdunlock(p);
346
347 error = copyout(kbuf, buffer, count * sizeof(struct proc_fdinfo));
348 kfree((void *)kbuf, (vm_size_t)(numfds * sizeof(struct proc_fdinfo)));
349 if (error == 0)
350 *retval = (count * sizeof(struct proc_fdinfo));
351 return(error);
352}
353
6d2010ae
A
354/*
355 * Helper functions for proc_pidfileportlist.
356 */
357static int
358proc_fileport_count(__unused mach_port_name_t name,
359 __unused struct fileglob *fg, void *arg)
360{
361 uint32_t *counter = arg;
362
363 *counter += 1;
364 return (0);
365}
366
367struct fileport_fdtype_args {
368 struct proc_fileportinfo *ffa_pfi;
369 struct proc_fileportinfo *ffa_pfi_end;
370};
371
372static int
373proc_fileport_fdtype(mach_port_name_t name, struct fileglob *fg, void *arg)
374{
375 struct fileport_fdtype_args *ffa = arg;
376
377 if (ffa->ffa_pfi != ffa->ffa_pfi_end) {
378 ffa->ffa_pfi->proc_fdtype = fg->fg_type;
379 ffa->ffa_pfi->proc_fileport = name;
380 ffa->ffa_pfi++;
381 return (0); /* keep walking */
382 } else
383 return (-1); /* stop the walk! */
384}
385
386int
387proc_pidfileportlist(proc_t p,
388 user_addr_t buffer, uint32_t buffersize, int32_t *retval)
389{
390 void *kbuf;
391 vm_size_t kbufsize;
392 struct proc_fileportinfo *pfi;
393 uint32_t needfileports, numfileports;
394 struct fileport_fdtype_args ffa;
395 int error;
396
397 needfileports = buffersize / sizeof (*pfi);
398 if ((user_addr_t)0 == buffer || needfileports > (uint32_t)maxfiles) {
399 /*
400 * Either (i) the user is asking for a fileport count,
401 * or (ii) the number of fileports they're asking for is
402 * larger than the maximum number of open files (!); count
403 * them to bound subsequent heap allocations.
404 */
405 numfileports = 0;
406 switch (fileport_walk(p->task,
407 proc_fileport_count, &numfileports)) {
408 case KERN_SUCCESS:
409 break;
410 case KERN_RESOURCE_SHORTAGE:
411 return (ENOMEM);
412 case KERN_INVALID_TASK:
413 return (ESRCH);
414 default:
415 return (EINVAL);
416 }
417
418 if (numfileports == 0) {
419 *retval = 0; /* none at all, bail */
420 return (0);
421 }
422 if ((user_addr_t)0 == buffer) {
423 numfileports += 20; /* accelerate convergence */
424 *retval = numfileports * sizeof (*pfi);
425 return (0);
426 }
427 if (needfileports > numfileports)
428 needfileports = numfileports;
429 }
430
431 assert(buffersize >= PROC_PIDLISTFILEPORTS_SIZE);
432
433 kbufsize = (vm_size_t)needfileports * sizeof (*pfi);
434 pfi = kbuf = kalloc(kbufsize);
435 if (kbuf == NULL)
436 return (ENOMEM);
437 bzero(kbuf, kbufsize);
438
439 ffa.ffa_pfi = pfi;
440 ffa.ffa_pfi_end = pfi + needfileports;
441
442 switch (fileport_walk(p->task, proc_fileport_fdtype, &ffa)) {
443 case KERN_SUCCESS:
444 error = 0;
445 pfi = ffa.ffa_pfi;
446 if ((numfileports = pfi - (typeof(pfi))kbuf) == 0)
447 break;
448 if (numfileports > needfileports)
449 panic("more fileports returned than requested");
450 error = copyout(kbuf, buffer, numfileports * sizeof (*pfi));
451 break;
452 case KERN_RESOURCE_SHORTAGE:
453 error = ENOMEM;
454 break;
455 case KERN_INVALID_TASK:
456 error = ESRCH;
457 break;
458 default:
459 error = EINVAL;
460 break;
461 }
462 kfree(kbuf, kbufsize);
463 if (error == 0)
464 *retval = numfileports * sizeof (*pfi);
465 return (error);
466}
0c530ab8
A
467
468int
b0d623f7 469proc_pidbsdinfo(proc_t p, struct proc_bsdinfo * pbsd, int zombie)
0c530ab8
A
470{
471 register struct tty *tp;
472 struct session *sessionp = NULL;
2d21ac55
A
473 struct pgrp * pg;
474 kauth_cred_t my_cred;
0c530ab8 475
2d21ac55
A
476 pg = proc_pgrp(p);
477 sessionp = proc_session(p);
478
479 my_cred = kauth_cred_proc_ref(p);
0c530ab8
A
480 bzero(pbsd, sizeof(struct proc_bsdinfo));
481 pbsd->pbi_status = p->p_stat;
482 pbsd->pbi_xstatus = p->p_xstat;
483 pbsd->pbi_pid = p->p_pid;
2d21ac55 484 pbsd->pbi_ppid = p->p_ppid;
6d2010ae
A
485 pbsd->pbi_uid = kauth_cred_getuid(my_cred);
486 pbsd->pbi_gid = kauth_cred_getgid(my_cred);
487 pbsd->pbi_ruid = kauth_cred_getruid(my_cred);
488 pbsd->pbi_rgid = kauth_cred_getrgid(my_cred);
489 pbsd->pbi_svuid = kauth_cred_getsvuid(my_cred);
490 pbsd->pbi_svgid = kauth_cred_getsvgid(my_cred);
2d21ac55 491 kauth_cred_unref(&my_cred);
0c530ab8
A
492
493 pbsd->pbi_nice = p->p_nice;
b0d623f7
A
494 pbsd->pbi_start_tvsec = p->p_start.tv_sec;
495 pbsd->pbi_start_tvusec = p->p_start.tv_usec;
6d2010ae
A
496 bcopy(&p->p_comm, &pbsd->pbi_comm[0], MAXCOMLEN);
497 pbsd->pbi_comm[MAXCOMLEN - 1] = '\0';
498 bcopy(&p->p_name, &pbsd->pbi_name[0], 2*MAXCOMLEN);
499 pbsd->pbi_name[(2*MAXCOMLEN) - 1] = '\0';
0c530ab8
A
500
501 pbsd->pbi_flags = 0;
502 if ((p->p_flag & P_SYSTEM) == P_SYSTEM)
503 pbsd->pbi_flags |= PROC_FLAG_SYSTEM;
2d21ac55 504 if ((p->p_lflag & P_LTRACED) == P_LTRACED)
0c530ab8 505 pbsd->pbi_flags |= PROC_FLAG_TRACED;
2d21ac55 506 if ((p->p_lflag & P_LEXIT) == P_LEXIT)
0c530ab8 507 pbsd->pbi_flags |= PROC_FLAG_INEXIT;
2d21ac55 508 if ((p->p_lflag & P_LPPWAIT) == P_LPPWAIT)
0c530ab8
A
509 pbsd->pbi_flags |= PROC_FLAG_PPWAIT;
510 if ((p->p_flag & P_LP64) == P_LP64)
511 pbsd->pbi_flags |= PROC_FLAG_LP64;
512 if ((p->p_flag & P_CONTROLT) == P_CONTROLT)
513 pbsd->pbi_flags |= PROC_FLAG_CONTROLT;
2d21ac55
A
514 if ((p->p_flag & P_THCWD) == P_THCWD)
515 pbsd->pbi_flags |= PROC_FLAG_THCWD;
6d2010ae
A
516 if ((p->p_flag & P_SUGID) == P_SUGID)
517 pbsd->pbi_flags |= PROC_FLAG_PSUGID;
518 if ((p->p_flag & P_EXEC) == P_EXEC)
519 pbsd->pbi_flags |= PROC_FLAG_EXEC;
0c530ab8 520
b0d623f7
A
521 if (sessionp != SESSION_NULL) {
522 if (SESS_LEADER(p, sessionp))
523 pbsd->pbi_flags |= PROC_FLAG_SLEADER;
524 if (sessionp->s_ttyvp)
525 pbsd->pbi_flags |= PROC_FLAG_CTTY;
526 }
527
528
529 switch(PROC_CONTROL_STATE(p)) {
530 case P_PCTHROTTLE:
531 pbsd->pbi_flags |= PROC_FLAG_PC_THROTTLE;
532 break;
533 case P_PCSUSP:
534 pbsd->pbi_flags |= PROC_FLAG_PC_SUSP;
535 break;
536 case P_PCKILL:
537 pbsd->pbi_flags |= PROC_FLAG_PC_KILL;
538 break;
539 };
540
541 switch(PROC_ACTION_STATE(p)) {
542 case P_PCTHROTTLE:
543 pbsd->pbi_flags |= PROC_FLAG_PA_THROTTLE;
544 break;
545 case P_PCSUSP:
546 pbsd->pbi_flags |= PROC_FLAG_PA_SUSP;
547 break;
548 };
0c530ab8 549
6d2010ae
A
550 /* if process is a zombie skip bg state */
551 if ((zombie == 0) && (p->p_stat != SZOMB) && (p->task != TASK_NULL))
552 proc_get_darwinbgstate(p->task, &pbsd->pbi_flags);
553
b0d623f7
A
554 if (zombie == 0)
555 pbsd->pbi_nfiles = p->p_fd->fd_nfiles;
2d21ac55
A
556 if (pg != PGRP_NULL) {
557 pbsd->pbi_pgid = p->p_pgrpid;
558 pbsd->pbi_pjobc = pg->pg_jobc;
b0d623f7 559 if ((p->p_flag & P_CONTROLT) && (sessionp != SESSION_NULL) && (tp = SESSION_TP(sessionp))) {
0c530ab8 560 pbsd->e_tdev = tp->t_dev;
2d21ac55 561 pbsd->e_tpgid = sessionp->s_ttypgrpid;
0c530ab8
A
562 }
563 }
2d21ac55
A
564 if (sessionp != SESSION_NULL)
565 session_rele(sessionp);
566 if (pg != PGRP_NULL)
567 pg_rele(pg);
568
0c530ab8
A
569 return(0);
570}
571
572
6d2010ae
A
573int
574proc_pidshortbsdinfo(proc_t p, struct proc_bsdshortinfo * pbsd_shortp, int zombie)
575{
576 bzero(pbsd_shortp, sizeof(struct proc_bsdshortinfo));
577 pbsd_shortp->pbsi_pid = p->p_pid;
578 pbsd_shortp->pbsi_ppid = p->p_ppid;
579 pbsd_shortp->pbsi_pgid = p->p_pgrpid;
580 pbsd_shortp->pbsi_status = p->p_stat;
581 bcopy(&p->p_comm, &pbsd_shortp->pbsi_comm[0], MAXCOMLEN);
582 pbsd_shortp->pbsi_comm[MAXCOMLEN - 1] = '\0';
583
584 pbsd_shortp->pbsi_flags = 0;
585 if ((p->p_flag & P_SYSTEM) == P_SYSTEM)
586 pbsd_shortp->pbsi_flags |= PROC_FLAG_SYSTEM;
587 if ((p->p_lflag & P_LTRACED) == P_LTRACED)
588 pbsd_shortp->pbsi_flags |= PROC_FLAG_TRACED;
589 if ((p->p_lflag & P_LEXIT) == P_LEXIT)
590 pbsd_shortp->pbsi_flags |= PROC_FLAG_INEXIT;
591 if ((p->p_lflag & P_LPPWAIT) == P_LPPWAIT)
592 pbsd_shortp->pbsi_flags |= PROC_FLAG_PPWAIT;
593 if ((p->p_flag & P_LP64) == P_LP64)
594 pbsd_shortp->pbsi_flags |= PROC_FLAG_LP64;
595 if ((p->p_flag & P_CONTROLT) == P_CONTROLT)
596 pbsd_shortp->pbsi_flags |= PROC_FLAG_CONTROLT;
597 if ((p->p_flag & P_THCWD) == P_THCWD)
598 pbsd_shortp->pbsi_flags |= PROC_FLAG_THCWD;
599 if ((p->p_flag & P_SUGID) == P_SUGID)
600 pbsd_shortp->pbsi_flags |= PROC_FLAG_PSUGID;
601 if ((p->p_flag & P_EXEC) == P_EXEC)
602 pbsd_shortp->pbsi_flags |= PROC_FLAG_EXEC;
603
604 switch(PROC_CONTROL_STATE(p)) {
605 case P_PCTHROTTLE:
606 pbsd_shortp->pbsi_flags |= PROC_FLAG_PC_THROTTLE;
607 break;
608 case P_PCSUSP:
609 pbsd_shortp->pbsi_flags |= PROC_FLAG_PC_SUSP;
610 break;
611 case P_PCKILL:
612 pbsd_shortp->pbsi_flags |= PROC_FLAG_PC_KILL;
613 break;
614 };
615
616 switch(PROC_ACTION_STATE(p)) {
617 case P_PCTHROTTLE:
618 pbsd_shortp->pbsi_flags |= PROC_FLAG_PA_THROTTLE;
619 break;
620 case P_PCSUSP:
621 pbsd_shortp->pbsi_flags |= PROC_FLAG_PA_SUSP;
622 break;
623 };
624
625 /* if process is a zombie skip bg state */
626 if ((zombie == 0) && (p->p_stat != SZOMB) && (p->task != TASK_NULL))
627 proc_get_darwinbgstate(p->task, &pbsd_shortp->pbsi_flags);
628
629 pbsd_shortp->pbsi_uid = p->p_uid;
630 pbsd_shortp->pbsi_gid = p->p_gid;
631 pbsd_shortp->pbsi_ruid = p->p_ruid;
632 pbsd_shortp->pbsi_rgid = p->p_rgid;
633 pbsd_shortp->pbsi_svuid = p->p_svuid;
634 pbsd_shortp->pbsi_svgid = p->p_svgid;
635
636 return(0);
637}
638
0c530ab8
A
639int
640proc_pidtaskinfo(proc_t p, struct proc_taskinfo * ptinfo)
641{
642 task_t task;
643
644 task = p->task;
645
646 bzero(ptinfo, sizeof(struct proc_taskinfo));
647 fill_taskprocinfo(task, (struct proc_taskinfo_internal *)ptinfo);
648
649 return(0);
650}
651
652
653
654int
655proc_pidthreadinfo(proc_t p, uint64_t arg, struct proc_threadinfo *pthinfo)
656{
657 int error = 0;
658 uint64_t threadaddr = (uint64_t)arg;
659
660 bzero(pthinfo, sizeof(struct proc_threadinfo));
661
2d21ac55 662 error = fill_taskthreadinfo(p->task, threadaddr, (struct proc_threadinfo_internal *)pthinfo, NULL, NULL);
0c530ab8
A
663 if (error)
664 return(ESRCH);
665 else
666 return(0);
667
668}
669
b0d623f7
A
670void
671bsd_getthreadname(void *uth, char *buffer)
672{
673 struct uthread *ut = (struct uthread *)uth;
674 if(ut->pth_name)
675 bcopy(ut->pth_name,buffer,MAXTHREADNAMESIZE);
676}
0c530ab8 677
2d21ac55
A
678void
679bsd_threadcdir(void * uth, void *vptr, int *vidp)
680{
681 struct uthread * ut = (struct uthread *)uth;
682 vnode_t vp;
683 vnode_t *vpp = (vnode_t *)vptr;
684
685 vp = ut->uu_cdir;
686 if (vp != NULLVP) {
687 if (vpp != NULL) {
688 *vpp = vp;
689 if (vidp != NULL)
690 *vidp = vp->v_id;
691 }
692 }
693}
694
695
696int
697proc_pidthreadpathinfo(proc_t p, uint64_t arg, struct proc_threadwithpathinfo *pinfo)
698{
699 vnode_t vp = NULLVP;
700 int vid;
701 int error = 0;
702 uint64_t threadaddr = (uint64_t)arg;
703 int count;
704
705 bzero(pinfo, sizeof(struct proc_threadwithpathinfo));
706
707 error = fill_taskthreadinfo(p->task, threadaddr, (struct proc_threadinfo_internal *)&pinfo->pt, (void *)&vp, &vid);
708 if (error)
709 return(ESRCH);
710
711 if ((vp != NULLVP) && ((vnode_getwithvid(vp, vid)) == 0)) {
712 error = fill_vnodeinfo(vp, &pinfo->pvip.vip_vi) ;
713 if (error == 0) {
714 count = MAXPATHLEN;
715 vn_getpath(vp, &pinfo->pvip.vip_path[0], &count);
716 pinfo->pvip.vip_path[MAXPATHLEN-1] = 0;
717 }
718 vnode_put(vp);
719 }
720 return(error);
721}
722
723
724
0c530ab8 725int
b0d623f7 726proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval)
0c530ab8
A
727{
728 int count = 0;
729 int ret = 0;
730 int error = 0;
731 void * kbuf;
732 int numthreads;
733
734
735 count = buffersize/(sizeof(uint64_t));
736 numthreads = get_numthreads(p->task);
737
738 numthreads += 10;
739
740 if (numthreads > count)
741 numthreads = count;
742
743 kbuf = (void *)kalloc(numthreads * sizeof(uint64_t));
2d21ac55
A
744 if (kbuf == NULL)
745 return(ENOMEM);
0c530ab8
A
746 bzero(kbuf, numthreads * sizeof(uint64_t));
747
748 ret = fill_taskthreadlist(p->task, kbuf, numthreads);
749
750 error = copyout(kbuf, buffer, ret);
751 kfree(kbuf, numthreads * sizeof(uint64_t));
752 if (error == 0)
753 *retval = ret;
754 return(error);
755
756}
757
758
759int
b0d623f7 760proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
0c530ab8
A
761{
762 struct proc_regioninfo preginfo;
763 int ret, error = 0;
764
765 bzero(&preginfo, sizeof(struct proc_regioninfo));
b0d623f7 766 ret = fill_procregioninfo( p->task, arg, (struct proc_regioninfo_internal *)&preginfo, (uintptr_t *)0, (uint32_t *)0);
0c530ab8
A
767 if (ret == 0)
768 return(EINVAL);
769 error = copyout(&preginfo, buffer, sizeof(struct proc_regioninfo));
770 if (error == 0)
771 *retval = sizeof(struct proc_regioninfo);
772 return(error);
773}
774
775
776int
b0d623f7 777proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
0c530ab8
A
778{
779 struct proc_regionwithpathinfo preginfo;
780 int ret, error = 0;
b0d623f7 781 uintptr_t vnodeaddr= 0;
0c530ab8
A
782 uint32_t vnodeid= 0;
783 vnode_t vp;
784 int count;
785
786 bzero(&preginfo, sizeof(struct proc_regionwithpathinfo));
787
b0d623f7 788 ret = fill_procregioninfo( p->task, arg, (struct proc_regioninfo_internal *)&preginfo.prp_prinfo, (uintptr_t *)&vnodeaddr, (uint32_t *)&vnodeid);
0c530ab8
A
789 if (ret == 0)
790 return(EINVAL);
791 if (vnodeaddr) {
792 vp = (vnode_t)vnodeaddr;
793 if ((vnode_getwithvid(vp, vnodeid)) == 0) {
794 /* FILL THE VNODEINFO */
795 error = fill_vnodeinfo(vp, &preginfo.prp_vip.vip_vi);
796 count = MAXPATHLEN;
797 vn_getpath(vp, &preginfo.prp_vip.vip_path[0], &count);
798 /* Always make sure it is null terminated */
799 preginfo.prp_vip.vip_path[MAXPATHLEN-1] = 0;
800 vnode_put(vp);
801 }
802 }
803 error = copyout(&preginfo, buffer, sizeof(struct proc_regionwithpathinfo));
804 if (error == 0)
805 *retval = sizeof(struct proc_regionwithpathinfo);
806 return(error);
807}
808
2d21ac55
A
809/*
810 * Path is relative to current process directory; may different from current
811 * thread directory.
812 */
0c530ab8 813int
b0d623f7 814proc_pidvnodepathinfo(proc_t p, __unused uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
0c530ab8
A
815{
816 struct proc_vnodepathinfo pvninfo;
817 int error = 0;
818 vnode_t vncdirvp = NULLVP;
819 uint32_t vncdirid=0;
820 vnode_t vnrdirvp = NULLVP;
821 uint32_t vnrdirid=0;
822 int count;
823
824 bzero(&pvninfo, sizeof(struct proc_vnodepathinfo));
825
826 proc_fdlock(p);
827 if (p->p_fd->fd_cdir) {
828 vncdirvp = p->p_fd->fd_cdir;
829 vncdirid = p->p_fd->fd_cdir->v_id;
830 }
831 if (p->p_fd->fd_rdir) {
832 vnrdirvp = p->p_fd->fd_rdir;
833 vnrdirid = p->p_fd->fd_rdir->v_id;
834 }
835 proc_fdunlock(p);
836
837 if (vncdirvp != NULLVP) {
838 if ((error = vnode_getwithvid(vncdirvp, vncdirid)) == 0) {
839 /* FILL THE VNODEINFO */
840 error = fill_vnodeinfo(vncdirvp, &pvninfo.pvi_cdir.vip_vi);
841 if ( error == 0) {
842 count = MAXPATHLEN;
843 vn_getpath(vncdirvp, &pvninfo.pvi_cdir.vip_path[0], &count);
844 pvninfo.pvi_cdir.vip_path[MAXPATHLEN-1] = 0;
845 }
846 vnode_put(vncdirvp);
847 } else {
848 goto out;
849 }
850 }
851
852 if ((error == 0) && (vnrdirvp != NULLVP)) {
853 if ((error = vnode_getwithvid(vnrdirvp, vnrdirid)) == 0) {
854 /* FILL THE VNODEINFO */
855 error = fill_vnodeinfo(vnrdirvp, &pvninfo.pvi_rdir.vip_vi);
856 if ( error == 0) {
857 count = MAXPATHLEN;
858 vn_getpath(vnrdirvp, &pvninfo.pvi_rdir.vip_path[0], &count);
859 pvninfo.pvi_rdir.vip_path[MAXPATHLEN-1] = 0;
860 }
861 vnode_put(vnrdirvp);
862 } else {
863 goto out;
864 }
865 }
866 if (error == 0) {
867 error = copyout(&pvninfo, buffer, sizeof(struct proc_vnodepathinfo));
868 if (error == 0)
869 *retval = sizeof(struct proc_vnodepathinfo);
870 }
871out:
872 return(error);
873}
874
2d21ac55 875int
b0d623f7 876proc_pidpathinfo(proc_t p, __unused uint64_t arg, user_addr_t buffer, uint32_t buffersize, __unused int32_t *retval)
2d21ac55
A
877{
878 int vid, error;
879 vnode_t tvp;
880 vnode_t nvp = NULLVP;
881 int len = buffersize;
882 char * buf;
883
884 tvp = p->p_textvp;
885
886 if (tvp == NULLVP)
887 return(ESRCH);
888
889 buf = (char *)kalloc(buffersize);
890 if (buf == NULL)
891 return(ENOMEM);
892
893
894 vid = vnode_vid(tvp);
895 error = vnode_getwithvid(tvp, vid);
896 if (error == 0) {
b0d623f7 897 error = vn_getpath_fsenter(tvp, buf, &len);
2d21ac55
A
898 vnode_put(tvp);
899 if (error == 0) {
900 error = vnode_lookup(buf, 0, &nvp, vfs_context_current());
901 if ((error == 0) && ( nvp != NULLVP))
902 vnode_put(nvp);
903 if (error == 0) {
904 error = copyout(buf, buffer, len);
905 }
906 }
907 }
908 kfree(buf, buffersize);
909 return(error);
910}
911
912
b0d623f7
A
913int
914proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo)
915{
916 int error = 0;
917
918 bzero(pwqinfo, sizeof(struct proc_workqueueinfo));
919
920 error = fill_procworkqueue(p, pwqinfo);
921 if (error)
922 return(ESRCH);
923 else
924 return(0);
925
926}
0c530ab8
A
927/********************************** proc_pidinfo ********************************/
928
929
930int
b0d623f7 931proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8
A
932{
933 struct proc * p = PROC_NULL;
934 int error = ENOTSUP;
935 int gotref = 0;
936 int findzomb = 0;
6d2010ae 937 int refheld = 0, shortversion = 0;
0c530ab8 938 uint32_t size;
b0d623f7 939 int zombie = 0;
0c530ab8
A
940
941 switch (flavor) {
942 case PROC_PIDLISTFDS:
943 size = PROC_PIDLISTFD_SIZE;
944 if (buffer == (user_addr_t)0)
945 size = 0;
946 break;
947 case PROC_PIDTBSDINFO:
948 size = PROC_PIDTBSDINFO_SIZE;
949 break;
950 case PROC_PIDTASKINFO:
951 size = PROC_PIDTASKINFO_SIZE;
952 break;
953 case PROC_PIDTASKALLINFO:
954 size = PROC_PIDTASKALLINFO_SIZE;
955 break;
956 case PROC_PIDTHREADINFO:
957 size = PROC_PIDTHREADINFO_SIZE;
958 break;
959 case PROC_PIDLISTTHREADS:
960 size = PROC_PIDLISTTHREADS_SIZE;
961 break;
962 case PROC_PIDREGIONINFO:
963 size = PROC_PIDREGIONINFO_SIZE;
964 break;
965 case PROC_PIDREGIONPATHINFO:
966 size = PROC_PIDREGIONPATHINFO_SIZE;
967 break;
968 case PROC_PIDVNODEPATHINFO:
969 size = PROC_PIDVNODEPATHINFO_SIZE;
970 break;
2d21ac55
A
971 case PROC_PIDTHREADPATHINFO:
972 size = PROC_PIDTHREADPATHINFO_SIZE;
973 break;
974 case PROC_PIDPATHINFO:
975 size = MAXPATHLEN;
976 break;
b0d623f7
A
977 case PROC_PIDWORKQUEUEINFO:
978 /* kernel does not have workq info */
979 if (pid == 0)
980 return(EINVAL);
981 else
982 size = PROC_PIDWORKQUEUEINFO_SIZE;
983 break;
6d2010ae
A
984 case PROC_PIDT_SHORTBSDINFO:
985 size = PROC_PIDT_SHORTBSDINFO_SIZE;
986 break;
987 case PROC_PIDLISTFILEPORTS:
988 size = PROC_PIDLISTFILEPORTS_SIZE;
989 if (buffer == (user_addr_t)0)
990 size = 0;
991 break;
0c530ab8
A
992 default:
993 return(EINVAL);
994 }
995
996 if (buffersize < size)
997 return(ENOMEM);
998
2d21ac55
A
999 if ((flavor == PROC_PIDPATHINFO) && (buffersize > PROC_PIDPATHINFO_MAXSIZE)) {
1000 return(EOVERFLOW);
1001 }
1002
6d2010ae 1003 if ((flavor != PROC_PIDTBSDINFO) && (flavor != PROC_PIDPATHINFO) && (flavor != PROC_PIDT_SHORTBSDINFO)) {
2d21ac55 1004 if ((p = proc_find(pid)) == PROC_NULL) {
0c530ab8
A
1005 error = ESRCH;
1006 goto out;
1007 } else {
1008 gotref = 1;
1009
1010 /* Do we have permission to look into this ? */
1011 if ((error = proc_security_policy(p)) != 0) {
1012 goto out;
1013 }
1014 }
1015 }
1016 switch (flavor) {
1017 case PROC_PIDLISTFDS: {
1018 error = proc_pidfdlist(p, buffer, buffersize, retval);
1019 }
1020 break;
1021
6d2010ae
A
1022 case PROC_PIDT_SHORTBSDINFO:
1023 shortversion = 1;
0c530ab8
A
1024 case PROC_PIDTBSDINFO: {
1025 struct proc_bsdinfo pbsd;
6d2010ae 1026 struct proc_bsdshortinfo pbsd_short;
0c530ab8 1027
b0d623f7 1028 zombie = 0;
0c530ab8
A
1029 if (arg)
1030 findzomb = 1;
2d21ac55 1031 p = proc_find(pid);
0c530ab8 1032 if (p == PROC_NULL) {
b0d623f7 1033 if (findzomb)
6d2010ae 1034 p = proc_find_zombref(pid);
0c530ab8
A
1035 if (p == NULL) {
1036 error = ESRCH;
0c530ab8
A
1037 goto out;
1038 }
b0d623f7 1039 zombie = 1;
6d2010ae
A
1040 }
1041 refheld = 1;
0c530ab8 1042 /* Do we have permission to look into this ? */
6d2010ae
A
1043 if ((flavor != PROC_PIDT_SHORTBSDINFO) && ((error = proc_security_policy(p)) != 0)) {
1044 if (refheld != 0) {
1045 if (zombie != 0)
1046 proc_drop_zombref(p);
1047 else
1048 proc_rele(p);
1049 }
0c530ab8
A
1050 goto out;
1051 }
6d2010ae
A
1052 if (shortversion != 0) {
1053 error = proc_pidshortbsdinfo(p, &pbsd_short, zombie);
1054 } else {
1055 error = proc_pidbsdinfo(p, &pbsd, zombie);
1056 }
1057 if (refheld != 0) {
1058 if (zombie != 0)
1059 proc_drop_zombref(p);
1060 else
1061 proc_rele(p);
1062 }
0c530ab8 1063 if (error == 0) {
6d2010ae
A
1064 if (shortversion != 0) {
1065 error = copyout(&pbsd_short, buffer, sizeof(struct proc_bsdshortinfo));
1066 if (error == 0)
1067 *retval = sizeof(struct proc_bsdshortinfo);
1068 } else {
1069 error = copyout(&pbsd, buffer, sizeof(struct proc_bsdinfo));
1070 if (error == 0)
1071 *retval = sizeof(struct proc_bsdinfo);
1072 }
0c530ab8
A
1073 }
1074 }
1075 break;
1076
1077 case PROC_PIDTASKINFO: {
1078 struct proc_taskinfo ptinfo;
1079
1080 error = proc_pidtaskinfo(p, &ptinfo);
1081 if (error == 0) {
1082 error = copyout(&ptinfo, buffer, sizeof(struct proc_taskinfo));
1083 if (error == 0)
1084 *retval = sizeof(struct proc_taskinfo);
1085 }
1086 }
1087 break;
1088
1089 case PROC_PIDTASKALLINFO: {
1090 struct proc_taskallinfo pall;
1091
b0d623f7 1092 error = proc_pidbsdinfo(p, &pall.pbsd, 0);
0c530ab8
A
1093 error = proc_pidtaskinfo(p, &pall.ptinfo);
1094 if (error == 0) {
1095 error = copyout(&pall, buffer, sizeof(struct proc_taskallinfo));
1096 if (error == 0)
1097 *retval = sizeof(struct proc_taskallinfo);
1098 }
1099 }
1100 break;
1101
1102 case PROC_PIDTHREADINFO:{
1103 struct proc_threadinfo pthinfo;
1104
1105 error = proc_pidthreadinfo(p, arg, &pthinfo);
1106 if (error == 0) {
1107 error = copyout(&pthinfo, buffer, sizeof(struct proc_threadinfo));
1108 if (error == 0)
1109 *retval = sizeof(struct proc_threadinfo);
1110 }
1111 }
1112 break;
1113
1114 case PROC_PIDLISTTHREADS:{
1115 error = proc_pidlistthreads(p, buffer, buffersize, retval);
1116 }
1117 break;
1118
1119 case PROC_PIDREGIONINFO:{
1120 error = proc_pidregioninfo(p, arg, buffer, buffersize, retval);
1121 }
1122 break;
1123
1124
1125 case PROC_PIDREGIONPATHINFO:{
1126 error = proc_pidregionpathinfo(p, arg, buffer, buffersize, retval);
1127 }
1128 break;
1129
1130 case PROC_PIDVNODEPATHINFO:{
1131 error = proc_pidvnodepathinfo(p, arg, buffer, buffersize, retval);
1132 }
1133 break;
1134
2d21ac55
A
1135
1136 case PROC_PIDTHREADPATHINFO:{
1137 struct proc_threadwithpathinfo pinfo;
1138
1139 error = proc_pidthreadpathinfo(p, arg, &pinfo);
1140 if (error == 0) {
1141 error = copyout((caddr_t)&pinfo, buffer, sizeof(struct proc_threadwithpathinfo));
1142 if (error == 0)
1143 *retval = sizeof(struct proc_threadwithpathinfo);
1144 }
1145 }
1146 break;
1147
1148 case PROC_PIDPATHINFO: {
1149 p = proc_find(pid);
1150 if (p == PROC_NULL) {
1151 error = ESRCH;
1152 goto out;
1153 }
1154 gotref = 1;
1155 error = proc_pidpathinfo(p, arg, buffer, buffersize, retval);
1156 }
1157 break;
1158
b0d623f7
A
1159
1160 case PROC_PIDWORKQUEUEINFO:{
1161 struct proc_workqueueinfo pwqinfo;
1162
1163 error = proc_pidworkqueueinfo(p, &pwqinfo);
1164 if (error == 0) {
1165 error = copyout(&pwqinfo, buffer, sizeof(struct proc_workqueueinfo));
1166 if (error == 0)
1167 *retval = sizeof(struct proc_workqueueinfo);
1168 }
1169 }
1170 break;
1171
6d2010ae
A
1172 case PROC_PIDLISTFILEPORTS: {
1173 error = proc_pidfileportlist(p, buffer, buffersize,
1174 retval);
1175 }
1176 break;
1177
0c530ab8
A
1178 default:
1179 error = ENOTSUP;
1180 }
1181
1182out:
1183 if (gotref)
2d21ac55 1184 proc_rele(p);
0c530ab8
A
1185 return(error);
1186}
1187
1188
1189int
b0d623f7 1190pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1191{
1192 struct vnode_fdinfo vfi;
1193 int error= 0;
1194
1195 if ((error = vnode_getwithvid(vp, vid)) != 0) {
1196 return(error);
1197 }
1198 bzero(&vfi, sizeof(struct vnode_fdinfo));
2d21ac55 1199 fill_fileinfo(fp, closeonexec, &vfi.pfi);
0c530ab8
A
1200 error = fill_vnodeinfo(vp, &vfi.pvi);
1201 vnode_put(vp);
1202 if (error == 0) {
1203 error = copyout((caddr_t)&vfi, buffer, sizeof(struct vnode_fdinfo));
1204 if (error == 0)
1205 *retval = sizeof(struct vnode_fdinfo);
1206 }
1207 return(error);
1208}
1209
1210int
b0d623f7 1211pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1212{
1213 struct vnode_fdinfowithpath vfip;
1214 int count, error= 0;
1215
1216 if ((error = vnode_getwithvid(vp, vid)) != 0) {
1217 return(error);
1218 }
1219 bzero(&vfip, sizeof(struct vnode_fdinfowithpath));
2d21ac55 1220 fill_fileinfo(fp, closeonexec, &vfip.pfi);
0c530ab8
A
1221 error = fill_vnodeinfo(vp, &vfip.pvip.vip_vi) ;
1222 if (error == 0) {
1223 count = MAXPATHLEN;
1224 vn_getpath(vp, &vfip.pvip.vip_path[0], &count);
1225 vfip.pvip.vip_path[MAXPATHLEN-1] = 0;
1226 vnode_put(vp);
1227 error = copyout((caddr_t)&vfip, buffer, sizeof(struct vnode_fdinfowithpath));
1228 if (error == 0)
1229 *retval = sizeof(struct vnode_fdinfowithpath);
1230 } else
1231 vnode_put(vp);
1232 return(error);
1233}
1234
1235void
2d21ac55 1236fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * fproc)
0c530ab8
A
1237{
1238 fproc->fi_openflags = fp->f_fglob->fg_flag;
2d21ac55 1239 fproc->fi_status = 0;
0c530ab8
A
1240 fproc->fi_offset = fp->f_fglob->fg_offset;
1241 fproc->fi_type = fp->f_fglob->fg_type;
2d21ac55
A
1242 if (fp->f_fglob->fg_count)
1243 fproc->fi_status |= PROC_FP_SHARED;
1244 if (closeonexec != 0)
1245 fproc->fi_status |= PROC_FP_CLEXEC;
0c530ab8
A
1246}
1247
1248
1249
1250int
1251fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo)
1252{
1253 vfs_context_t context;
2d21ac55 1254 struct stat64 sb;
0c530ab8
A
1255 int error = 0;
1256
0c530ab8 1257 context = vfs_context_create((vfs_context_t)0);
2d21ac55 1258 error = vn_stat(vp, &sb, NULL, 1, context);
0c530ab8
A
1259 (void)vfs_context_rele(context);
1260
2d21ac55
A
1261 munge_vinfo_stat(&sb, &vinfo->vi_stat);
1262
0c530ab8
A
1263 if (error != 0)
1264 goto out;
1265
1266 if (vp->v_mount != dead_mountp) {
1267 vinfo->vi_fsid = vp->v_mount->mnt_vfsstat.f_fsid;
1268 } else {
1269 vinfo->vi_fsid.val[0] = 0;
1270 vinfo->vi_fsid.val[1] = 0;
1271 }
1272 vinfo->vi_type = vp->v_type;
1273out:
1274 return(error);
1275}
1276
1277int
b0d623f7 1278pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8 1279{
2d21ac55 1280#if SOCKETS
0c530ab8
A
1281 struct socket_fdinfo s;
1282 int error = 0;
1283
1284 bzero(&s, sizeof(struct socket_fdinfo));
2d21ac55 1285 fill_fileinfo(fp, closeonexec, &s.pfi);
0c530ab8
A
1286 if ((error = fill_socketinfo(so, &s.psi)) == 0) {
1287 if ((error = copyout(&s, buffer, sizeof(struct socket_fdinfo))) == 0)
1288 *retval = sizeof(struct socket_fdinfo);
1289 }
0c530ab8 1290 return (error);
2d21ac55
A
1291#else
1292 *retval = 0;
1293 return (ENOTSUP);
1294#endif
0c530ab8
A
1295}
1296
1297int
b0d623f7 1298pid_pseminfo(struct psemnode *psem, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1299{
1300 struct psem_fdinfo pseminfo;
1301 int error = 0;
1302
1303 bzero(&pseminfo, sizeof(struct psem_fdinfo));
2d21ac55 1304 fill_fileinfo(fp, closeonexec, &pseminfo.pfi);
0c530ab8
A
1305
1306 if ((error = fill_pseminfo(psem, &pseminfo.pseminfo)) == 0) {
1307 if ((error = copyout(&pseminfo, buffer, sizeof(struct psem_fdinfo))) == 0)
1308 *retval = sizeof(struct psem_fdinfo);
1309 }
1310
1311 return(error);
1312}
1313
1314int
b0d623f7 1315pid_pshminfo(struct pshmnode *pshm, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1316{
1317 struct pshm_fdinfo pshminfo;
1318 int error = 0;
1319
1320 bzero(&pshminfo, sizeof(struct pshm_fdinfo));
2d21ac55 1321 fill_fileinfo(fp, closeonexec, &pshminfo.pfi);
0c530ab8
A
1322
1323 if ((error = fill_pshminfo(pshm, &pshminfo.pshminfo)) == 0) {
1324 if ((error = copyout(&pshminfo, buffer, sizeof(struct pshm_fdinfo))) == 0)
1325 *retval = sizeof(struct pshm_fdinfo);
1326 }
1327
1328 return(error);
1329}
1330
1331int
b0d623f7 1332pid_pipeinfo(struct pipe * p, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1333{
1334 struct pipe_fdinfo pipeinfo;
1335 int error = 0;
1336
1337 bzero(&pipeinfo, sizeof(struct pipe_fdinfo));
2d21ac55 1338 fill_fileinfo(fp, closeonexec, &pipeinfo.pfi);
0c530ab8
A
1339 if ((error = fill_pipeinfo(p, &pipeinfo.pipeinfo)) == 0) {
1340 if ((error = copyout(&pipeinfo, buffer, sizeof(struct pipe_fdinfo))) == 0)
1341 *retval = sizeof(struct pipe_fdinfo);
1342 }
1343
1344 return(error);
1345}
1346
1347int
b0d623f7 1348pid_kqueueinfo(struct kqueue * kq, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, int32_t * retval)
0c530ab8
A
1349{
1350 struct kqueue_fdinfo kqinfo;
1351 int error = 0;
1352
1353 bzero(&kqinfo, sizeof(struct kqueue_fdinfo));
1354
2d21ac55 1355 fill_fileinfo(fp, closeonexec, &kqinfo.pfi);
0c530ab8
A
1356
1357 if ((error = fill_kqueueinfo(kq, &kqinfo.kqueueinfo)) == 0) {
1358 if ((error = copyout(&kqinfo, buffer, sizeof(struct kqueue_fdinfo))) == 0)
1359 *retval = sizeof(struct kqueue_fdinfo);
1360 }
1361
1362 return(error);
1363}
1364
1365int
b0d623f7 1366pid_atalkinfo(__unused struct atalk * at, __unused struct fileproc *fp, __unused int closeonexec, __unused user_addr_t buffer, __unused uint32_t buffersize, __unused int32_t * retval)
0c530ab8
A
1367{
1368 return ENOTSUP;
1369}
1370
1371
1372
1373/************************** proc_pidfdinfo routine ***************************/
1374int
b0d623f7 1375proc_pidfdinfo(int pid, int flavor, int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8
A
1376{
1377 proc_t p;
1378 int error = ENOTSUP;
1379 struct fileproc * fp;
1380 uint32_t size;
2d21ac55 1381 int closeonexec = 0;
0c530ab8
A
1382
1383 switch (flavor) {
1384 case PROC_PIDFDVNODEINFO:
1385 size = PROC_PIDFDVNODEINFO_SIZE;
1386 break;
1387 case PROC_PIDFDVNODEPATHINFO:
1388 size = PROC_PIDFDVNODEPATHINFO_SIZE;
1389 break;
1390 case PROC_PIDFDSOCKETINFO:
1391 size = PROC_PIDFDSOCKETINFO_SIZE;
1392 break;
1393 case PROC_PIDFDPSEMINFO:
1394 size = PROC_PIDFDPSEMINFO_SIZE;
1395 break;
1396 case PROC_PIDFDPSHMINFO:
1397 size = PROC_PIDFDPSHMINFO_SIZE;
1398 break;
1399 case PROC_PIDFDPIPEINFO:
1400 size = PROC_PIDFDPIPEINFO_SIZE;
1401 break;
1402 case PROC_PIDFDKQUEUEINFO:
1403 size = PROC_PIDFDKQUEUEINFO_SIZE;
1404 break;
1405 case PROC_PIDFDATALKINFO:
1406 size = PROC_PIDFDATALKINFO_SIZE;
1407 break;
1408
1409 default:
1410 return(EINVAL);
1411
1412 }
1413
1414 if (buffersize < size)
1415 return(ENOMEM);
1416
2d21ac55 1417 if ((p = proc_find(pid)) == PROC_NULL) {
0c530ab8
A
1418 error = ESRCH;
1419 goto out;
1420 }
1421 /* Do we have permission to look into this ? */
1422 if ((error = proc_security_policy(p)) != 0) {
1423 goto out1;
1424 }
1425
1426 switch (flavor) {
1427 case PROC_PIDFDVNODEINFO: {
1428 vnode_t vp;
1429 uint32_t vid=0;
1430
1431 if ((error = fp_getfvpandvid(p, fd, &fp, &vp, &vid)) !=0) {
1432 goto out1;
1433 }
2d21ac55
A
1434 /* no need to be under the fdlock */
1435 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1436 error = pid_vnodeinfo(vp, vid, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1437 }
1438 break;
1439
1440 case PROC_PIDFDVNODEPATHINFO: {
1441 vnode_t vp;
1442 uint32_t vid=0;
1443
1444 if ((error = fp_getfvpandvid(p, fd, &fp, &vp, &vid)) !=0) {
1445 goto out1;
1446 }
1447
2d21ac55
A
1448 /* no need to be under the fdlock */
1449 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1450 error = pid_vnodeinfopath(vp, vid, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1451 }
1452 break;
1453
1454 case PROC_PIDFDSOCKETINFO: {
1455 socket_t so;
1456
1457 if ((error = fp_getfsock(p, fd, &fp, &so)) !=0) {
1458 goto out1;
1459 }
2d21ac55
A
1460 /* no need to be under the fdlock */
1461 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1462 error = pid_socketinfo(so, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1463 }
1464 break;
1465
1466 case PROC_PIDFDPSEMINFO: {
1467 struct psemnode * psem;
1468
1469 if ((error = fp_getfpsem(p, fd, &fp, &psem)) !=0) {
1470 goto out1;
1471 }
2d21ac55
A
1472 /* no need to be under the fdlock */
1473 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1474 error = pid_pseminfo(psem, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1475 }
1476 break;
1477
1478 case PROC_PIDFDPSHMINFO: {
1479 struct pshmnode * pshm;
1480
1481 if ((error = fp_getfpshm(p, fd, &fp, &pshm)) !=0) {
1482 goto out1;
1483 }
2d21ac55
A
1484 /* no need to be under the fdlock */
1485 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1486 error = pid_pshminfo(pshm, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1487 }
1488 break;
1489
1490 case PROC_PIDFDPIPEINFO: {
1491 struct pipe * cpipe;
1492
1493 if ((error = fp_getfpipe(p, fd, &fp, &cpipe)) !=0) {
1494 goto out1;
1495 }
2d21ac55
A
1496 /* no need to be under the fdlock */
1497 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1498 error = pid_pipeinfo(cpipe, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1499 }
1500 break;
1501
1502 case PROC_PIDFDKQUEUEINFO: {
1503 struct kqueue * kq;
1504
1505 if ((error = fp_getfkq(p, fd, &fp, &kq)) !=0) {
1506 goto out1;
1507 }
2d21ac55
A
1508 /* no need to be under the fdlock */
1509 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1510 error = pid_kqueueinfo(kq, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1511 }
1512 break;
1513
b0d623f7 1514#if NETAT
0c530ab8
A
1515 case PROC_PIDFDATALKINFO: {
1516 struct atalk * at;
1517
1518 if ((error = fp_getfatalk(p, fd, &fp, &at)) !=0) {
1519 goto out1;
1520 }
1521
2d21ac55
A
1522 /* no need to be under the fdlock */
1523 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1524 error = pid_atalkinfo(at, fp, closeonexec, buffer, buffersize, retval);
0c530ab8
A
1525 }
1526 break;
b0d623f7 1527#endif /* NETAT */
0c530ab8
A
1528 default: {
1529 error = EINVAL;
6d2010ae 1530 goto out1;
0c530ab8 1531 }
0c530ab8
A
1532 }
1533
1534 fp_drop(p, fd, fp , 0);
1535out1 :
2d21ac55 1536 proc_rele(p);
0c530ab8
A
1537out:
1538 return(error);
1539}
1540
6d2010ae
A
1541/*
1542 * Helper function for proc_pidfileportinfo
1543 */
1544
1545struct fileport_info_args {
1546 int fia_flavor;
1547 user_addr_t fia_buffer;
1548 uint32_t fia_buffersize;
1549 int32_t *fia_retval;
1550};
1551
1552static kern_return_t
1553proc_fileport_info(__unused mach_port_name_t name,
1554 struct fileglob *fg, void *arg)
1555{
1556 struct fileport_info_args *fia = arg;
1557 struct fileproc __fileproc, *fp = &__fileproc;
1558 int error;
1559
1560 bzero(fp, sizeof (*fp));
1561 fp->f_fglob = fg;
1562
1563 switch (fia->fia_flavor) {
1564 case PROC_PIDFILEPORTVNODEPATHINFO: {
1565 vnode_t vp;
1566
1567 if (fg->fg_type != DTYPE_VNODE) {
1568 error = ENOTSUP;
1569 break;
1570 }
1571 vp = (struct vnode *)fg->fg_data;
1572 error = pid_vnodeinfopath(vp, vnode_vid(vp), fp, 0,
1573 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
1574 } break;
1575
1576 case PROC_PIDFILEPORTSOCKETINFO: {
1577 socket_t so;
1578
1579 if (fg->fg_type != DTYPE_SOCKET) {
1580 error = EOPNOTSUPP;
1581 break;
1582 }
1583 so = (socket_t)fg->fg_data;
1584 error = pid_socketinfo(so, fp, 0,
1585 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
1586 } break;
1587
1588 case PROC_PIDFILEPORTPSHMINFO: {
1589 struct pshmnode *pshm;
1590
1591 if (fg->fg_type != DTYPE_PSXSHM) {
1592 error = EBADF; /* ick - mirror fp_getfpshm */
1593 break;
1594 }
1595 pshm = (struct pshmnode *)fg->fg_data;
1596 error = pid_pshminfo(pshm, fp, 0,
1597 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
1598 } break;
1599
1600 case PROC_PIDFILEPORTPIPEINFO: {
1601 struct pipe *cpipe;
1602
1603 if (fg->fg_type != DTYPE_PIPE) {
1604 error = EBADF; /* ick - mirror fp_getfpipe */
1605 break;
1606 }
1607 cpipe = (struct pipe *)fg->fg_data;
1608 error = pid_pipeinfo(cpipe, fp, 0,
1609 fia->fia_buffer, fia->fia_buffersize, fia->fia_retval);
1610 } break;
1611
1612 default:
1613 error = EINVAL;
1614 break;
1615 }
1616
1617 return (error);
1618}
1619
1620/************************* proc_pidfileportinfo routine *********************/
1621int
1622proc_pidfileportinfo(int pid, int flavor, mach_port_name_t name,
1623 user_addr_t buffer, uint32_t buffersize, int32_t *retval)
1624{
1625 proc_t p;
1626 int error = ENOTSUP;
1627 uint32_t size;
1628 struct fileport_info_args fia;
1629
1630 /* fileport types are restricted by filetype_issendable() */
1631
1632 switch (flavor) {
1633 case PROC_PIDFILEPORTVNODEPATHINFO:
1634 size = PROC_PIDFILEPORTVNODEPATHINFO_SIZE;
1635 break;
1636 case PROC_PIDFILEPORTSOCKETINFO:
1637 size = PROC_PIDFILEPORTSOCKETINFO_SIZE;
1638 break;
1639 case PROC_PIDFILEPORTPSHMINFO:
1640 size = PROC_PIDFILEPORTPSHMINFO_SIZE;
1641 break;
1642 case PROC_PIDFILEPORTPIPEINFO:
1643 size = PROC_PIDFILEPORTPIPEINFO_SIZE;
1644 break;
1645 default:
1646 return (EINVAL);
1647 }
1648
1649 if (buffersize < size)
1650 return (ENOMEM);
1651 if ((p = proc_find(pid)) == PROC_NULL) {
1652 error = ESRCH;
1653 goto out;
1654 }
1655 if ((error = proc_security_policy(p)) != 0) {
1656 goto out1;
1657 }
1658
1659 fia.fia_flavor = flavor;
1660 fia.fia_buffer = buffer;
1661 fia.fia_buffersize = buffersize;
1662 fia.fia_retval = retval;
1663
1664 if (fileport_invoke(p->task, name,
1665 proc_fileport_info, &fia, &error) != KERN_SUCCESS)
1666 error = EINVAL;
1667out1:
1668 proc_rele(p);
1669out:
1670 return (error);
1671}
0c530ab8
A
1672
1673static int
1674proc_security_policy(proc_t p)
1675{
2d21ac55
A
1676 kauth_cred_t my_cred;
1677 uid_t uid;
1678
1679 my_cred = kauth_cred_proc_ref(p);
1680 uid = kauth_cred_getuid(my_cred) ;
1681 kauth_cred_unref(&my_cred);
1682
1683 if ((uid != kauth_cred_getuid(kauth_cred_get()))
0c530ab8
A
1684 && suser(kauth_cred_get(), (u_short *)0)) {
1685 return(EPERM);
1686 }
1687
1688 return(0);
1689}
1690
0c530ab8 1691int
b0d623f7 1692proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval)
0c530ab8 1693{
0c530ab8 1694 if (suser(kauth_cred_get(), (u_short *)0) == 0) {
2d21ac55 1695 return(log_dmesg(buffer, buffersize, retval));
0c530ab8
A
1696 } else
1697 return(EPERM);
1698}
1699
b0d623f7
A
1700/* ********* process control sets on self only */
1701int
6d2010ae 1702proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, __unused int32_t * retval)
b0d623f7
A
1703{
1704 struct proc * pself = PROC_NULL;
1705 int error = 0;
1706 uint32_t pcontrol = (uint32_t)arg;
6d2010ae 1707 struct uthread *ut = NULL;
b0d623f7
A
1708
1709
1710 pself = current_proc();
1711 if (pid != pself->p_pid)
1712 return(EINVAL);
1713
b0d623f7
A
1714
1715 switch (flavor) {
1716 case PROC_SELFSET_PCONTROL: {
6d2010ae
A
1717 if (pcontrol > P_PCMAX)
1718 return(EINVAL);
b0d623f7
A
1719 proc_lock(pself);
1720 /* reset existing control setting while retaining action state */
1721 pself->p_pcaction &= PROC_ACTION_MASK;
1722 /* set new control state */
1723 pself->p_pcaction |= pcontrol;
1724 proc_unlock(pself);
1725 }
1726 break;
1727
6d2010ae
A
1728 case PROC_SELFSET_THREADNAME: {
1729 /* PROC_SELFSET_THREADNAME_SIZE = (MAXTHREADNAMESIZE -1) */
1730 if(buffersize > PROC_SELFSET_THREADNAME_SIZE)
1731 return ENAMETOOLONG;
1732 ut = current_uthread();
1733
1734 if(!ut->pth_name)
1735 {
1736 ut->pth_name = (char*)kalloc(MAXTHREADNAMESIZE );
1737 if(!ut->pth_name)
1738 return ENOMEM;
1739 }
1740 bzero(ut->pth_name, MAXTHREADNAMESIZE);
1741 error = copyin(buffer, ut->pth_name, buffersize);
1742 }
1743 break;
1744
1745 case PROC_SELFSET_VMRSRCOWNER: {
1746 /* need to to be superuser */
1747 if (suser(kauth_cred_get(), (u_short *)0) != 0) {
1748 error = EPERM;
1749 goto out;
1750 }
1751
1752 proc_lock(pself);
1753 /* reset existing control setting while retaining action state */
1754 pself->p_lflag |= P_LVMRSRCOWNER;
1755 proc_unlock(pself);
1756 }
1757 break;
1758
b0d623f7
A
1759 default:
1760 error = ENOTSUP;
1761 }
1762
6d2010ae 1763out:
b0d623f7
A
1764 return(error);
1765}
1766
1767
2d21ac55
A
1768/*
1769 * copy stat64 structure into vinfo_stat structure.
1770 */
1771static void
1772munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp)
1773{
1774 bzero(vsbp, sizeof(struct vinfo_stat));
1775
1776 vsbp->vst_dev = sbp->st_dev;
1777 vsbp->vst_mode = sbp->st_mode;
1778 vsbp->vst_nlink = sbp->st_nlink;
1779 vsbp->vst_ino = sbp->st_ino;
1780 vsbp->vst_uid = sbp->st_uid;
1781 vsbp->vst_gid = sbp->st_gid;
1782 vsbp->vst_atime = sbp->st_atimespec.tv_sec;
1783 vsbp->vst_atimensec = sbp->st_atimespec.tv_nsec;
1784 vsbp->vst_mtime = sbp->st_mtimespec.tv_sec;
1785 vsbp->vst_mtimensec = sbp->st_mtimespec.tv_nsec;
1786 vsbp->vst_ctime = sbp->st_ctimespec.tv_sec;
1787 vsbp->vst_ctimensec = sbp->st_ctimespec.tv_nsec;
1788 vsbp->vst_birthtime = sbp->st_birthtimespec.tv_sec;
1789 vsbp->vst_birthtimensec = sbp->st_birthtimespec.tv_nsec;
1790 vsbp->vst_size = sbp->st_size;
1791 vsbp->vst_blocks = sbp->st_blocks;
1792 vsbp->vst_blksize = sbp->st_blksize;
1793 vsbp->vst_flags = sbp->st_flags;
1794 vsbp->vst_gen = sbp->st_gen;
1795 vsbp->vst_rdev = sbp->st_rdev;
1796 vsbp->vst_qspare[0] = sbp->st_qspare[0];
1797 vsbp->vst_qspare[1] = sbp->st_qspare[1];
1798}