henesyinit from p9fd787fda5 years agoHistory
1288 lines · 22.4 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#include	"ureg.h" enum{	Qdir,	Qargs,	Qctl,	Qfd,	Qfpregs,	Qkregs,	Qmem,	Qnote,	Qnoteid,	Qnotepg,	Qns,	Qproc,	Qregs,	Qsegment,	Qstatus,	Qtext,	Qwait,	Qprofile,}; enum{	CMclose,	CMclosefiles,	CMfixedpri,	CMhang,	CMkill,	CMnohang,	CMpri,	CMprivate,	CMprofile,	CMstart,	CMstartstop,	CMstop,	CMwaitstop,	CMwired,}; #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,			0440,	"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,	CMkill,		"kill",		1,	CMpri,		"pri",			2,	CMprivate,	"private",		1,	CMprofile,	"profile",		1,	CMstart,		"start",		1,	CMstartstop,	"startstop",	1,	CMstop,		"stop",		1,	CMwaitstop,	"waitstop",	1,	CMwired,		"wired",		2,}; /* 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 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(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(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 voidprocinit(void){	if(conf.nproc >= (1<<(16-QSHIFT))-1)		print("warning: too many procs for devproc\n");} 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); 	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 Qmem:	case Qnote:	case Qctl:		if(p->privatemem)			error(Eperm);		/* fall through */	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); 	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->name->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);	if(waserror()){		unlock(f);		qunlock(&p->debug);		nexterror();	} 	n = readstr(0, a, count, p->dot->name->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);	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) == 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)

Lines 1–500 of 1288.