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