]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/proc_info.c
xnu-1228.12.14.tar.gz
[apple/xnu.git] / bsd / kern / proc_info.c
1 /*
2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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
52 #include <bsm/audit_kernel.h>
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>
60 #include <vm/vm_kern.h>
61 #include <vm/vm_map.h>
62 #include <mach/host_info.h>
63 #include <mach/task_info.h>
64 #include <mach/thread_info.h>
65 #include <mach/vm_region.h>
66
67 #include <sys/mount_internal.h>
68 #include <sys/proc_info.h>
69 #include <sys/bsdtask_info.h>
70 #include <sys/kdebug.h>
71 #include <sys/sysproto.h>
72 #include <sys/msgbuf.h>
73
74 #include <sys/msgbuf.h>
75
76 #include <machine/machine_routines.h>
77
78 #include <vm/vm_protos.h>
79
80 struct pshmnode;
81 struct psemnode;
82 struct pipe;
83 struct kqueue;
84 struct atalk;
85
86 int proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t * retval);
87
88 /* protos for proc_info calls */
89 int proc_listpids(uint32_t type, uint32_t tyoneinfo, user_addr_t buffer, uint32_t buffersize, register_t * retval);
90 int proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t * retval);
91 int proc_pidfdinfo(int pid, int flavor,int fd, user_addr_t buffer, uint32_t buffersize, register_t * retval);
92 int proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, register_t * retval);
93
94 /* protos for procpidinfo calls */
95 int proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, register_t *retval);
96 int proc_pidbsdinfo(proc_t p, struct proc_bsdinfo *pbsd);
97 int proc_pidtaskinfo(proc_t p, struct proc_taskinfo *ptinfo);
98 int proc_pidallinfo(proc_t p, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t *retval);
99 int proc_pidthreadinfo(proc_t p, uint64_t arg, struct proc_threadinfo *pthinfo);
100 int proc_pidthreadpathinfo(proc_t p, uint64_t arg, struct proc_threadwithpathinfo *pinfo);
101 int proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, register_t *retval);
102 int proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t *retval);
103 int proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t *retval);
104 int proc_pidvnodepathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t *retval);
105 int proc_pidpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t *retval);
106
107
108 /* protos for proc_pidfdinfo calls */
109 int pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval);
110 int pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval);
111 int pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval);
112 int pid_pseminfo(struct psemnode * psem, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval);
113 int pid_pshminfo(struct pshmnode * pshm, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval);
114 int pid_pipeinfo(struct pipe * p, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval);
115 int pid_kqueueinfo(struct kqueue * kq, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval);
116 int pid_atalkinfo(struct atalk * at, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval);
117
118
119 /* protos for misc */
120
121 int fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo);
122 void fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * finfo);
123 static int proc_security_policy(proc_t p);
124 static void munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp);
125
126 /***************************** proc_info ********************/
127
128 int
129 proc_info(__unused struct proc *p, struct proc_info_args * uap, register_t *retval)
130 {
131 return(proc_info_internal(uap->callnum, uap->pid, uap->flavor, uap->arg, uap->buffer, uap->buffersize, retval));
132 }
133
134
135 int
136 proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t * retval)
137 {
138
139 switch(callnum) {
140 case 1: /* proc_listpids */
141 /* pid contains type and flavor contains typeinfo */
142 return(proc_listpids(pid, flavor, buffer, buffersize, retval));
143 case 2: /* proc_pidinfo */
144 return(proc_pidinfo(pid, flavor, arg, buffer, buffersize, retval));
145 case 3: /* proc_pidfdinfo */
146 return(proc_pidfdinfo(pid, flavor, (int)arg, buffer, buffersize, retval));
147 case 4: /* proc_kernmsgbuf */
148 return(proc_kernmsgbuf(buffer, buffersize, retval));
149 default:
150 return(EINVAL);
151 }
152
153 return(EINVAL);
154 }
155
156 /******************* proc_listpids routine ****************/
157 int
158 proc_listpids(uint32_t type, uint32_t typeinfo, user_addr_t buffer, uint32_t buffersize, register_t * retval)
159 {
160 int numprocs, wantpids;
161 char * kbuf;
162 int * ptr;
163 int n, skip;
164 struct proc * p;
165 int error = 0;
166
167 /* if the buffer is null, return num of procs */
168 if (buffer == (user_addr_t)0) {
169 *retval = ((nprocs+20) * sizeof(int));
170 return(0);
171 }
172
173 if (buffersize < sizeof(int)) {
174 return(ENOMEM);
175 }
176 wantpids = buffersize/sizeof(int);
177 numprocs = nprocs+20;
178 if (numprocs > wantpids)
179 numprocs = wantpids;
180
181 kbuf = (char *)kalloc((vm_size_t)(numprocs * sizeof(int)));
182 if (kbuf == NULL)
183 return(ENOMEM);
184 bzero(kbuf, sizeof(int));
185
186 proc_list_lock();
187
188
189 n = 0;
190 ptr = (int *)kbuf;
191 LIST_FOREACH(p, &allproc, p_list) {
192 skip = 0;
193 switch (type) {
194 case PROC_PGRP_ONLY:
195 if (p->p_pgrpid != (pid_t)typeinfo)
196 skip = 1;
197 break;
198 case PROC_ALL_PIDS:
199 skip = 0;
200 break;
201 case PROC_TTY_ONLY:
202 /* racy but list lock is held */
203 if ((p->p_flag & P_CONTROLT) == 0 ||
204 (p->p_pgrp == NULL) || (p->p_pgrp->pg_session == NULL) ||
205 p->p_pgrp->pg_session->s_ttyp == NULL ||
206 p->p_pgrp->pg_session->s_ttyp->t_dev != (dev_t)typeinfo)
207 skip = 1;
208 break;
209 case PROC_UID_ONLY:
210 if (p->p_ucred == NULL)
211 skip = 1;
212 else {
213 kauth_cred_t my_cred;
214 uid_t uid;
215
216 my_cred = kauth_cred_proc_ref(p);
217 uid = kauth_cred_getuid(my_cred);
218 kauth_cred_unref(&my_cred);
219 if (uid != (uid_t)typeinfo)
220 skip = 1;
221 }
222 break;
223 case PROC_RUID_ONLY:
224 if (p->p_ucred == NULL)
225 skip = 1;
226 else {
227 kauth_cred_t my_cred;
228 uid_t uid;
229
230 my_cred = kauth_cred_proc_ref(p);
231 uid = my_cred->cr_ruid;
232 kauth_cred_unref(&my_cred);
233 if (uid != (uid_t)typeinfo)
234 skip = 1;
235 }
236 break;
237 default:
238 skip = 1;
239 break;
240 };
241
242 /* Do we have permission to look into this ? */
243 if (proc_security_policy(p) != 0) {
244 skip = 1;
245 }
246
247 if(skip == 0) {
248 *ptr++ = p->p_pid;
249 n++;
250 }
251 if (n >= numprocs)
252 break;
253 }
254
255 if (n < numprocs) {
256 LIST_FOREACH(p, &zombproc, p_list) {
257 *ptr++ = p->p_pid;
258 n++;
259 if (n >= numprocs)
260 break;
261 }
262 }
263
264
265 proc_list_unlock();
266
267 ptr = (int *)kbuf;
268 error = copyout((caddr_t)ptr, buffer, n * sizeof(int));
269 if (error == 0)
270 *retval = (n * sizeof(int));
271 kfree((void *)kbuf, (vm_size_t)(numprocs * sizeof(int)));
272
273 return(error);
274 }
275
276
277 /********************************** proc_pidinfo routines ********************************/
278
279 int
280 proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, register_t *retval)
281 {
282 int numfds, needfds;
283 char * kbuf;
284 struct proc_fdinfo * pfd;
285 struct fileproc * fp;
286 int n;
287 int count = 0;
288 int error = 0;
289
290 numfds = p->p_fd->fd_nfiles;
291
292 if (buffer == (user_addr_t) 0) {
293 numfds += 20;
294 *retval = (numfds * sizeof(struct proc_fdinfo));
295 return(0);
296 }
297
298 /* buffersize is big enough atleast for one struct */
299 needfds = buffersize/sizeof(struct proc_fdinfo);
300
301 if (numfds > needfds)
302 numfds = needfds;
303
304 kbuf = (char *)kalloc((vm_size_t)(numfds * sizeof(struct proc_fdinfo)));
305 if (kbuf == NULL)
306 return(ENOMEM);
307 bzero(kbuf, numfds * sizeof(struct proc_fdinfo));
308
309 proc_fdlock(p);
310
311 pfd = (struct proc_fdinfo *)kbuf;
312
313 for (n = 0; ((n < numfds) && (n < p->p_fd->fd_nfiles)); n++) {
314 if (((fp = p->p_fd->fd_ofiles[n]) != 0)
315 && ((p->p_fd->fd_ofileflags[n] & UF_RESERVED) == 0)) {
316 pfd->proc_fd = n;
317 pfd->proc_fdtype = fp->f_fglob->fg_type;
318 count++;
319 pfd++;
320 }
321 }
322 proc_fdunlock(p);
323
324 error = copyout(kbuf, buffer, count * sizeof(struct proc_fdinfo));
325 kfree((void *)kbuf, (vm_size_t)(numfds * sizeof(struct proc_fdinfo)));
326 if (error == 0)
327 *retval = (count * sizeof(struct proc_fdinfo));
328 return(error);
329 }
330
331
332 int
333 proc_pidbsdinfo(proc_t p, struct proc_bsdinfo * pbsd)
334 {
335 register struct tty *tp;
336 struct session *sessionp = NULL;
337 struct pgrp * pg;
338 kauth_cred_t my_cred;
339
340 pg = proc_pgrp(p);
341 sessionp = proc_session(p);
342
343 my_cred = kauth_cred_proc_ref(p);
344 bzero(pbsd, sizeof(struct proc_bsdinfo));
345 pbsd->pbi_status = p->p_stat;
346 pbsd->pbi_xstatus = p->p_xstat;
347 pbsd->pbi_pid = p->p_pid;
348 pbsd->pbi_ppid = p->p_ppid;
349 pbsd->pbi_uid = my_cred->cr_uid;
350 pbsd->pbi_gid = my_cred->cr_gid;
351 pbsd->pbi_ruid = my_cred->cr_ruid;
352 pbsd->pbi_rgid = my_cred->cr_rgid;
353 pbsd->pbi_svuid = my_cred->cr_svuid;
354 pbsd->pbi_svgid = my_cred->cr_svgid;
355 kauth_cred_unref(&my_cred);
356
357 pbsd->pbi_nice = p->p_nice;
358 pbsd->pbi_start = p->p_start;
359 bcopy(&p->p_comm, &pbsd->pbi_comm[0], MAXCOMLEN);
360 bcopy(&p->p_name, &pbsd->pbi_name[0], 2* MAXCOMLEN);
361
362 pbsd->pbi_flags = 0;
363 if ((p->p_flag & P_SYSTEM) == P_SYSTEM)
364 pbsd->pbi_flags |= PROC_FLAG_SYSTEM;
365 if ((p->p_lflag & P_LTRACED) == P_LTRACED)
366 pbsd->pbi_flags |= PROC_FLAG_TRACED;
367 if ((p->p_lflag & P_LEXIT) == P_LEXIT)
368 pbsd->pbi_flags |= PROC_FLAG_INEXIT;
369 if ((p->p_lflag & P_LPPWAIT) == P_LPPWAIT)
370 pbsd->pbi_flags |= PROC_FLAG_PPWAIT;
371 if ((p->p_flag & P_LP64) == P_LP64)
372 pbsd->pbi_flags |= PROC_FLAG_LP64;
373 if ((p->p_flag & P_CONTROLT) == P_CONTROLT)
374 pbsd->pbi_flags |= PROC_FLAG_CONTROLT;
375 if ((p->p_flag & P_THCWD) == P_THCWD)
376 pbsd->pbi_flags |= PROC_FLAG_THCWD;
377
378 if (SESS_LEADER(p, sessionp))
379 pbsd->pbi_flags |= PROC_FLAG_SLEADER;
380 if ((sessionp != SESSION_NULL) && sessionp->s_ttyvp)
381 pbsd->pbi_flags |= PROC_FLAG_CTTY;
382
383 pbsd->pbi_nfiles = p->p_fd->fd_nfiles;
384 if (pg != PGRP_NULL) {
385 pbsd->pbi_pgid = p->p_pgrpid;
386 pbsd->pbi_pjobc = pg->pg_jobc;
387 if ((p->p_flag & P_CONTROLT) && (sessionp != SESSION_NULL) && (tp = sessionp->s_ttyp)) {
388 pbsd->e_tdev = tp->t_dev;
389 pbsd->e_tpgid = sessionp->s_ttypgrpid;
390 }
391 }
392 if (sessionp != SESSION_NULL)
393 session_rele(sessionp);
394 if (pg != PGRP_NULL)
395 pg_rele(pg);
396
397 return(0);
398 }
399
400
401 int
402 proc_pidtaskinfo(proc_t p, struct proc_taskinfo * ptinfo)
403 {
404 task_t task;
405
406 task = p->task;
407
408 bzero(ptinfo, sizeof(struct proc_taskinfo));
409 fill_taskprocinfo(task, (struct proc_taskinfo_internal *)ptinfo);
410
411 return(0);
412 }
413
414
415
416 int
417 proc_pidthreadinfo(proc_t p, uint64_t arg, struct proc_threadinfo *pthinfo)
418 {
419 int error = 0;
420 uint64_t threadaddr = (uint64_t)arg;
421
422 bzero(pthinfo, sizeof(struct proc_threadinfo));
423
424 error = fill_taskthreadinfo(p->task, threadaddr, (struct proc_threadinfo_internal *)pthinfo, NULL, NULL);
425 if (error)
426 return(ESRCH);
427 else
428 return(0);
429
430 }
431
432
433 void
434 bsd_threadcdir(void * uth, void *vptr, int *vidp)
435 {
436 struct uthread * ut = (struct uthread *)uth;
437 vnode_t vp;
438 vnode_t *vpp = (vnode_t *)vptr;
439
440 vp = ut->uu_cdir;
441 if (vp != NULLVP) {
442 if (vpp != NULL) {
443 *vpp = vp;
444 if (vidp != NULL)
445 *vidp = vp->v_id;
446 }
447 }
448 }
449
450
451 int
452 proc_pidthreadpathinfo(proc_t p, uint64_t arg, struct proc_threadwithpathinfo *pinfo)
453 {
454 vnode_t vp = NULLVP;
455 int vid;
456 int error = 0;
457 uint64_t threadaddr = (uint64_t)arg;
458 int count;
459
460 bzero(pinfo, sizeof(struct proc_threadwithpathinfo));
461
462 error = fill_taskthreadinfo(p->task, threadaddr, (struct proc_threadinfo_internal *)&pinfo->pt, (void *)&vp, &vid);
463 if (error)
464 return(ESRCH);
465
466 if ((vp != NULLVP) && ((vnode_getwithvid(vp, vid)) == 0)) {
467 error = fill_vnodeinfo(vp, &pinfo->pvip.vip_vi) ;
468 if (error == 0) {
469 count = MAXPATHLEN;
470 vn_getpath(vp, &pinfo->pvip.vip_path[0], &count);
471 pinfo->pvip.vip_path[MAXPATHLEN-1] = 0;
472 }
473 vnode_put(vp);
474 }
475 return(error);
476 }
477
478
479
480 int
481 proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, register_t *retval)
482 {
483 int count = 0;
484 int ret = 0;
485 int error = 0;
486 void * kbuf;
487 int numthreads;
488
489
490 count = buffersize/(sizeof(uint64_t));
491 numthreads = get_numthreads(p->task);
492
493 numthreads += 10;
494
495 if (numthreads > count)
496 numthreads = count;
497
498 kbuf = (void *)kalloc(numthreads * sizeof(uint64_t));
499 if (kbuf == NULL)
500 return(ENOMEM);
501 bzero(kbuf, numthreads * sizeof(uint64_t));
502
503 ret = fill_taskthreadlist(p->task, kbuf, numthreads);
504
505 error = copyout(kbuf, buffer, ret);
506 kfree(kbuf, numthreads * sizeof(uint64_t));
507 if (error == 0)
508 *retval = ret;
509 return(error);
510
511 }
512
513
514 int
515 proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, register_t *retval)
516 {
517 struct proc_regioninfo preginfo;
518 int ret, error = 0;
519
520 bzero(&preginfo, sizeof(struct proc_regioninfo));
521 ret = fill_procregioninfo( p->task, arg, (struct proc_regioninfo_internal *)&preginfo, (uint32_t *)0, (uint32_t *)0);
522 if (ret == 0)
523 return(EINVAL);
524 error = copyout(&preginfo, buffer, sizeof(struct proc_regioninfo));
525 if (error == 0)
526 *retval = sizeof(struct proc_regioninfo);
527 return(error);
528 }
529
530
531 int
532 proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, register_t *retval)
533 {
534 struct proc_regionwithpathinfo preginfo;
535 int ret, error = 0;
536 uint32_t vnodeaddr= 0;
537 uint32_t vnodeid= 0;
538 vnode_t vp;
539 int count;
540
541 bzero(&preginfo, sizeof(struct proc_regionwithpathinfo));
542
543 ret = fill_procregioninfo( p->task, arg, (struct proc_regioninfo_internal *)&preginfo.prp_prinfo, (uint32_t *)&vnodeaddr, (uint32_t *)&vnodeid);
544 if (ret == 0)
545 return(EINVAL);
546 if (vnodeaddr) {
547 vp = (vnode_t)vnodeaddr;
548 if ((vnode_getwithvid(vp, vnodeid)) == 0) {
549 /* FILL THE VNODEINFO */
550 error = fill_vnodeinfo(vp, &preginfo.prp_vip.vip_vi);
551 count = MAXPATHLEN;
552 vn_getpath(vp, &preginfo.prp_vip.vip_path[0], &count);
553 /* Always make sure it is null terminated */
554 preginfo.prp_vip.vip_path[MAXPATHLEN-1] = 0;
555 vnode_put(vp);
556 }
557 }
558 error = copyout(&preginfo, buffer, sizeof(struct proc_regionwithpathinfo));
559 if (error == 0)
560 *retval = sizeof(struct proc_regionwithpathinfo);
561 return(error);
562 }
563
564 /*
565 * Path is relative to current process directory; may different from current
566 * thread directory.
567 */
568 int
569 proc_pidvnodepathinfo(proc_t p, __unused uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, register_t *retval)
570 {
571 struct proc_vnodepathinfo pvninfo;
572 int error = 0;
573 vnode_t vncdirvp = NULLVP;
574 uint32_t vncdirid=0;
575 vnode_t vnrdirvp = NULLVP;
576 uint32_t vnrdirid=0;
577 int count;
578
579 bzero(&pvninfo, sizeof(struct proc_vnodepathinfo));
580
581 proc_fdlock(p);
582 if (p->p_fd->fd_cdir) {
583 vncdirvp = p->p_fd->fd_cdir;
584 vncdirid = p->p_fd->fd_cdir->v_id;
585 }
586 if (p->p_fd->fd_rdir) {
587 vnrdirvp = p->p_fd->fd_rdir;
588 vnrdirid = p->p_fd->fd_rdir->v_id;
589 }
590 proc_fdunlock(p);
591
592 if (vncdirvp != NULLVP) {
593 if ((error = vnode_getwithvid(vncdirvp, vncdirid)) == 0) {
594 /* FILL THE VNODEINFO */
595 error = fill_vnodeinfo(vncdirvp, &pvninfo.pvi_cdir.vip_vi);
596 if ( error == 0) {
597 count = MAXPATHLEN;
598 vn_getpath(vncdirvp, &pvninfo.pvi_cdir.vip_path[0], &count);
599 pvninfo.pvi_cdir.vip_path[MAXPATHLEN-1] = 0;
600 }
601 vnode_put(vncdirvp);
602 } else {
603 goto out;
604 }
605 }
606
607 if ((error == 0) && (vnrdirvp != NULLVP)) {
608 if ((error = vnode_getwithvid(vnrdirvp, vnrdirid)) == 0) {
609 /* FILL THE VNODEINFO */
610 error = fill_vnodeinfo(vnrdirvp, &pvninfo.pvi_rdir.vip_vi);
611 if ( error == 0) {
612 count = MAXPATHLEN;
613 vn_getpath(vnrdirvp, &pvninfo.pvi_rdir.vip_path[0], &count);
614 pvninfo.pvi_rdir.vip_path[MAXPATHLEN-1] = 0;
615 }
616 vnode_put(vnrdirvp);
617 } else {
618 goto out;
619 }
620 }
621 if (error == 0) {
622 error = copyout(&pvninfo, buffer, sizeof(struct proc_vnodepathinfo));
623 if (error == 0)
624 *retval = sizeof(struct proc_vnodepathinfo);
625 }
626 out:
627 return(error);
628 }
629
630 int
631 proc_pidpathinfo(proc_t p, __unused uint64_t arg, user_addr_t buffer, uint32_t buffersize, __unused register_t *retval)
632 {
633 int vid, error;
634 vnode_t tvp;
635 vnode_t nvp = NULLVP;
636 int len = buffersize;
637 char * buf;
638
639 tvp = p->p_textvp;
640
641 if (tvp == NULLVP)
642 return(ESRCH);
643
644 buf = (char *)kalloc(buffersize);
645 if (buf == NULL)
646 return(ENOMEM);
647
648
649 vid = vnode_vid(tvp);
650 error = vnode_getwithvid(tvp, vid);
651 if (error == 0) {
652 error = vn_getpath(tvp, buf, &len);
653 vnode_put(tvp);
654 if (error == 0) {
655 error = vnode_lookup(buf, 0, &nvp, vfs_context_current());
656 if ((error == 0) && ( nvp != NULLVP))
657 vnode_put(nvp);
658 if (error == 0) {
659 error = copyout(buf, buffer, len);
660 }
661 }
662 }
663 kfree(buf, buffersize);
664 return(error);
665 }
666
667
668 /********************************** proc_pidinfo ********************************/
669
670
671 int
672 proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t * retval)
673 {
674 struct proc * p = PROC_NULL;
675 int error = ENOTSUP;
676 int gotref = 0;
677 int findzomb = 0;
678 int refheld = 0;
679 uint32_t size;
680
681 switch (flavor) {
682 case PROC_PIDLISTFDS:
683 size = PROC_PIDLISTFD_SIZE;
684 if (buffer == (user_addr_t)0)
685 size = 0;
686 break;
687 case PROC_PIDTBSDINFO:
688 size = PROC_PIDTBSDINFO_SIZE;
689 break;
690 case PROC_PIDTASKINFO:
691 size = PROC_PIDTASKINFO_SIZE;
692 break;
693 case PROC_PIDTASKALLINFO:
694 size = PROC_PIDTASKALLINFO_SIZE;
695 break;
696 case PROC_PIDTHREADINFO:
697 size = PROC_PIDTHREADINFO_SIZE;
698 break;
699 case PROC_PIDLISTTHREADS:
700 size = PROC_PIDLISTTHREADS_SIZE;
701 break;
702 case PROC_PIDREGIONINFO:
703 size = PROC_PIDREGIONINFO_SIZE;
704 break;
705 case PROC_PIDREGIONPATHINFO:
706 size = PROC_PIDREGIONPATHINFO_SIZE;
707 break;
708 case PROC_PIDVNODEPATHINFO:
709 size = PROC_PIDVNODEPATHINFO_SIZE;
710 break;
711 case PROC_PIDTHREADPATHINFO:
712 size = PROC_PIDTHREADPATHINFO_SIZE;
713 break;
714 case PROC_PIDPATHINFO:
715 size = MAXPATHLEN;
716 break;
717 default:
718 return(EINVAL);
719 }
720
721 if (buffersize < size)
722 return(ENOMEM);
723
724 if ((flavor == PROC_PIDPATHINFO) && (buffersize > PROC_PIDPATHINFO_MAXSIZE)) {
725 return(EOVERFLOW);
726 }
727
728 if ((flavor != PROC_PIDTBSDINFO) && (flavor != PROC_PIDPATHINFO)) {
729 if ((p = proc_find(pid)) == PROC_NULL) {
730 error = ESRCH;
731 goto out;
732 } else {
733 gotref = 1;
734
735 /* Do we have permission to look into this ? */
736 if ((error = proc_security_policy(p)) != 0) {
737 goto out;
738 }
739 }
740 }
741 switch (flavor) {
742 case PROC_PIDLISTFDS: {
743 error = proc_pidfdlist(p, buffer, buffersize, retval);
744 }
745 break;
746
747 case PROC_PIDTBSDINFO: {
748 struct proc_bsdinfo pbsd;
749
750 if (arg)
751 findzomb = 1;
752 p = proc_find(pid);
753 if (p == PROC_NULL) {
754 if (findzomb)
755 p = pzfind(pid);
756 if (p == NULL) {
757 error = ESRCH;
758 goto out;
759 }
760 } else
761 refheld = 1;
762 /* Do we have permission to look into this ? */
763 if ((error = proc_security_policy(p)) != 0) {
764 if (refheld != 0)
765 proc_rele(p);
766 goto out;
767 }
768 error = proc_pidbsdinfo(p, &pbsd);
769 if (refheld != 0)
770 proc_rele(p);
771 if (error == 0) {
772 error = copyout(&pbsd, buffer, sizeof(struct proc_bsdinfo));
773 if (error == 0)
774 *retval = sizeof(struct proc_bsdinfo);
775 }
776 }
777 break;
778
779 case PROC_PIDTASKINFO: {
780 struct proc_taskinfo ptinfo;
781
782 error = proc_pidtaskinfo(p, &ptinfo);
783 if (error == 0) {
784 error = copyout(&ptinfo, buffer, sizeof(struct proc_taskinfo));
785 if (error == 0)
786 *retval = sizeof(struct proc_taskinfo);
787 }
788 }
789 break;
790
791 case PROC_PIDTASKALLINFO: {
792 struct proc_taskallinfo pall;
793
794 error = proc_pidbsdinfo(p, &pall.pbsd);
795 error = proc_pidtaskinfo(p, &pall.ptinfo);
796 if (error == 0) {
797 error = copyout(&pall, buffer, sizeof(struct proc_taskallinfo));
798 if (error == 0)
799 *retval = sizeof(struct proc_taskallinfo);
800 }
801 }
802 break;
803
804 case PROC_PIDTHREADINFO:{
805 struct proc_threadinfo pthinfo;
806
807 error = proc_pidthreadinfo(p, arg, &pthinfo);
808 if (error == 0) {
809 error = copyout(&pthinfo, buffer, sizeof(struct proc_threadinfo));
810 if (error == 0)
811 *retval = sizeof(struct proc_threadinfo);
812 }
813 }
814 break;
815
816 case PROC_PIDLISTTHREADS:{
817 error = proc_pidlistthreads(p, buffer, buffersize, retval);
818 }
819 break;
820
821 case PROC_PIDREGIONINFO:{
822 error = proc_pidregioninfo(p, arg, buffer, buffersize, retval);
823 }
824 break;
825
826
827 case PROC_PIDREGIONPATHINFO:{
828 error = proc_pidregionpathinfo(p, arg, buffer, buffersize, retval);
829 }
830 break;
831
832 case PROC_PIDVNODEPATHINFO:{
833 error = proc_pidvnodepathinfo(p, arg, buffer, buffersize, retval);
834 }
835 break;
836
837
838 case PROC_PIDTHREADPATHINFO:{
839 struct proc_threadwithpathinfo pinfo;
840
841 error = proc_pidthreadpathinfo(p, arg, &pinfo);
842 if (error == 0) {
843 error = copyout((caddr_t)&pinfo, buffer, sizeof(struct proc_threadwithpathinfo));
844 if (error == 0)
845 *retval = sizeof(struct proc_threadwithpathinfo);
846 }
847 }
848 break;
849
850 case PROC_PIDPATHINFO: {
851 p = proc_find(pid);
852 if (p == PROC_NULL) {
853 error = ESRCH;
854 goto out;
855 }
856 gotref = 1;
857 error = proc_pidpathinfo(p, arg, buffer, buffersize, retval);
858 }
859 break;
860
861 default:
862 error = ENOTSUP;
863 }
864
865 out:
866 if (gotref)
867 proc_rele(p);
868 return(error);
869 }
870
871
872 int
873 pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, register_t * retval)
874 {
875 struct vnode_fdinfo vfi;
876 int error= 0;
877
878 if ((error = vnode_getwithvid(vp, vid)) != 0) {
879 return(error);
880 }
881 bzero(&vfi, sizeof(struct vnode_fdinfo));
882 fill_fileinfo(fp, closeonexec, &vfi.pfi);
883 error = fill_vnodeinfo(vp, &vfi.pvi);
884 vnode_put(vp);
885 if (error == 0) {
886 error = copyout((caddr_t)&vfi, buffer, sizeof(struct vnode_fdinfo));
887 if (error == 0)
888 *retval = sizeof(struct vnode_fdinfo);
889 }
890 return(error);
891 }
892
893 int
894 pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, register_t * retval)
895 {
896 struct vnode_fdinfowithpath vfip;
897 int count, error= 0;
898
899 if ((error = vnode_getwithvid(vp, vid)) != 0) {
900 return(error);
901 }
902 bzero(&vfip, sizeof(struct vnode_fdinfowithpath));
903 fill_fileinfo(fp, closeonexec, &vfip.pfi);
904 error = fill_vnodeinfo(vp, &vfip.pvip.vip_vi) ;
905 if (error == 0) {
906 count = MAXPATHLEN;
907 vn_getpath(vp, &vfip.pvip.vip_path[0], &count);
908 vfip.pvip.vip_path[MAXPATHLEN-1] = 0;
909 vnode_put(vp);
910 error = copyout((caddr_t)&vfip, buffer, sizeof(struct vnode_fdinfowithpath));
911 if (error == 0)
912 *retval = sizeof(struct vnode_fdinfowithpath);
913 } else
914 vnode_put(vp);
915 return(error);
916 }
917
918 void
919 fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * fproc)
920 {
921 fproc->fi_openflags = fp->f_fglob->fg_flag;
922 fproc->fi_status = 0;
923 fproc->fi_offset = fp->f_fglob->fg_offset;
924 fproc->fi_type = fp->f_fglob->fg_type;
925 if (fp->f_fglob->fg_count)
926 fproc->fi_status |= PROC_FP_SHARED;
927 if (closeonexec != 0)
928 fproc->fi_status |= PROC_FP_CLEXEC;
929 }
930
931
932
933 int
934 fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo)
935 {
936 vfs_context_t context;
937 struct stat64 sb;
938 int error = 0;
939
940 context = vfs_context_create((vfs_context_t)0);
941 error = vn_stat(vp, &sb, NULL, 1, context);
942 (void)vfs_context_rele(context);
943
944 munge_vinfo_stat(&sb, &vinfo->vi_stat);
945
946 if (error != 0)
947 goto out;
948
949 if (vp->v_mount != dead_mountp) {
950 vinfo->vi_fsid = vp->v_mount->mnt_vfsstat.f_fsid;
951 } else {
952 vinfo->vi_fsid.val[0] = 0;
953 vinfo->vi_fsid.val[1] = 0;
954 }
955 vinfo->vi_type = vp->v_type;
956 out:
957 return(error);
958 }
959
960 int
961 pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, register_t * retval)
962 {
963 #if SOCKETS
964 struct socket_fdinfo s;
965 int error = 0;
966
967 bzero(&s, sizeof(struct socket_fdinfo));
968 fill_fileinfo(fp, closeonexec, &s.pfi);
969 if ((error = fill_socketinfo(so, &s.psi)) == 0) {
970 if ((error = copyout(&s, buffer, sizeof(struct socket_fdinfo))) == 0)
971 *retval = sizeof(struct socket_fdinfo);
972 }
973 return (error);
974 #else
975 *retval = 0;
976 return (ENOTSUP);
977 #endif
978 }
979
980 int
981 pid_pseminfo(struct psemnode *psem, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, register_t * retval)
982 {
983 struct psem_fdinfo pseminfo;
984 int error = 0;
985
986 bzero(&pseminfo, sizeof(struct psem_fdinfo));
987 fill_fileinfo(fp, closeonexec, &pseminfo.pfi);
988
989 if ((error = fill_pseminfo(psem, &pseminfo.pseminfo)) == 0) {
990 if ((error = copyout(&pseminfo, buffer, sizeof(struct psem_fdinfo))) == 0)
991 *retval = sizeof(struct psem_fdinfo);
992 }
993
994 return(error);
995 }
996
997 int
998 pid_pshminfo(struct pshmnode *pshm, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, register_t * retval)
999 {
1000 struct pshm_fdinfo pshminfo;
1001 int error = 0;
1002
1003 bzero(&pshminfo, sizeof(struct pshm_fdinfo));
1004 fill_fileinfo(fp, closeonexec, &pshminfo.pfi);
1005
1006 if ((error = fill_pshminfo(pshm, &pshminfo.pshminfo)) == 0) {
1007 if ((error = copyout(&pshminfo, buffer, sizeof(struct pshm_fdinfo))) == 0)
1008 *retval = sizeof(struct pshm_fdinfo);
1009 }
1010
1011 return(error);
1012 }
1013
1014 int
1015 pid_pipeinfo(struct pipe * p, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, register_t * retval)
1016 {
1017 struct pipe_fdinfo pipeinfo;
1018 int error = 0;
1019
1020 bzero(&pipeinfo, sizeof(struct pipe_fdinfo));
1021 fill_fileinfo(fp, closeonexec, &pipeinfo.pfi);
1022 if ((error = fill_pipeinfo(p, &pipeinfo.pipeinfo)) == 0) {
1023 if ((error = copyout(&pipeinfo, buffer, sizeof(struct pipe_fdinfo))) == 0)
1024 *retval = sizeof(struct pipe_fdinfo);
1025 }
1026
1027 return(error);
1028 }
1029
1030 int
1031 pid_kqueueinfo(struct kqueue * kq, struct fileproc *fp, int closeonexec, user_addr_t buffer, __unused uint32_t buffersize, register_t * retval)
1032 {
1033 struct kqueue_fdinfo kqinfo;
1034 int error = 0;
1035
1036 bzero(&kqinfo, sizeof(struct kqueue_fdinfo));
1037
1038 fill_fileinfo(fp, closeonexec, &kqinfo.pfi);
1039
1040 if ((error = fill_kqueueinfo(kq, &kqinfo.kqueueinfo)) == 0) {
1041 if ((error = copyout(&kqinfo, buffer, sizeof(struct kqueue_fdinfo))) == 0)
1042 *retval = sizeof(struct kqueue_fdinfo);
1043 }
1044
1045 return(error);
1046 }
1047
1048 int
1049 pid_atalkinfo(__unused struct atalk * at, __unused struct fileproc *fp, __unused int closeonexec, __unused user_addr_t buffer, __unused uint32_t buffersize, __unused register_t * retval)
1050 {
1051 return ENOTSUP;
1052 }
1053
1054
1055
1056 /************************** proc_pidfdinfo routine ***************************/
1057 int
1058 proc_pidfdinfo(int pid, int flavor, int fd, user_addr_t buffer, uint32_t buffersize, register_t * retval)
1059 {
1060 proc_t p;
1061 int error = ENOTSUP;
1062 struct fileproc * fp;
1063 uint32_t size;
1064 int closeonexec = 0;
1065
1066 switch (flavor) {
1067 case PROC_PIDFDVNODEINFO:
1068 size = PROC_PIDFDVNODEINFO_SIZE;
1069 break;
1070 case PROC_PIDFDVNODEPATHINFO:
1071 size = PROC_PIDFDVNODEPATHINFO_SIZE;
1072 break;
1073 case PROC_PIDFDSOCKETINFO:
1074 size = PROC_PIDFDSOCKETINFO_SIZE;
1075 break;
1076 case PROC_PIDFDPSEMINFO:
1077 size = PROC_PIDFDPSEMINFO_SIZE;
1078 break;
1079 case PROC_PIDFDPSHMINFO:
1080 size = PROC_PIDFDPSHMINFO_SIZE;
1081 break;
1082 case PROC_PIDFDPIPEINFO:
1083 size = PROC_PIDFDPIPEINFO_SIZE;
1084 break;
1085 case PROC_PIDFDKQUEUEINFO:
1086 size = PROC_PIDFDKQUEUEINFO_SIZE;
1087 break;
1088 case PROC_PIDFDATALKINFO:
1089 size = PROC_PIDFDATALKINFO_SIZE;
1090 break;
1091
1092 default:
1093 return(EINVAL);
1094
1095 }
1096
1097 if (buffersize < size)
1098 return(ENOMEM);
1099
1100 if ((p = proc_find(pid)) == PROC_NULL) {
1101 error = ESRCH;
1102 goto out;
1103 }
1104 /* Do we have permission to look into this ? */
1105 if ((error = proc_security_policy(p)) != 0) {
1106 goto out1;
1107 }
1108
1109 switch (flavor) {
1110 case PROC_PIDFDVNODEINFO: {
1111 vnode_t vp;
1112 uint32_t vid=0;
1113
1114 if ((error = fp_getfvpandvid(p, fd, &fp, &vp, &vid)) !=0) {
1115 goto out1;
1116 }
1117 /* no need to be under the fdlock */
1118 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1119 error = pid_vnodeinfo(vp, vid, fp, closeonexec, buffer, buffersize, retval);
1120 }
1121 break;
1122
1123 case PROC_PIDFDVNODEPATHINFO: {
1124 vnode_t vp;
1125 uint32_t vid=0;
1126
1127 if ((error = fp_getfvpandvid(p, fd, &fp, &vp, &vid)) !=0) {
1128 goto out1;
1129 }
1130
1131 /* no need to be under the fdlock */
1132 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1133 error = pid_vnodeinfopath(vp, vid, fp, closeonexec, buffer, buffersize, retval);
1134 }
1135 break;
1136
1137 case PROC_PIDFDSOCKETINFO: {
1138 socket_t so;
1139
1140 if ((error = fp_getfsock(p, fd, &fp, &so)) !=0) {
1141 goto out1;
1142 }
1143 /* no need to be under the fdlock */
1144 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1145 error = pid_socketinfo(so, fp, closeonexec, buffer, buffersize, retval);
1146 }
1147 break;
1148
1149 case PROC_PIDFDPSEMINFO: {
1150 struct psemnode * psem;
1151
1152 if ((error = fp_getfpsem(p, fd, &fp, &psem)) !=0) {
1153 goto out1;
1154 }
1155 /* no need to be under the fdlock */
1156 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1157 error = pid_pseminfo(psem, fp, closeonexec, buffer, buffersize, retval);
1158 }
1159 break;
1160
1161 case PROC_PIDFDPSHMINFO: {
1162 struct pshmnode * pshm;
1163
1164 if ((error = fp_getfpshm(p, fd, &fp, &pshm)) !=0) {
1165 goto out1;
1166 }
1167 /* no need to be under the fdlock */
1168 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1169 error = pid_pshminfo(pshm, fp, closeonexec, buffer, buffersize, retval);
1170 }
1171 break;
1172
1173 case PROC_PIDFDPIPEINFO: {
1174 struct pipe * cpipe;
1175
1176 if ((error = fp_getfpipe(p, fd, &fp, &cpipe)) !=0) {
1177 goto out1;
1178 }
1179 /* no need to be under the fdlock */
1180 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1181 error = pid_pipeinfo(cpipe, fp, closeonexec, buffer, buffersize, retval);
1182 }
1183 break;
1184
1185 case PROC_PIDFDKQUEUEINFO: {
1186 struct kqueue * kq;
1187
1188 if ((error = fp_getfkq(p, fd, &fp, &kq)) !=0) {
1189 goto out1;
1190 }
1191 /* no need to be under the fdlock */
1192 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1193 error = pid_kqueueinfo(kq, fp, closeonexec, buffer, buffersize, retval);
1194 }
1195 break;
1196
1197 case PROC_PIDFDATALKINFO: {
1198 struct atalk * at;
1199
1200 if ((error = fp_getfatalk(p, fd, &fp, &at)) !=0) {
1201 goto out1;
1202 }
1203
1204 /* no need to be under the fdlock */
1205 closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
1206 error = pid_atalkinfo(at, fp, closeonexec, buffer, buffersize, retval);
1207 }
1208 break;
1209
1210 default: {
1211 error = EINVAL;
1212 }
1213 break;
1214
1215 }
1216
1217 fp_drop(p, fd, fp , 0);
1218 out1 :
1219 proc_rele(p);
1220 out:
1221 return(error);
1222 }
1223
1224
1225 static int
1226 proc_security_policy(proc_t p)
1227 {
1228 kauth_cred_t my_cred;
1229 uid_t uid;
1230
1231 my_cred = kauth_cred_proc_ref(p);
1232 uid = kauth_cred_getuid(my_cred) ;
1233 kauth_cred_unref(&my_cred);
1234
1235 if ((uid != kauth_cred_getuid(kauth_cred_get()))
1236 && suser(kauth_cred_get(), (u_short *)0)) {
1237 return(EPERM);
1238 }
1239
1240 return(0);
1241 }
1242
1243 int
1244 proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, register_t * retval)
1245 {
1246 if (suser(kauth_cred_get(), (u_short *)0) == 0) {
1247 return(log_dmesg(buffer, buffersize, retval));
1248 } else
1249 return(EPERM);
1250 }
1251
1252 /*
1253 * copy stat64 structure into vinfo_stat structure.
1254 */
1255 static void
1256 munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp)
1257 {
1258 bzero(vsbp, sizeof(struct vinfo_stat));
1259
1260 vsbp->vst_dev = sbp->st_dev;
1261 vsbp->vst_mode = sbp->st_mode;
1262 vsbp->vst_nlink = sbp->st_nlink;
1263 vsbp->vst_ino = sbp->st_ino;
1264 vsbp->vst_uid = sbp->st_uid;
1265 vsbp->vst_gid = sbp->st_gid;
1266 vsbp->vst_atime = sbp->st_atimespec.tv_sec;
1267 vsbp->vst_atimensec = sbp->st_atimespec.tv_nsec;
1268 vsbp->vst_mtime = sbp->st_mtimespec.tv_sec;
1269 vsbp->vst_mtimensec = sbp->st_mtimespec.tv_nsec;
1270 vsbp->vst_ctime = sbp->st_ctimespec.tv_sec;
1271 vsbp->vst_ctimensec = sbp->st_ctimespec.tv_nsec;
1272 vsbp->vst_birthtime = sbp->st_birthtimespec.tv_sec;
1273 vsbp->vst_birthtimensec = sbp->st_birthtimespec.tv_nsec;
1274 vsbp->vst_size = sbp->st_size;
1275 vsbp->vst_blocks = sbp->st_blocks;
1276 vsbp->vst_blksize = sbp->st_blksize;
1277 vsbp->vst_flags = sbp->st_flags;
1278 vsbp->vst_gen = sbp->st_gen;
1279 vsbp->vst_rdev = sbp->st_rdev;
1280 vsbp->vst_qspare[0] = sbp->st_qspare[0];
1281 vsbp->vst_qspare[1] = sbp->st_qspare[1];
1282 }