1179185Sjb/*- 2210688Srpaulo * Copyright (c) 2010 The FreeBSD Foundation 3179185Sjb * Copyright (c) 2008 John Birrell (jb@freebsd.org) 4179185Sjb * All rights reserved. 5316713Smarkj * 6210688Srpaulo * Portions of this software were developed by Rui Paulo under sponsorship 7210688Srpaulo * from the FreeBSD Foundation. 8179185Sjb * 9179185Sjb * Redistribution and use in source and binary forms, with or without 10179185Sjb * modification, are permitted provided that the following conditions 11179185Sjb * are met: 12179185Sjb * 1. Redistributions of source code must retain the above copyright 13179185Sjb * notice, this list of conditions and the following disclaimer. 14179185Sjb * 2. Redistributions in binary form must reproduce the above copyright 15179185Sjb * notice, this list of conditions and the following disclaimer in the 16179185Sjb * documentation and/or other materials provided with the distribution. 17179185Sjb * 18179185Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19179185Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20179185Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21179185Sjb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22179185Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23179185Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24179185Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25179185Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26179185Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27179185Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28179185Sjb * SUCH DAMAGE. 29179185Sjb */ 30179185Sjb 31316713Smarkj#include <sys/cdefs.h> 32316713Smarkj__FBSDID("$FreeBSD: stable/11/lib/libproc/proc_util.c 316713 2017-04-11 17:36:19Z markj $"); 33316713Smarkj 34210688Srpaulo#include <sys/types.h> 35210688Srpaulo#include <sys/ptrace.h> 36210688Srpaulo#include <sys/wait.h> 37316713Smarkj 38210688Srpaulo#include <err.h> 39179185Sjb#include <errno.h> 40210688Srpaulo#include <signal.h> 41210688Srpaulo#include <string.h> 42265308Smarkj#include <unistd.h> 43316713Smarkj 44210688Srpaulo#include "_libproc.h" 45179185Sjb 46179185Sjbint 47179185Sjbproc_clearflags(struct proc_handle *phdl, int mask) 48179185Sjb{ 49210688Srpaulo 50179185Sjb if (phdl == NULL) 51179185Sjb return (EINVAL); 52179185Sjb 53179185Sjb phdl->flags &= ~mask; 54179185Sjb 55179185Sjb return (0); 56179185Sjb} 57179185Sjb 58210688Srpaulo/* 59210688Srpaulo * NB: we return -1 as the Solaris libproc Psetrun() function. 60210688Srpaulo */ 61179185Sjbint 62179185Sjbproc_continue(struct proc_handle *phdl) 63179185Sjb{ 64316713Smarkj int pending; 65210688Srpaulo 66179185Sjb if (phdl == NULL) 67210688Srpaulo return (-1); 68179185Sjb 69265308Smarkj if (phdl->status == PS_STOP && WSTOPSIG(phdl->wstat) != SIGTRAP) 70265308Smarkj pending = WSTOPSIG(phdl->wstat); 71316713Smarkj else 72316713Smarkj pending = 0; 73265308Smarkj if (ptrace(PT_CONTINUE, phdl->pid, (caddr_t)(uintptr_t)1, pending) != 0) 74210688Srpaulo return (-1); 75179185Sjb 76179185Sjb phdl->status = PS_RUN; 77179185Sjb 78179185Sjb return (0); 79179185Sjb} 80179185Sjb 81179185Sjbint 82210688Srpauloproc_detach(struct proc_handle *phdl, int reason) 83179185Sjb{ 84210688Srpaulo int status; 85210688Srpaulo 86179185Sjb if (phdl == NULL) 87179185Sjb return (EINVAL); 88210688Srpaulo if (reason == PRELEASE_KILL) { 89210688Srpaulo kill(phdl->pid, SIGKILL); 90210688Srpaulo return (0); 91210688Srpaulo } 92210688Srpaulo if (ptrace(PT_DETACH, phdl->pid, 0, 0) != 0 && errno == ESRCH) 93210688Srpaulo return (0); 94210688Srpaulo if (errno == EBUSY) { 95210688Srpaulo kill(phdl->pid, SIGSTOP); 96210688Srpaulo waitpid(phdl->pid, &status, WUNTRACED); 97210688Srpaulo ptrace(PT_DETACH, phdl->pid, 0, 0); 98210688Srpaulo kill(phdl->pid, SIGCONT); 99210688Srpaulo return (0); 100210688Srpaulo } 101179185Sjb 102179185Sjb return (0); 103179185Sjb} 104179185Sjb 105179185Sjbint 106179185Sjbproc_getflags(struct proc_handle *phdl) 107179185Sjb{ 108210688Srpaulo 109179185Sjb if (phdl == NULL) 110179185Sjb return (-1); 111179185Sjb 112316713Smarkj return (phdl->flags); 113179185Sjb} 114179185Sjb 115179185Sjbint 116179185Sjbproc_setflags(struct proc_handle *phdl, int mask) 117179185Sjb{ 118210688Srpaulo 119179185Sjb if (phdl == NULL) 120179185Sjb return (EINVAL); 121179185Sjb 122179185Sjb phdl->flags |= mask; 123179185Sjb 124179185Sjb return (0); 125179185Sjb} 126179185Sjb 127179185Sjbint 128179185Sjbproc_state(struct proc_handle *phdl) 129179185Sjb{ 130210688Srpaulo 131179185Sjb if (phdl == NULL) 132179185Sjb return (-1); 133179185Sjb 134179185Sjb return (phdl->status); 135179185Sjb} 136179185Sjb 137210688Srpaulopid_t 138210688Srpauloproc_getpid(struct proc_handle *phdl) 139179185Sjb{ 140179185Sjb 141179185Sjb if (phdl == NULL) 142210688Srpaulo return (-1); 143179185Sjb 144210688Srpaulo return (phdl->pid); 145210688Srpaulo} 146179185Sjb 147210688Srpauloint 148210688Srpauloproc_wstatus(struct proc_handle *phdl) 149210688Srpaulo{ 150210688Srpaulo int status; 151210688Srpaulo 152210688Srpaulo if (phdl == NULL) 153210688Srpaulo return (-1); 154211184Srpaulo if (waitpid(phdl->pid, &status, WUNTRACED) < 0) { 155257298Smarkj if (errno != EINTR) 156257222Smarkj DPRINTF("waitpid"); 157210688Srpaulo return (-1); 158211184Srpaulo } 159210688Srpaulo if (WIFSTOPPED(status)) 160210688Srpaulo phdl->status = PS_STOP; 161210688Srpaulo if (WIFEXITED(status) || WIFSIGNALED(status)) 162179185Sjb phdl->status = PS_UNDEAD; 163210688Srpaulo phdl->wstat = status; 164179185Sjb 165211184Srpaulo return (phdl->status); 166179185Sjb} 167179185Sjb 168210688Srpauloint 169210688Srpauloproc_getwstat(struct proc_handle *phdl) 170179185Sjb{ 171210688Srpaulo 172179185Sjb if (phdl == NULL) 173179185Sjb return (-1); 174179185Sjb 175210688Srpaulo return (phdl->wstat); 176179185Sjb} 177210688Srpaulo 178210688Srpaulochar * 179210688Srpauloproc_signame(int sig, char *name, size_t namesz) 180210688Srpaulo{ 181210688Srpaulo 182210688Srpaulo strlcpy(name, strsignal(sig), namesz); 183210688Srpaulo 184210688Srpaulo return (name); 185210688Srpaulo} 186210688Srpaulo 187210688Srpauloint 188211184Srpauloproc_read(struct proc_handle *phdl, void *buf, size_t size, size_t addr) 189210688Srpaulo{ 190210688Srpaulo struct ptrace_io_desc piod; 191210688Srpaulo 192210688Srpaulo if (phdl == NULL) 193210688Srpaulo return (-1); 194210688Srpaulo piod.piod_op = PIOD_READ_D; 195210688Srpaulo piod.piod_len = size; 196210688Srpaulo piod.piod_addr = (void *)buf; 197210688Srpaulo piod.piod_offs = (void *)addr; 198210688Srpaulo 199210688Srpaulo if (ptrace(PT_IO, phdl->pid, (caddr_t)&piod, 0) < 0) 200210688Srpaulo return (-1); 201210688Srpaulo return (piod.piod_len); 202210688Srpaulo} 203210688Srpaulo 204210688Srpauloconst lwpstatus_t * 205210688Srpauloproc_getlwpstatus(struct proc_handle *phdl) 206210688Srpaulo{ 207210688Srpaulo struct ptrace_lwpinfo lwpinfo; 208210688Srpaulo lwpstatus_t *psp = &phdl->lwps; 209210688Srpaulo siginfo_t *siginfo; 210210688Srpaulo 211210688Srpaulo if (phdl == NULL) 212210688Srpaulo return (NULL); 213211184Srpaulo if (ptrace(PT_LWPINFO, phdl->pid, (caddr_t)&lwpinfo, 214211184Srpaulo sizeof(lwpinfo)) < 0) 215210688Srpaulo return (NULL); 216210688Srpaulo siginfo = &lwpinfo.pl_siginfo; 217210688Srpaulo if (lwpinfo.pl_event == PL_EVENT_SIGNAL && 218265308Smarkj (lwpinfo.pl_flags & PL_FLAG_SI) != 0) { 219265308Smarkj if (siginfo->si_signo == SIGTRAP && 220265308Smarkj (siginfo->si_code == TRAP_BRKPT || 221265308Smarkj siginfo->si_code == TRAP_TRACE)) { 222265308Smarkj psp->pr_why = PR_FAULTED; 223265308Smarkj psp->pr_what = FLTBPT; 224265308Smarkj } else { 225265308Smarkj psp->pr_why = PR_SIGNALLED; 226265308Smarkj psp->pr_what = siginfo->si_signo; 227265308Smarkj } 228210688Srpaulo } else if (lwpinfo.pl_flags & PL_FLAG_SCE) { 229210688Srpaulo psp->pr_why = PR_SYSENTRY; 230210688Srpaulo } else if (lwpinfo.pl_flags & PL_FLAG_SCX) { 231210688Srpaulo psp->pr_why = PR_SYSEXIT; 232210688Srpaulo } 233210688Srpaulo 234210688Srpaulo return (psp); 235210688Srpaulo} 236