187321Sdes/*- 2230132Suqs * Copyright (c) 2001 Dag-Erling Co��dan Sm��rgrav 387321Sdes * All rights reserved. 487321Sdes * 587321Sdes * Redistribution and use in source and binary forms, with or without 687321Sdes * modification, are permitted provided that the following conditions 787321Sdes * are met: 887321Sdes * 1. Redistributions of source code must retain the above copyright 987321Sdes * notice, this list of conditions and the following disclaimer 1087321Sdes * in this position and unchanged. 1187321Sdes * 2. Redistributions in binary form must reproduce the above copyright 1287321Sdes * notice, this list of conditions and the following disclaimer in the 1387321Sdes * documentation and/or other materials provided with the distribution. 1487321Sdes * 3. The name of the author may not be used to endorse or promote products 1587321Sdes * derived from this software without specific prior written permission. 1687321Sdes * 1787321Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1887321Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1987321Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2087321Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2187321Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2287321Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2387321Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2487321Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2587321Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2687321Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2787321Sdes * 2887321Sdes * $FreeBSD$ 2987321Sdes */ 3087321Sdes 31147676Speter#include "opt_compat.h" 32147676Speter 3387321Sdes#include <sys/param.h> 3487321Sdes#include <sys/lock.h> 3587321Sdes#include <sys/mutex.h> 3687321Sdes#include <sys/pioctl.h> 37164033Srwatson#include <sys/priv.h> 3887321Sdes#include <sys/proc.h> 3987321Sdes#include <sys/signalvar.h> 4087321Sdes#include <sys/systm.h> 4187321Sdes 4287321Sdes#include <fs/pseudofs/pseudofs.h> 4387321Sdes#include <fs/procfs/procfs.h> 4487321Sdes 45205014Snwhitehorn#ifdef COMPAT_FREEBSD32 46147692Speterstruct procfs_status32 { 47147692Speter int state; /* Running, stopped, something else? */ 48147692Speter int flags; /* Any flags */ 49147692Speter unsigned int events; /* Events to stop on */ 50147692Speter int why; /* What event, if any, proc stopped on */ 51147692Speter unsigned int val; /* Any extra data */ 52147692Speter}; 53147692Speter 54147692Speter#define PIOCWAIT32 _IOR('p', 4, struct procfs_status32) 55147692Speter#define PIOCSTATUS32 _IOR('p', 6, struct procfs_status32) 56147692Speter#endif 57147692Speter 5887321Sdes/* 5987321Sdes * Process ioctls 6087321Sdes */ 6187321Sdesint 6287321Sdesprocfs_ioctl(PFS_IOCTL_ARGS) 6387321Sdes{ 6487321Sdes struct procfs_status *ps; 65205014Snwhitehorn#ifdef COMPAT_FREEBSD32 66147692Speter struct procfs_status32 *ps32; 67147692Speter#endif 6887542Sdes int error, flags, sig; 69162711Sru#ifdef COMPAT_FREEBSD6 70162711Sru int ival; 71162711Sru#endif 7287321Sdes 73169168Sdes KASSERT(p != NULL, 74169168Sdes ("%s() called without a process", __func__)); 75169168Sdes PROC_LOCK_ASSERT(p, MA_OWNED); 76169168Sdes 7787321Sdes error = 0; 7887321Sdes switch (cmd) { 79147676Speter#if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 80147676Speter case _IOC(IOC_IN, 'p', 1, 0): 81147676Speter#endif 82162711Sru#ifdef COMPAT_FREEBSD6 83162711Sru case _IO('p', 1): 84162711Sru ival = IOCPARM_IVAL(data); 85162711Sru data = &ival; 86162711Sru#endif 8787321Sdes case PIOCBIS: 88162711Sru p->p_stops |= *(unsigned int *)data; 8987321Sdes break; 90147676Speter#if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 91147676Speter case _IOC(IOC_IN, 'p', 2, 0): 92147676Speter#endif 93162711Sru#ifdef COMPAT_FREEBSD6 94162711Sru case _IO('p', 2): 95162711Sru ival = IOCPARM_IVAL(data); 96162711Sru data = &ival; 97162711Sru#endif 9887321Sdes case PIOCBIC: 99162711Sru p->p_stops &= ~*(unsigned int *)data; 10087321Sdes break; 101147676Speter#if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 102147676Speter case _IOC(IOC_IN, 'p', 3, 0): 103147676Speter#endif 104162711Sru#ifdef COMPAT_FREEBSD6 105162711Sru case _IO('p', 3): 106162711Sru ival = IOCPARM_IVAL(data); 107162711Sru data = &ival; 108162711Sru#endif 10987321Sdes case PIOCSFL: 110162711Sru flags = *(unsigned int *)data; 111164033Srwatson if (flags & PF_ISUGID) { 112164033Srwatson /* 113164033Srwatson * XXXRW: Is this specific check required here, as 114164033Srwatson * p_candebug() should implement it, or other checks 115164033Srwatson * are missing. 116164033Srwatson */ 117170587Srwatson error = priv_check(td, PRIV_DEBUG_SUGID); 118164033Srwatson if (error) 119164033Srwatson break; 120164033Srwatson } 12187542Sdes p->p_pfsflags = flags; 12287321Sdes break; 12387321Sdes case PIOCGFL: 12487542Sdes *(unsigned int *)data = p->p_pfsflags; 12587321Sdes break; 12687321Sdes case PIOCWAIT: 127164356Skib while (p->p_step == 0 && (p->p_flag & P_WEXIT) == 0) { 12887321Sdes /* sleep until p stops */ 129169168Sdes _PHOLD(p); 13087321Sdes error = msleep(&p->p_stype, &p->p_mtx, 13187321Sdes PWAIT|PCATCH, "pioctl", 0); 132169168Sdes _PRELE(p); 13387321Sdes if (error != 0) 13487321Sdes break; 13587321Sdes } 13687321Sdes /* fall through to PIOCSTATUS */ 13787321Sdes case PIOCSTATUS: 13887321Sdes ps = (struct procfs_status *)data; 13987321Sdes ps->state = (p->p_step == 0); 14087321Sdes ps->flags = 0; /* nope */ 14187321Sdes ps->events = p->p_stops; 14287321Sdes ps->why = p->p_step ? p->p_stype : 0; 14387321Sdes ps->val = p->p_step ? p->p_xstat : 0; 14487321Sdes break; 145205014Snwhitehorn#ifdef COMPAT_FREEBSD32 146147692Speter case PIOCWAIT32: 147164356Skib while (p->p_step == 0 && (p->p_flag & P_WEXIT) == 0) { 148147692Speter /* sleep until p stops */ 149169168Sdes _PHOLD(p); 150147692Speter error = msleep(&p->p_stype, &p->p_mtx, 151147692Speter PWAIT|PCATCH, "pioctl", 0); 152169168Sdes _PRELE(p); 153147692Speter if (error != 0) 154147692Speter break; 155147692Speter } 156147692Speter /* fall through to PIOCSTATUS32 */ 157147692Speter case PIOCSTATUS32: 158147692Speter ps32 = (struct procfs_status32 *)data; 159147692Speter ps32->state = (p->p_step == 0); 160147692Speter ps32->flags = 0; /* nope */ 161147692Speter ps32->events = p->p_stops; 162147692Speter ps32->why = p->p_step ? p->p_stype : 0; 163147692Speter ps32->val = p->p_step ? p->p_xstat : 0; 164147692Speter break; 165147692Speter#endif 166147676Speter#if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 167147676Speter case _IOC(IOC_IN, 'p', 5, 0): 168147676Speter#endif 169162711Sru#ifdef COMPAT_FREEBSD6 170162711Sru case _IO('p', 5): 171162711Sru ival = IOCPARM_IVAL(data); 172162711Sru data = &ival; 173162711Sru#endif 17487321Sdes case PIOCCONT: 17587542Sdes if (p->p_step == 0) 17687321Sdes break; 177162711Sru sig = *(unsigned int *)data; 17887542Sdes if (sig != 0 && !_SIG_VALID(sig)) { 17987321Sdes error = EINVAL; 18087321Sdes break; 18187321Sdes } 18287321Sdes#if 0 18387321Sdes p->p_step = 0; 18499072Sjulian if (P_SHOULDSTOP(p)) { 18587321Sdes p->p_xstat = sig; 186102950Sdavidxu p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG); 187170307Sjeff PROC_SLOCK(p); 188103216Sjulian thread_unsuspend(p); 189170307Sjeff PROC_SUNLOCK(p); 190113618Sjhb } else if (sig) 191225617Skmacy kern_psignal(p, sig); 19287321Sdes#else 19387321Sdes if (sig) 194225617Skmacy kern_psignal(p, sig); 19587542Sdes p->p_step = 0; 19687321Sdes wakeup(&p->p_step); 19787321Sdes#endif 19887321Sdes break; 19987321Sdes default: 20087321Sdes error = (ENOTTY); 20187321Sdes } 202123247Sdes 20387321Sdes return (error); 20487321Sdes} 20587321Sdes 20687321Sdes/* 20787321Sdes * Clean up on last close 20887321Sdes */ 20987321Sdesint 21087321Sdesprocfs_close(PFS_CLOSE_ARGS) 21187321Sdes{ 21287321Sdes if (p != NULL && (p->p_pfsflags & PF_LINGER) == 0) { 213113618Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 21487321Sdes p->p_pfsflags = 0; 21587321Sdes p->p_stops = 0; 21687321Sdes p->p_step = 0; 21787321Sdes wakeup(&p->p_step); 21887321Sdes } 21987321Sdes return (0); 22087321Sdes} 221