⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devproc.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 2 页
字号:
#include	"u.h"#include "trace.h"#include	"tos.h"#include	"lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"error.h"#include	"ureg.h"extern uchar _end[];	// Plan 9 VXenum{	Qdir,	Qtrace,	Qargs,	Qctl,	Qfd,	Qfpregs,	Qkregs,	Qmem,	Qnote,	Qnoteid,	Qnotepg,	Qns,	Qproc,	Qregs,	Qsegment,	Qstatus,	Qtext,	Qwait,	Qprofile,};enum{	CMclose,	CMclosefiles,	CMfixedpri,	CMhang,	CMkill,	CMnohang,	CMnoswap,	CMpri,	CMprivate,	CMprofile,	CMstart,	CMstartstop,	CMstartsyscall,	CMstop,	CMwaitstop,	CMwired,	CMtrace,};enum{	Nevents = 0x4000,	Emask = Nevents - 1,};#define	STATSIZE	(2*KNAMELEN+12+9*12)/* * Status, fd, and ns are left fully readable (0444) because of their use in debugging, * particularly on shared servers. * Arguably, ns and fd shouldn't be readable; if you'd prefer, change them to 0000 */Dirtab procdir[] ={	"args",		{Qargs},	0,			0660,	"ctl",		{Qctl},		0,			0000,	"fd",		{Qfd},		0,			0444,	"fpregs",	{Qfpregs},	sizeof(FPsave),		0000,	"kregs",	{Qkregs},	sizeof(Ureg),		0400,	"mem",		{Qmem},		0,			0000,	"note",		{Qnote},	0,			0000,	"noteid",	{Qnoteid},	0,			0664,	"notepg",	{Qnotepg},	0,			0000,	"ns",		{Qns},		0,			0444,	"proc",		{Qproc},	0,			0400,	"regs",		{Qregs},	sizeof(Ureg),		0000,	"segment",	{Qsegment},	0,			0444,	"status",	{Qstatus},	STATSIZE,		0444,	"text",		{Qtext},	0,			0000,	"wait",		{Qwait},	0,			0400,	"profile",	{Qprofile},	0,			0400,};staticCmdtab proccmd[] = {	CMclose,		"close",		2,	CMclosefiles,		"closefiles",		1,	CMfixedpri,		"fixedpri",		2,	CMhang,			"hang",			1,	CMnohang,		"nohang",		1,	CMnoswap,		"noswap",		1,	CMkill,			"kill",			1,	CMpri,			"pri",			2,	CMprivate,		"private",		1,	CMprofile,		"profile",		1,	CMstart,		"start",		1,	CMstartstop,		"startstop",		1,	CMstartsyscall,		"startsyscall",		1,	CMstop,			"stop",			1,	CMwaitstop,		"waitstop",		1,	CMwired,		"wired",		2,	CMtrace,		"trace",		0,};/* Segment type from portdat.h */static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", };/* * Qids are, in path: *	 4 bits of file type (qids above) *	23 bits of process slot number + 1 *	     in vers, *	32 bits of pid, for consistency checking * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid. */#define	QSHIFT	5	/* location in qid of proc slot # */#define	QID(q)		((((ulong)(q).path)&0x0000001F)>>0)#define	SLOT(q)		(((((ulong)(q).path)&0x07FFFFFE0)>>QSHIFT)-1)#define	PID(q)		((q).vers)#define	NOTEID(q)	((q).vers)void	procctlreq(Proc*, char*, int);int	procctlmemio(Proc*, ulong, int, void*, int);Chan*	proctext(Chan*, Proc*);Segment* txt2data(Proc*, Segment*);int	procstopped(void*);void	mntscan(Mntwalk*, Proc*);static Traceevent *tevents;static Lock tlock;static int topens;static int tproduced, tconsumed;void (*proctrace)(Proc*, int, vlong);extern int unfair;static voidprofclock(Ureg *ur, Timer *t){#if 0	Tos *tos;	if(up == 0 || up->state != Running)		return;	/* user profiling clock */	if(userureg(ur)){		tos = (Tos*)(USTKTOP-sizeof(Tos));		tos->clock += TK2MS(1);		segclock(ur->pc);	}#endif}static intprocgen(Chan *c, char *name, Dirtab *tab, int _, int s, Dir *dp){	Qid qid;	Proc *p;	char *ename;	Segment *q;	ulong pid, path, perm, len;	if(s == DEVDOTDOT){		mkqid(&qid, Qdir, 0, QTDIR);		devdir(c, qid, "#p", 0, eve, 0555, dp);		return 1;	}	if(c->qid.path == Qdir){		if(s == 0){			strcpy(up->genbuf, "trace");			mkqid(&qid, Qtrace, -1, QTFILE);			devdir(c, qid, up->genbuf, 0, eve, 0444, dp);			return 1;		}		if(name != nil){			/* ignore s and use name to find pid */			pid = strtol(name, &ename, 10);			if(pid==0 || ename[0]!='\0')				return -1;			s = procindex(pid);			if(s < 0)				return -1;		}		else if(--s >= conf.nproc)			return -1;		p = proctab(s);		pid = p->pid;		if(pid == 0)			return 0;		sprint(up->genbuf, "%lud", pid);		/*		 * String comparison is done in devwalk so name must match its formatted pid		*/		if(name != nil && strcmp(name, up->genbuf) != 0)			return -1;		mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR);		devdir(c, qid, up->genbuf, 0, p->user, DMDIR|0555, dp);		return 1;	}	if(c->qid.path == Qtrace){		strcpy(up->genbuf, "trace");		mkqid(&qid, Qtrace, -1, QTFILE);		devdir(c, qid, up->genbuf, 0, eve, 0444, dp);		return 1;	}	if(s >= nelem(procdir))		return -1;	if(tab)		panic("procgen");	tab = &procdir[s];	path = c->qid.path&~(((1<<QSHIFT)-1));	/* slot component */	p = proctab(SLOT(c->qid));	perm = tab->perm;	if(perm == 0)		perm = p->procmode;	else	/* just copy read bits */		perm |= p->procmode & 0444;	len = tab->length;	switch(QID(c->qid)) {	case Qwait:		len = p->nwait;	/* incorrect size, but >0 means there's something to read */		break;	case Qprofile:		q = p->seg[TSEG];		if(q && q->profile) {			len = (q->top-q->base)>>LRESPROF;			len *= sizeof(*q->profile);		}		break;	}	mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);	devdir(c, qid, tab->name, len, p->user, perm, dp);	return 1;}static void_proctrace(Proc* p, int etype, vlong ts){	Traceevent *te;	if (p->trace == 0 || topens == 0 ||		tproduced - tconsumed >= Nevents)		return;	te = &tevents[tproduced&Emask];	te->pid = p->pid;	te->etype = etype;	if (ts == 0)		te->time = todget(nil);	else		te->time = ts;	tproduced++;}static voidprocinit(void){	if(conf.nproc >= (1<<(16-QSHIFT))-1)		print("warning: too many procs for devproc\n");	addclock0link((void (*)(void))profclock, 113);	/* Relative prime to HZ */}static Chan*procattach(char *spec){	return devattach('p', spec);}static Walkqid*procwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, 0, 0, procgen);}static intprocstat(Chan *c, uchar *db, int n){	return devstat(c, db, n, 0, 0, procgen);}/* *  none can't read or write state on other *  processes.  This is to contain access of *  servers running as none should they be *  subverted by, for example, a stack attack. */static voidnonone(Proc *p){	if(p == up)		return;	if(strcmp(up->user, "none") != 0)		return;	if(iseve())		return;	error(Eperm);}static Chan*procopen(Chan *c, int omode){	Proc *p;	Pgrp *pg;	Chan *tc;	int pid;	if(c->qid.type & QTDIR)		return devopen(c, omode, 0, 0, procgen);	if(QID(c->qid) == Qtrace){		if (omode != OREAD) 			error(Eperm);		lock(&tlock);		if (waserror()){			unlock(&tlock);			nexterror();		}		if (topens > 0)			error("already open");		topens++;		if (tevents == nil){			tevents = (Traceevent*)malloc(sizeof(Traceevent) * Nevents);			if(tevents == nil)				error(Enomem);			tproduced = tconsumed = 0;		}		proctrace = _proctrace;		unlock(&tlock);		poperror();		c->mode = openmode(omode);		c->flag |= COPEN;		c->offset = 0;		return c;	}			p = proctab(SLOT(c->qid));	qlock(&p->debug);	if(waserror()){		qunlock(&p->debug);		nexterror();	}	pid = PID(c->qid);	if(p->pid != pid)		error(Eprocdied);	omode = openmode(omode);	switch(QID(c->qid)){	case Qtext:		if(omode != OREAD)			error(Eperm);		tc = proctext(c, p);		tc->offset = 0;		qunlock(&p->debug);		poperror();		return tc;	case Qproc:	case Qkregs:	case Qsegment:	case Qprofile:	case Qfd:		if(omode != OREAD)			error(Eperm);		break;	case Qnote:		if(p->privatemem)			error(Eperm);		break;	case Qmem:	case Qctl:		if(p->privatemem)			error(Eperm);		nonone(p);		break;	case Qargs:	case Qnoteid:	case Qstatus:	case Qwait:	case Qregs:	case Qfpregs:		nonone(p);		break;	case Qns:		if(omode != OREAD)			error(Eperm);		c->aux = malloc(sizeof(Mntwalk));		break;	case Qnotepg:		nonone(p);		pg = p->pgrp;		if(pg == nil)			error(Eprocdied);		if(omode!=OWRITE || pg->pgrpid == 1)			error(Eperm);		c->pgrpid.path = pg->pgrpid+1;		c->pgrpid.vers = p->noteid;		break;	default:		pprint("procopen %lux\n", c->qid);		error(Egreg);	}	/* Affix pid to qid */	if(p->state != Dead)		c->qid.vers = p->pid;	/* make sure the process slot didn't get reallocated while we were playing */	coherence();	if(p->pid != pid)		error(Eprocdied);	tc = devopen(c, omode, 0, 0, procgen);	qunlock(&p->debug);	poperror();	return tc;}static intprocwstat(Chan *c, uchar *db, int n){	Proc *p;	Dir *d;	if(c->qid.type&QTDIR)		error(Eperm);	if(QID(c->qid) == Qtrace)		return devwstat(c, db, n);			p = proctab(SLOT(c->qid));	nonone(p);	d = nil;	if(waserror()){		free(d);		qunlock(&p->debug);		nexterror();	}	qlock(&p->debug);	if(p->pid != PID(c->qid))		error(Eprocdied);	if(strcmp(up->user, p->user) != 0 && strcmp(up->user, eve) != 0)		error(Eperm);	d = smalloc(sizeof(Dir)+n);	n = convM2D(db, n, &d[0], (char*)&d[1]);	if(n == 0)		error(Eshortstat);	if(!emptystr(d->uid) && strcmp(d->uid, p->user) != 0){		if(strcmp(up->user, eve) != 0)			error(Eperm);		else			kstrdup(&p->user, d->uid);	}	if(d->mode != ~0UL)		p->procmode = d->mode&0777;	poperror();	free(d);	qunlock(&p->debug);	return n;}static longprocoffset(long offset, char *va, int *np){	if(offset > 0) {		offset -= *np;		if(offset < 0) {			memmove(va, va+*np+offset, -offset);			*np = -offset;		}		else			*np = 0;	}	return offset;}static intprocqidwidth(Chan *c){	char buf[32];	return sprint(buf, "%lud", c->qid.vers);}intprocfdprint(Chan *c, int fd, int w, char *s, int ns){	int n;	if(w == 0)		w = procqidwidth(c);	n = snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %*lud %.2ux) %5ld %8lld %s\n",		fd,		&"r w rw"[(c->mode&3)<<1],		devtab[c->type]->dc, c->dev,		c->qid.path, w, c->qid.vers, c->qid.type,		c->iounit, c->offset, c->path->s);	return n;}static intprocfds(Proc *p, char *va, int count, long offset){	Fgrp *f;	Chan *c;	char buf[256];	int n, i, w, ww;	char *a;	/* print to buf to avoid holding fgrp lock while writing to user space */	if(count > sizeof buf)		count = sizeof buf;	a = buf;	qlock(&p->debug);	f = p->fgrp;	if(f == nil){		qunlock(&p->debug);		return 0;	}	lock(&f->ref.lk);	if(waserror()){		unlock(&f->ref.lk);		qunlock(&p->debug);		nexterror();	}	n = readstr(0, a, count, p->dot->path->s);	n += snprint(a+n, count-n, "\n");	offset = procoffset(offset, a, &n);	/* compute width of qid.path */	w = 0;	for(i = 0; i <= f->maxfd; i++) {		c = f->fd[i];		if(c == nil)			continue;		ww = procqidwidth(c);		if(ww > w)			w = ww;	}	for(i = 0; i <= f->maxfd; i++) {		c = f->fd[i];		if(c == nil)			continue;		n += procfdprint(c, i, w, a+n, count-n);		offset = procoffset(offset, a, &n);	}	unlock(&f->ref.lk);	qunlock(&p->debug);	poperror();	/* copy result to user space, now that locks are released */	memmove(va, buf, n);	return n;}static voidprocclose(Chan * c){	if(QID(c->qid) == Qtrace){		lock(&tlock);		if(topens > 0)			topens--;		if(topens == 0)			proctrace = nil;		unlock(&tlock);	}	if(QID(c->qid) == Qns && c->aux != 0)		free(c->aux);}static voidint2flag(int flag, char *s){	if(flag == 0){		*s = '\0';		return;	}	*s++ = '-';	if(flag & MAFTER)		*s++ = 'a';	if(flag & MBEFORE)		*s++ = 'b';	if(flag & MCREATE)		*s++ = 'c';	if(flag & MCACHE)		*s++ = 'C';	*s = '\0';}static intprocargs(Proc *p, char *buf, int nbuf){	int j, k, m;	char *a;	int n;	a = p->args;	if(p->setargs){		snprint(buf, nbuf, "%s [%s]", p->text, p->args);		return strlen(buf);	}	n = p->nargs;	for(j = 0; j < nbuf - 1; j += m){		if(n <= 0)			break;		if(j != 0)			buf[j++] = ' ';		m = snprint(buf+j, nbuf-j, "%q",  a);		k = strlen(a) + 1;		a += k;		n -= k;	}	return j;}static inteventsavailable(void *_){	return tproduced > tconsumed;}static longprocread(Chan *c, void *va, long n, vlong off){	/* NSEG*32 was too small for worst cases */	char *a, flag[10], *sps, *srv, statbuf[NSEG*64];	int i, j, m, navail, ne, pid, rsize;	long l;	uchar *rptr;	ulong offset;	Mntwalk *mw;	Proc *p;	Segment *sg, *s;	Ureg kur;	Waitq *wq;		a = va;	offset = off;	if(c->qid.type & QTDIR)		return devdirread(c, a, n, 0, 0, procgen);	if(QID(c->qid) == Qtrace){		if(!eventsavailable(nil))			return 0;		rptr = (uchar*)va;		navail = tproduced - tconsumed;		if(navail > n / sizeof(Traceevent))			navail = n / sizeof(Traceevent);		while(navail > 0) {			ne = ((tconsumed & Emask) + navail > Nevents)? 					Nevents - (tconsumed & Emask): navail;			memmove(rptr, &tevents[tconsumed & Emask], 					ne * sizeof(Traceevent));			tconsumed += ne;			rptr += ne * sizeof(Traceevent);			navail -= ne;		}		return rptr - (uchar*)va;	}	p = proctab(SLOT(c->qid));	if(p->pid != PID(c->qid))		error(Eprocdied);	switch(QID(c->qid)){	case Qargs:		qlock(&p->debug);		j = procargs(p, up->genbuf, sizeof up->genbuf);		qunlock(&p->debug);		if(offset >= j)			return 0;		if(offset+n > j)			n = j-offset;		memmove(a, &up->genbuf[offset], n);		return n;	case Qmem:		if(offset < USTKTOP)			return procctlmemio(p, offset, n, va, 1);		error("no kernel memory access");	case Qprofile:		s = p->seg[TSEG];		if(s == 0 || s->profile == 0)			error("profile is off");		i = (s->top-s->base)>>LRESPROF;		i *= sizeof(*s->profile);		if(offset >= i)			return 0;		if(offset+n > i)			n = i - offset;		memmove(a, ((char*)s->profile)+offset, n);		return n;	case Qnote:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -