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 80struct pshmnode; 81struct psemnode; 82struct pipe; 83struct kqueue; 84struct atalk; 85 86int 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 */ 89int proc_listpids(uint32_t type, uint32_t tyoneinfo, user_addr_t buffer, uint32_t buffersize, register_t * retval); 90int proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t * retval); 91int proc_pidfdinfo(int pid, int flavor,int fd, user_addr_t buffer, uint32_t buffersize, register_t * retval); 92int proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, register_t * retval); 93 94/* protos for procpidinfo calls */ 95int proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, register_t *retval); 96int proc_pidbsdinfo(proc_t p, struct proc_bsdinfo *pbsd); 97int proc_pidtaskinfo(proc_t p, struct proc_taskinfo *ptinfo); 98int proc_pidallinfo(proc_t p, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t *retval); 99int proc_pidthreadinfo(proc_t p, uint64_t arg, struct proc_threadinfo *pthinfo); 100int proc_pidthreadpathinfo(proc_t p, uint64_t arg, struct proc_threadwithpathinfo *pinfo); 101int proc_pidlistthreads(proc_t p, user_addr_t buffer, uint32_t buffersize, register_t *retval); 102int proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t *retval); 103int proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t *retval); 104int proc_pidvnodepathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, register_t *retval); 105int 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 */ 109int pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval); 110int pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval); 111int pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval); 112int pid_pseminfo(struct psemnode * psem, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval); 113int pid_pshminfo(struct pshmnode * pshm, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval); 114int pid_pipeinfo(struct pipe * p, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval); 115int pid_kqueueinfo(struct kqueue * kq, struct fileproc * fp, int closeonexec, user_addr_t buffer, uint32_t buffersize, register_t * retval); 116int 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 121int fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo); 122void fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * finfo); 123static int proc_security_policy(proc_t p); 124static void munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp); 125 126/***************************** proc_info ********************/ 127 128int 129proc_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 135int 136proc_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 ****************/ 157int 158proc_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 279int 280proc_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 332int 333proc_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 401int 402proc_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 416int 417proc_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 433void 434bsd_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 451int 452proc_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 480int 481proc_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 514int 515proc_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 531int 532proc_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 */ 568int 569proc_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 } 626out: 627 return(error); 628} 629 630int 631proc_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 671int 672proc_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 865out: 866 if (gotref) 867 proc_rele(p); 868 return(error); 869} 870 871 872int 873pid_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 893int 894pid_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 918void 919fill_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 933int 934fill_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; 956out: 957 return(error); 958} 959 960int 961pid_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 980int 981pid_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 997int 998pid_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 1014int 1015pid_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 1030int 1031pid_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 1048int 1049pid_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 ***************************/ 1057int 1058proc_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); 1218out1 : 1219 proc_rele(p); 1220out: 1221 return(error); 1222} 1223 1224 1225static int 1226proc_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 1243int 1244proc_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 */ 1255static void 1256munge_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} 1283