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