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

📄 sysproc.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 2 页
字号:
#define	WANT_M#include	"u.h"#include	"tos.h"#include	"lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"error.h"#include "a.out.h"int	shargs(char*, int, char**);extern void checkpages(void);extern void checkpagerefs(void);longsysr1(ulong *x){	vx32sysr1();	return 0;}longsysrfork(ulong *arg){	Proc *p;	int n, i;	Fgrp *ofg;	Pgrp *opg;	Rgrp *org;	Egrp *oeg;	ulong pid, flag;	Mach *wm;	flag = arg[0];	/* Check flags before we commit */	if((flag & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))		error(Ebadarg);	if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG))		error(Ebadarg);	if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG))		error(Ebadarg);	if((flag&RFPROC) == 0) {		if(flag & (RFMEM|RFNOWAIT))			error(Ebadarg);		if(flag & (RFFDG|RFCFDG)) {			ofg = up->fgrp;			if(flag & RFFDG)				up->fgrp = dupfgrp(ofg);			else				up->fgrp = dupfgrp(nil);			closefgrp(ofg);		}		if(flag & (RFNAMEG|RFCNAMEG)) {			opg = up->pgrp;			up->pgrp = newpgrp();			if(flag & RFNAMEG)				pgrpcpy(up->pgrp, opg);			/* inherit noattach */			up->pgrp->noattach = opg->noattach;			closepgrp(opg);		}		if(flag & RFNOMNT)			up->pgrp->noattach = 1;		if(flag & RFREND) {			org = up->rgrp;			up->rgrp = newrgrp();			closergrp(org);		}		if(flag & (RFENVG|RFCENVG)) {			oeg = up->egrp;			up->egrp = smalloc(sizeof(Egrp));			up->egrp->ref.ref = 1;			if(flag & RFENVG)				envcpy(up->egrp, oeg);			closeegrp(oeg);		}		if(flag & RFNOTEG)			up->noteid = incref(&noteidalloc);		return 0;	}	p = newproc();	p->fpsave = up->fpsave;	p->scallnr = up->scallnr;	p->s = up->s;	p->nerrlab = 0;	p->slash = up->slash;	p->dot = up->dot;	incref(&p->dot->ref);	memmove(p->note, up->note, sizeof(p->note));	p->privatemem = up->privatemem;	p->noswap = up->noswap;	p->nnote = up->nnote;	p->notified = 0;	p->lastnote = up->lastnote;	p->notify = up->notify;	p->ureg = up->ureg;	p->dbgreg = 0;	/* Make a new set of memory segments */	n = flag & RFMEM;	qlock(&p->seglock);	if(waserror()){		qunlock(&p->seglock);		nexterror();	}	for(i = 0; i < NSEG; i++)		if(up->seg[i])			p->seg[i] = dupseg(up->seg, i, n);	qunlock(&p->seglock);	poperror();	/* File descriptors */	if(flag & (RFFDG|RFCFDG)) {		if(flag & RFFDG)			p->fgrp = dupfgrp(up->fgrp);		else			p->fgrp = dupfgrp(nil);	}	else {		p->fgrp = up->fgrp;		incref(&p->fgrp->ref);	}	/* Process groups */	if(flag & (RFNAMEG|RFCNAMEG)) {		p->pgrp = newpgrp();		if(flag & RFNAMEG)			pgrpcpy(p->pgrp, up->pgrp);		/* inherit noattach */		p->pgrp->noattach = up->pgrp->noattach;	}	else {		p->pgrp = up->pgrp;		incref(&p->pgrp->ref);	}	if(flag & RFNOMNT)		up->pgrp->noattach = 1;	if(flag & RFREND)		p->rgrp = newrgrp();	else {		incref(&up->rgrp->ref);		p->rgrp = up->rgrp;	}	/* Environment group */	if(flag & (RFENVG|RFCENVG)) {		p->egrp = smalloc(sizeof(Egrp));		p->egrp->ref.ref = 1;		if(flag & RFENVG)			envcpy(p->egrp, up->egrp);	}	else {		p->egrp = up->egrp;		incref(&p->egrp->ref);	}	p->hang = up->hang;	p->procmode = up->procmode;	/* Craft a return frame which will cause the child to pop out of	 * the scheduler in user mode with the return register zero	 */	forkchild(p, up->dbgreg);	p->parent = up;	p->parentpid = up->pid;	if(flag&RFNOWAIT)		p->parentpid = 0;	else {		lock(&up->exl);		up->nchild++;		unlock(&up->exl);	}	if((flag&RFNOTEG) == 0)		p->noteid = up->noteid;	p->fpstate = up->fpstate;	pid = p->pid;	memset(p->time, 0, sizeof(p->time));	p->time[TReal] = msec();	kstrdup(&p->text, up->text);	kstrdup(&p->user, up->user);	/*	 *  since the bss/data segments are now shareable,	 *  any mmu info about this process is now stale	 *  (i.e. has bad properties) and has to be discarded.	 */	flushmmu();	p->basepri = up->basepri;	p->priority = up->basepri;	p->fixedpri = up->fixedpri;	p->mp = up->mp;	wm = up->wired;	if(wm)		procwired(p, wm->machno);	ready(p);	sched();	return pid;}static ulongl2be(long l){	uchar *cp;	cp = (uchar*)&l;	return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];}static char Echanged[] = "exec arguments changed underfoot";longsysexec(ulong *arg){	char *volatile elem, *volatile file, *ufile;	Chan *volatile tc;	/*	 * Open the file, remembering the final element and the full name.	 */	file = nil;	elem = nil;	tc = nil;	if(waserror()){		if(file)			free(file);		if(elem)			free(elem);		if(tc)			cclose(tc);		nexterror();	}	ufile = uvalidaddr(arg[0], 1, 0);	file = validnamedup(ufile, 1);	tc = namec(file, Aopen, OEXEC, 0);	kstrdup((char**)&elem, up->genbuf);	/*	 * Read the header.  If it's a #!, fill in progarg[] with info and repeat.	 */	int i, n, nprogarg;	char *progarg[sizeof(Exec)/2+1];	char *prog, *p;	char line[sizeof(Exec)+1];	Exec exec;	nprogarg = 0;	n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);	if(n < 2)		error(Ebadexec);	p = (char*)&exec;	if(p[0] == '#' && p[1] == '!'){		memmove(line, p, n);		nprogarg = shargs(line, n, progarg);		if(nprogarg == 0)			error(Ebadexec);				/* The original file becomes an extra arg after #! line */		progarg[nprogarg++] = file;				/*		 * Take the #! $0 as a file to open, and replace		 * $0 with the original path's name.		 */		prog = progarg[0];		progarg[0] = elem;		cclose(tc);		tc = nil;	/* in case namec errors out */		tc = namec(prog, Aopen, OEXEC, 0);		n = devtab[tc->type]->read(tc, &exec, sizeof(Exec), 0);		if(n < 2)			error(Ebadexec);	}	/* 	 * #! has had its chance, now we need a real binary	 */	ulong magic, entry, text, etext, data, edata, bss, ebss;	magic = l2be(exec.magic);	if(n != sizeof(Exec) || l2be(exec.magic) != AOUT_MAGIC)		error(Ebadexec);	entry = l2be(exec.entry);	text = l2be(exec.text);	data = l2be(exec.data);	bss = l2be(exec.bss);	etext = ROUND(UTZERO+sizeof(Exec)+text, BY2PG);	edata = ROUND(etext + data, BY2PG);	ebss = ROUND(etext + data + bss, BY2PG);	//iprint("entry %#lux text %#lux data %#lux bss %#lux\n", entry, text, data, bss);//iprint("etext %#lux edata %#lux ebss %#lux\n", etext, edata, ebss);	if(entry < UTZERO+sizeof(Exec) || entry >= UTZERO+sizeof(Exec)+text)		error(Ebadexec);		/* many overflow possibilities */	if(text >= USTKTOP || data >= USTKTOP || bss >= USTKTOP	|| etext >= USTKTOP || edata >= USTKTOP || ebss >= USTKTOP	|| etext >= USTKTOP || edata < etext || ebss < edata)		error(Ebadexec);	/*	 * Copy argv into new stack segment temporarily mapped elsewhere.	 * Be careful: multithreaded program could be changing argv during this.	 * Pass 1: count number of arguments, string bytes.	 */	int nargv, strbytes;	ulong argp, ssize, spage;	strbytes = 0;	for(i=0; i<nprogarg; i++)		strbytes += strlen(progarg[i]) + 1;	argp = arg[1];	for(nargv=0;; nargv++, argp += BY2WD){		ulong a;		char *str;		a = *(ulong*)uvalidaddr(argp, BY2WD, 0);		if(a == 0)			break;		str = uvalidaddr(a, 1, 0);		n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;		if(nprogarg > 0 && nargv == 0)			continue;	/* going to skip argv[0] on #! */		strbytes += n;	}	if(nargv == 0)		error("exec missing argv");	/* 	 * Skip over argv[0] if using #!.  Waited until now so that	 * string would still be checked for validity during loop.	 */	if(nprogarg > 0){		nargv--;		arg[1] += BY2WD;	}	ssize = BY2WD*((nprogarg+nargv)+1) + ROUND(strbytes, BY2WD) + sizeof(Tos);	/*	 * 8-byte align SP for those (e.g. sparc) that need it.	 * execregs() will subtract another 4 bytes for argc.	 */	if((ssize+4) & 7)		ssize += 4;	spage = (ssize+(BY2PG-1)) >> PGSHIFT;	/*	 * Pass 2: build the stack segment, being careful not to assume	 * that the counts from pass 1 are still valid.	 */	if(spage > TSTKSIZ)		error(Enovmem);	qlock(&up->seglock);	if(waserror()){		if(up->seg[ESEG]){			putseg(up->seg[ESEG]);			up->seg[ESEG] = nil;		}		qunlock(&up->seglock);		nexterror();	}	up->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);	flushmmu();	// Needed for Plan 9 VX  XXX really?	/*	 * Top-of-stack structure.	 */	Tos *tos;	ulong utos;	utos = USTKTOP - sizeof(Tos);	tos = (Tos*)(uzero + utos + TSTKTOP - USTKTOP);	tos->cyclefreq = m->cyclefreq;	cycles((uvlong*)&tos->pcycles);	tos->pcycles = -tos->pcycles;	tos->kcycles = tos->pcycles;	tos->clock = 0;	/*	 * Argument pointers and strings, together.	 */	char *bp, *ep;	ulong *targp;	ulong ustrp, uargp;	ustrp = utos - ROUND(strbytes, BY2WD);	uargp = ustrp - BY2WD*((nprogarg+nargv)+1);	bp = (char*)(uzero + ustrp + TSTKTOP - USTKTOP);	ep = bp + strbytes;	p = bp;	targp = (ulong*)(uzero + uargp + TSTKTOP - USTKTOP);		/* #! args are trusted */	for(i=0; i<nprogarg; i++){		n = strlen(progarg[i]) + 1;		if(n  > ep - p)			error(Echanged);		memmove(p, progarg[i], n);		p += n;		*targp++ = ustrp;		ustrp += n;	}		/* the rest are not */	argp = arg[1];	for(i=0; i<nargv; i++){		ulong a;		char *str;				a = *(ulong*)uvalidaddr(argp, BY2WD, 0);		argp += BY2WD;				str = uvalidaddr(a, 1, 0);		n = ((char*)vmemchr(str, 0, 0x7FFFFFFF) - str) + 1;		if(n  > ep - p)			error(Echanged);		memmove(p, str, n);		p += n;		*targp++ = ustrp;		ustrp += n;	}	if(*(ulong*)uvalidaddr(argp, BY2WD, 0) != 0)		error(Echanged);		*targp = 0;	/*	 * But wait, there's more: prepare an arg copy for up->args	 * using the copy we just made in the temporary segment.	 */	char *args;	int nargs;	n = p - bp;	/* includes NUL on last arg, so must be > 0 */	if(n <= 0)	/* nprogarg+nargv > 0; checked above */		error(Egreg);	if(n > 128)		n = 128;	args = smalloc(n);	if(waserror()){		free(args);		nexterror();	}	memmove(args, bp, n);	for(i=0; i<n; i++)	/* NULs -> spaces */		if(args[i] == '\0')			args[i] = ' ';	/* find beginning of UTF character boundary to place final NUL */	while(n > 0 && (args[n-1]&0xC0) == 0x80)		n--;	args[n-1] = '\0';	nargs = n;	/*	 * Now we're ready to commit.	 */	free(up->text);	up->text = elem;	free(up->args);	up->args = args;	up->nargs = n;	elem = nil;	poperror();	/* args */	/*	 * Free old memory.  Special segments maintained across exec.	 */	Segment *s;	for(i = SSEG; i <= BSEG; i++) {		putseg(up->seg[i]);		up->seg[i] = nil;	/* in case of error */	}	for(i = BSEG+1; i< NSEG; i++) {		s = up->seg[i];		if(s && (s->type&SG_CEXEC)) {			putseg(s);			up->seg[i] = nil;		}	}		/*	 * Close on exec	 */	Fgrp *f;	f = up->fgrp;	for(i=0; i<=f->maxfd; i++)		fdclose(i, CCEXEC);	/* Text.  Shared. Attaches to cache image if possible */	/* attachimage returns a locked cache image */	Image *img;	Segment *ts;	img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (etext-UTZERO)>>PGSHIFT);	ts = img->s;	up->seg[TSEG] = ts;	ts->flushme = 1;	ts->fstart = 0;	ts->flen = sizeof(Exec)+text;	unlock(&img->ref.lk);	/* Data. Shared. */	s = newseg(SG_DATA, etext, (edata-etext)>>PGSHIFT);	up->seg[DSEG] = s;	/* Attached by hand */	incref(&img->ref);	s->image = img;	s->fstart = ts->fstart+ts->flen;	s->flen = data;	/* BSS. Zero fill on demand */	up->seg[BSEG] = newseg(SG_BSS, edata, (ebss-edata)>>PGSHIFT);	/*	 * Move the stack	 */	s = up->seg[ESEG];	up->seg[ESEG] = 0;	up->seg[SSEG] = s;	qunlock(&up->seglock);	poperror();	/* seglock */	s->base = USTKTOP-USTKSIZE;	s->top = USTKTOP;	relocateseg(s, USTKTOP-TSTKTOP);	/*	 *  '/' processes are higher priority (hack to make /ip more responsive).	 */	if(devtab[tc->type]->dc == L'/')		up->basepri = PriRoot;	up->priority = up->basepri;	poperror();	/* tc, elem, file */	cclose(tc);	free(file);	// elem is now up->text	/*	 *  At this point, the mmu contains info about the old address	 *  space and needs to be flushed	 */	flushmmu();	qlock(&up->debug);	up->nnote = 0;	up->notify = 0;	up->notified = 0;	up->privatemem = 0;	procsetup(up);	qunlock(&up->debug);	if(up->hang)		up->procctl = Proc_stopme;	return execregs(entry, USTKTOP - uargp, nprogarg+nargv);}intshargs(char *s, int n, char **ap)

⌨️ 快捷键说明

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