procfs_ioctl.c revision 170307
187321Sdes/*- 287321Sdes * 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: head/sys/fs/procfs/procfs_ioctl.c 170307 2007-06-05 00:00:57Z jeff $ 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 45147692Speter#ifdef COMPAT_IA32 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; 65147692Speter#ifdef COMPAT_IA32 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 */ 117166826Srwatson error = priv_check_cred(td->td_ucred, 118166826Srwatson PRIV_DEBUG_SUGID, SUSER_ALLOWJAIL); 119164033Srwatson if (error) 120164033Srwatson break; 121164033Srwatson } 12287542Sdes p->p_pfsflags = flags; 12387321Sdes break; 12487321Sdes case PIOCGFL: 12587542Sdes *(unsigned int *)data = p->p_pfsflags; 12687321Sdes break; 12787321Sdes case PIOCWAIT: 128164356Skib while (p->p_step == 0 && (p->p_flag & P_WEXIT) == 0) { 12987321Sdes /* sleep until p stops */ 130169168Sdes _PHOLD(p); 13187321Sdes error = msleep(&p->p_stype, &p->p_mtx, 13287321Sdes PWAIT|PCATCH, "pioctl", 0); 133169168Sdes _PRELE(p); 13487321Sdes if (error != 0) 13587321Sdes break; 13687321Sdes } 13787321Sdes /* fall through to PIOCSTATUS */ 13887321Sdes case PIOCSTATUS: 13987321Sdes ps = (struct procfs_status *)data; 14087321Sdes ps->state = (p->p_step == 0); 14187321Sdes ps->flags = 0; /* nope */ 14287321Sdes ps->events = p->p_stops; 14387321Sdes ps->why = p->p_step ? p->p_stype : 0; 14487321Sdes ps->val = p->p_step ? p->p_xstat : 0; 14587321Sdes break; 146147692Speter#ifdef COMPAT_IA32 147147692Speter case PIOCWAIT32: 148164356Skib while (p->p_step == 0 && (p->p_flag & P_WEXIT) == 0) { 149147692Speter /* sleep until p stops */ 150169168Sdes _PHOLD(p); 151147692Speter error = msleep(&p->p_stype, &p->p_mtx, 152147692Speter PWAIT|PCATCH, "pioctl", 0); 153169168Sdes _PRELE(p); 154147692Speter if (error != 0) 155147692Speter break; 156147692Speter } 157147692Speter /* fall through to PIOCSTATUS32 */ 158147692Speter case PIOCSTATUS32: 159147692Speter ps32 = (struct procfs_status32 *)data; 160147692Speter ps32->state = (p->p_step == 0); 161147692Speter ps32->flags = 0; /* nope */ 162147692Speter ps32->events = p->p_stops; 163147692Speter ps32->why = p->p_step ? p->p_stype : 0; 164147692Speter ps32->val = p->p_step ? p->p_xstat : 0; 165147692Speter break; 166147692Speter#endif 167147676Speter#if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 168147676Speter case _IOC(IOC_IN, 'p', 5, 0): 169147676Speter#endif 170162711Sru#ifdef COMPAT_FREEBSD6 171162711Sru case _IO('p', 5): 172162711Sru ival = IOCPARM_IVAL(data); 173162711Sru data = &ival; 174162711Sru#endif 17587321Sdes case PIOCCONT: 17687542Sdes if (p->p_step == 0) 17787321Sdes break; 178162711Sru sig = *(unsigned int *)data; 17987542Sdes if (sig != 0 && !_SIG_VALID(sig)) { 18087321Sdes error = EINVAL; 18187321Sdes break; 18287321Sdes } 18387321Sdes#if 0 18487321Sdes p->p_step = 0; 18599072Sjulian if (P_SHOULDSTOP(p)) { 18687321Sdes p->p_xstat = sig; 187102950Sdavidxu p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG); 188170307Sjeff PROC_SLOCK(p); 189103216Sjulian thread_unsuspend(p); 190170307Sjeff PROC_SUNLOCK(p); 191113618Sjhb } else if (sig) 192113618Sjhb psignal(p, sig); 19387321Sdes#else 19487321Sdes if (sig) 19587321Sdes psignal(p, sig); 19687542Sdes p->p_step = 0; 19787321Sdes wakeup(&p->p_step); 19887321Sdes#endif 19987321Sdes break; 20087321Sdes default: 20187321Sdes error = (ENOTTY); 20287321Sdes } 203123247Sdes 20487321Sdes return (error); 20587321Sdes} 20687321Sdes 20787321Sdes/* 20887321Sdes * Clean up on last close 20987321Sdes */ 21087321Sdesint 21187321Sdesprocfs_close(PFS_CLOSE_ARGS) 21287321Sdes{ 21387321Sdes if (p != NULL && (p->p_pfsflags & PF_LINGER) == 0) { 214113618Sjhb PROC_LOCK_ASSERT(p, MA_OWNED); 21587321Sdes p->p_pfsflags = 0; 21687321Sdes p->p_stops = 0; 21787321Sdes p->p_step = 0; 21887321Sdes wakeup(&p->p_step); 21987321Sdes } 22087321Sdes return (0); 22187321Sdes} 222