Пример #1
0
inoptr newfile(inoptr pino, char *name)
{
    inoptr nindex;
    uint8_t j;

    /* First see if parent is writeable */
    if(!(getperm(pino) & OTH_WR))
        goto nogood;

    if(!(nindex = i_open(pino->c_dev, 0)))
        goto nogood;

    /* BUG FIX:  user/group setting was missing  SN */
    nindex->c_node.i_uid = udata.u_euid;
    nindex->c_node.i_gid = udata.u_egid;

    nindex->c_node.i_mode = F_REG;   /* For the time being */
    nindex->c_node.i_nlink = 1;
    nindex->c_node.i_size = 0;
    for(j=0; j <20; j++)
        nindex->c_node.i_addr[j] = 0;
    wr_inode(nindex);

    if(!ch_link(pino, "", name, nindex)) {
        i_deref(nindex);
        goto nogood;
    }
    i_deref(pino);
    return nindex;

nogood:
    i_deref(pino);
    return NULLINODE;
}
Пример #2
0
static arg_t chdiroot_op(inoptr ino, inoptr * p)
{
	if (getmode(ino) != F_DIR) {
		udata.u_error = ENOTDIR;
		i_deref(ino);
		return (-1);
	}
	i_deref(*p);
	*p = ino;
	return 0;
}
Пример #3
0
int16_t _stat(void)
{
	inoptr ino;
	if (!(ino = n_open(path, NULLINOPTR)))
		return (-1);
	stcpy(ino, buf);
	i_deref(ino);
	return (0);
}
Пример #4
0
void oft_deref(int8_t of)
{
    struct oft *ofptr;

    ofptr = of_tab + of;
    if(!(--ofptr->o_refs) && ofptr->o_inode) {
        i_deref(ofptr->o_inode);
        ofptr->o_inode = NULLINODE;
    }
}
Пример #5
0
arg_t _stat(void)
{
	inoptr ino;
	int err;
	if (!(ino = n_open(path, NULLINOPTR)))
		return (-1);
	err = stcpy(ino, buf);
	i_deref(ino);
	return err;
}
Пример #6
0
arg_t _mknod(void)
{
	inoptr ino;
	inoptr parent;
	char fname[FILENAME_LEN + 1];

	udata.u_error = 0;

	if (!super() && ((mode & F_MASK) != F_PIPE)) {
		udata.u_error = EPERM;
		goto nogood3;
	}
	if ((ino = n_open(name, &parent)) != NULL) {
		udata.u_error = EEXIST;
		goto nogood;
	}

	if (!parent) {
		udata.u_error = ENOENT;
		return (-1);
	}

	filename(name, fname);
	ino = newfile(parent, fname);
	if(!ino)
		goto nogood3;	/* parent inode is derefed in newfile. SN */

	/* Initialize mode and dev */
	ino->c_node.i_mode = mode & ~udata.u_mask;
	ino->c_node.i_addr[0] = isdevice(ino) ? dev : 0;
	setftime(ino, A_TIME | M_TIME | C_TIME);
	wr_inode(ino);

	i_deref(ino);
	return (0);

      nogood:
	i_deref(ino);
	i_deref(parent);
      nogood3:
	return (-1);
}
Пример #7
0
arg_t _chown(void)
{
	inoptr ino;
	int ret;

	if (!(ino = n_open(path, NULLINOPTR)))
		return (-1);
	ret = chown_op(ino);
	i_deref(ino);
	return ret;
}
Пример #8
0
static int chown_op(inoptr ino)
{
	if (ino->c_node.i_uid != udata.u_euid && esuper()) {
		i_deref(ino);
		return (-1);
	}
	ino->c_node.i_uid = owner;
	ino->c_node.i_gid = group;
	setftime(ino, C_TIME);
	return 0;
}
Пример #9
0
arg_t _unlink(void)
{
	inoptr ino;
	inoptr pino;
	int r;
	char fname[FILENAME_LEN + 1];

	ino = n_open(path, &pino);

	if (!(pino && ino)) {
		if (pino)	/* parent exist */
			i_deref(pino);
		udata.u_error = ENOENT;
		return (-1);
	}
	filename(path, fname);
	r = unlinki(ino, pino, fname);
	i_deref(pino);
	i_deref(ino);
	return r;
}
Пример #10
0
static int16_t chmod_op(inoptr ino)
{
	if (ino->c_node.i_uid != udata.u_euid && esuper()) {
		i_deref(ino);
		return (-1);
	}

	ino->c_node.i_mode =
	    (mode & MODE_MASK) | (ino->c_node.i_mode & F_MASK);
	setftime(ino, C_TIME);
	return 0;
}
Пример #11
0
uint8_t write_core_image(void)
{
	inoptr parent = NULLINODE;
	inoptr ino;

	udata.u_error = 0;

	/* FIXME: need to think more about the case sp is lala */
	if (uput("core", (uint8_t *)udata.u_syscall_sp - 5, 5))
		return 0;

	ino = n_open((char *)udata.u_syscall_sp - 5, &parent);
	if (ino) {
		i_deref(parent);
		return 0;
	}
	if (parent) {
		i_lock(parent);
		if ((ino = newfile(parent, "core")) != NULL) {
			ino->c_node.i_mode = F_REG | 0400;
			setftime(ino, A_TIME | M_TIME | C_TIME);
			wr_inode(ino);
			f_trunc(ino);
#if 0
	/* FIXME address ranges for different models - move core writer
	   for address spaces into helpers ?  */
			/* FIXME: need to add some arch specific header bits, and
			   also pull stuff like the true sp and registers out of
			   the return stack properly */

			corehdr.ch_base = pagemap_base;
			corehdr.ch_break = udata.u_break;
			corehdr.ch_sp = udata.u_syscall_sp;
			corehdr.ch_top = PROGTOP;
			udata.u_offset = 0;
			udata.u_base = (uint8_t *)&corehdr;
			udata.u_sysio = true;
			udata.u_count = sizeof(corehdr);
			writei(ino, 0);
			udata.u_sysio = false;
			udata.u_base = (uint8_t *)pagemap_base;
			udata.u_count = udata.u_break - pagemap_base;
			writei(ino, 0);
			udata.u_base = udata.u_sp;
			udata.u_count = PROGTOP - (uint32_t)udata.u_sp;
			writei(ino, 0);
#endif
			i_unlock_deref(ino);
			return W_COREDUMP;
		}
	}
	return 0;
}
Пример #12
0
arg_t _link(void)
{
	inoptr ino;
	inoptr ino2;
	inoptr parent2;
	char fname[FILENAME_LEN + 1];

	if (!(ino = n_open(name1, NULLINOPTR)))
		return (-1);

	if (getmode(ino) == F_DIR && esuper())
		goto nogood;

	if (ino->c_node.i_nlink == 0xFFFF) {
		udata.u_error = EMLINK;
		goto nogood;
	}

	/* Make sure file2 doesn't exist, and get its parent */
	if ((ino2 = n_open(name2, &parent2)) != NULL) {
		i_deref(ino2);
		i_deref(parent2);
		udata.u_error = EEXIST;
		goto nogood;
	}

	if (!parent2)
		goto nogood;

	if (ino->c_dev != parent2->c_dev) {
		i_deref(parent2);
		udata.u_error = EXDEV;
		goto nogood;
	}

	filename(name2, fname);

	if (!ch_link(parent2, "", fname, ino)) {
		i_deref(parent2);
		goto nogood;
	}

	/* Update the link count. */
	++ino->c_node.i_nlink;
	wr_inode(ino);
	setftime(ino, C_TIME);

	i_deref(parent2);
	i_deref(ino);
	return 0;

      nogood:
	i_deref(ino);
	return -1;
}
Пример #13
0
int16_t _utime(void)
{
	inoptr ino;
	time_t t[2];

	if (!valaddr(buf, 2 * sizeof(time_t)))
		return (-1);
	if (!(ino = n_open(file, NULLINOPTR)))
		return (-1);
	if (ino->c_node.i_uid != udata.u_euid && esuper()) {
		i_deref(ino);
		return (-1);
	}
	uget(buf, t, 2 * sizeof(time_t));
	/* FIXME: needs updating once we pack top bits
	   elsewhere in the inode */
	ino->c_node.i_atime = t[0];
	ino->c_node.i_mtime = t[1];
	setftime(ino, C_TIME);
	i_deref(ino);
	return (0);
}
Пример #14
0
inoptr srch_mt(inoptr ino)
{
    uint8_t j;
    struct mount *m = &fs_tab[0];

    for(j=0; j < NMOUNTS; ++j){
        if(m->m_dev != NO_DEVICE &&  m->m_fs->s_mntpt == ino) {
            i_deref(ino);
            return i_open(m->m_dev, ROOTINODE);
        }
        m++;
    };
    return ino;
}
Пример #15
0
uint8_t write_core_image(void)
{
	inoptr parent = NULLINODE;
	inoptr ino;

	udata.u_error = 0;

	/* FIXME: need to think more about the case sp is lala */
	if (uput("core", udata.u_syscall_sp - 5, 5))
		return 0;

	ino = n_open(udata.u_syscall_sp - 5, &parent);
	if (ino) {
		i_deref(parent);
		return 0;
	}
	if (parent) {
		i_lock(parent);
		if (ino = newfile(parent, "core")) {
			ino->c_node.i_mode = F_REG | 0400;
			setftime(ino, A_TIME | M_TIME | C_TIME);
			wr_inode(ino);
			f_trunc(ino);

			/* FIXME: need to add some arch specific header bits, and
			   also pull stuff like the true sp and registers out of
			   the return stack properly */

			corehdr.ch_base = MAPBASE;
			corehdr.ch_break = udata.u_break;
			corehdr.ch_sp = udata.u_syscall_sp;
			corehdr.ch_top = PROGTOP;
			udata.u_offset = 0;
			udata.u_base = (uint8_t *)&corehdr;
			udata.u_sysio = true;
			udata.u_count = sizeof(corehdr);
			writei(ino, 0);
			udata.u_sysio = false;
			udata.u_base = MAPBASE;
			udata.u_count = udata.u_break - MAPBASE;
			writei(ino, 0);
			udata.u_base = udata.u_sp;
			udata.u_count = PROGTOP - (uint16_t)udata.u_sp;
			writei(ino, 0);
			i_unlock_deref(ino);
			return W_COREDUMP;
		}
	}
	return 0;
}
Пример #16
0
arg_t _utime(void)
{
	inoptr ino;
	time_t t[2];

	if (!(ino = n_open(file, NULLINOPTR)))
		return (-1);
	if (ino->c_flags & CRDONLY) {
		udata.u_error = EROFS;
		goto out2;
	}
	/* Special case in the Unix API - NULL means now */
	if (buf) {
	        if (ino->c_node.i_uid != udata.u_euid && esuper())
			goto out;
		if (!valaddr(buf, 2 * sizeof(time_t)))
			goto out2;
		uget(buf, t, 2 * sizeof(time_t));
	} else {
	        if (!(getperm(ino) & OTH_WR))
			goto out;
	        rdtime(&t[0]);
	        memcpy(&t[1], &t[0], sizeof(t[1]));
        }
	/* FIXME: needs updating once we pack top bits
	   elsewhere in the inode */
	ino->c_node.i_atime = t[0].low;
	ino->c_node.i_mtime = t[1].low;
	setftime(ino, C_TIME);
	i_deref(ino);
	return (0);
out:
	udata.u_error = EPERM;
out2:
	i_deref(ino);
	return -1;
}
Пример #17
0
arg_t _access(void)
{
	inoptr ino;
	uint16_t euid;
	uint16_t egid;
	int16_t retval;

	if ((mode & 07) && !ugetc(path)) {
		udata.u_error = ENOENT;
		return (-1);
	}

	/* Temporarily make eff. id real id. */
	euid = udata.u_euid;
	egid = udata.u_egid;
	udata.u_euid = udata.u_ptab->p_uid;
	udata.u_egid = udata.u_gid;

	if (!(ino = n_open(path, NULLINOPTR))) {
		retval = -1;
		goto nogood;
	}

	retval = 0;
	if (~getperm(ino) & (mode & 07)) {
		udata.u_error = EACCES;
		retval = -1;
	}

	i_deref(ino);
      nogood:
	udata.u_euid = euid;
	udata.u_egid = egid;

	return (retval);
}
Пример #18
0
void doexit(int16_t val, int16_t val2)
{
	int16_t j;
	ptptr p;
	irqflags_t irq;

#ifdef DEBUG
	kprintf("process %d exiting\n", udata.u_ptab->p_pid);

	kprintf
	    ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n",
	     udata.u_page, udata.u_ptab, udata.u_ptab->p_page);
#endif
	if (udata.u_ptab->p_pid == 1)
		panic("killed init");

	_sync();		/* Not necessary, but a good idea. */

	irq = di();

	/* Discard our memory before we blow away and reuse the memory */
	pagemap_free(udata.u_ptab);

	for (j = 0; j < UFTSIZE; ++j) {
		if (udata.u_files[j] != NO_FILE)
			doclose(j);
	}


	udata.u_ptab->p_exitval = (val << 8) | (val2 & 0xff);

	i_deref(udata.u_cwd);
	i_deref(udata.u_root);

	/* Stash away child's execution tick counts in process table,
	 * overlaying some no longer necessary stuff.
	 *
	 * Pedantically POSIX says we should do this at the point of wait()
	 */
	udata.u_utime += udata.u_cutime;
	udata.u_stime += udata.u_cstime;
	memcpy(&(udata.u_ptab->p_priority), &udata.u_utime,
	       2 * sizeof(clock_t));

	for (p = ptab; p < ptab_end; ++p) {
		if (p->p_status == P_EMPTY || p == udata.u_ptab)
			continue;
		/* Set any child's parents to our parent */
		if (p->p_pptr == udata.u_ptab)
			p->p_pptr = udata.u_ptab->p_pptr;
		/* Send SIGHUP to any pgrp members and remove
		   them from our pgrp */
                if (p->p_pgrp == udata.u_ptab->p_pid) {
			p->p_pgrp = 0;
			ssig(p, SIGHUP);
		}
	}
	tty_exit();
	irqrestore(irq);
#ifdef DEBUG
	kprintf
	    ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n",
	     udata.u_page, udata.u_ptab, udata.u_ptab->p_page);
#endif
#ifdef CONFIG_ACCT
	acctexit(p);
#endif
        udata.u_page = 0xFFFFU;
        udata.u_page2 = 0xFFFFU;
	/* FIXME: send SIGCLD here */
	/* FIXME: POSIX.1 says that SIG_IGN for SIGCLD means don't go
	   zombie, just clean up as we go */
	/* Wake up a waiting parent, if any. */
	wakeup((char *) udata.u_ptab->p_pptr);

	udata.u_ptab->p_status = P_ZOMBIE;
	nready--;
	nproc--;

	switchin(getproc());
	panic("doexit: won't exit");
}
Пример #19
0
Файл: process.c Проект: 8l/FUZIX
void doexit(uint16_t val)
{
	int16_t j;
	ptptr p;
	irqflags_t irq;

#ifdef DEBUG
	kprintf("process %d exiting\n", udata.u_ptab->p_pid);

	kprintf
	    ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n",
	     udata.u_page, udata.u_ptab, udata.u_ptab->p_page);
#endif
	if (udata.u_ptab->p_pid == 1)
		panic(PANIC_KILLED_INIT);

	sync();		/* Not necessary, but a good idea. */

	irq = di();

	/* Discard our memory before we blow away and reuse the memory */
	pagemap_free(udata.u_ptab);

	for (j = 0; j < UFTSIZE; ++j) {
		if (udata.u_files[j] != NO_FILE)
			doclose(j);
	}


	udata.u_ptab->p_exitval = val;

	i_deref(udata.u_cwd);
	i_deref(udata.u_root);

	/* Stash away child's execution tick counts in process table,
	 * overlaying some no longer necessary stuff.
	 *
	 * Pedantically POSIX says we should do this at the point of wait()
	 */
	udata.u_utime += udata.u_cutime;
	udata.u_stime += udata.u_cstime;
	memcpy(&(udata.u_ptab->p_priority), &udata.u_utime,
	       2 * sizeof(clock_t));

	for (p = ptab; p < ptab_end; ++p) {
		if (p->p_status == P_EMPTY || p == udata.u_ptab)
			continue;
		/* Set any child's parents to our parent */
		/* FIXME: do we need to wakeup the parent if we do this ? */
		if (p->p_pptr == udata.u_ptab)
			p->p_pptr = udata.u_ptab->p_pptr;
		/* Send SIGHUP to any pgrp members and remove
		   them from our pgrp */
                if (p->p_pgrp == udata.u_ptab->p_pid) {
			p->p_pgrp = 0;
			ssig(p, SIGHUP);
			ssig(p, SIGCONT);
		}
	}
	tty_exit();
	irqrestore(irq);
#ifdef DEBUG
	kprintf
	    ("udata.u_page %u, udata.u_ptab %x, udata.u_ptab->p_page %u\n",
	     udata.u_page, udata.u_ptab, udata.u_ptab->p_page);
#endif
#ifdef CONFIG_ACCT
	acctexit(p);
#endif
        udata.u_page = 0xFFFFU;
        udata.u_page2 = 0xFFFFU;
        signal_parent(udata.u_ptab->p_pptr);
	nready--;
	nproc--;

	switchin(getproc());
	panic(PANIC_DOEXIT);
}
Пример #20
0
inoptr kn_open(char *namep, inoptr *parent)
{
    staticfast inoptr wd;     /* the directory we are currently searching. */
    staticfast inoptr ninode;
    inoptr temp;
    staticfast char *name;

    name = namep;
#ifdef DEBUG
    kprintf("kn_open(\"%s\")\n", name);
#endif

    if(*name == '/')
        wd = udata.u_root;
    else
        wd = udata.u_cwd;

    i_ref(ninode = wd);
    i_ref(ninode);

    for(;;)
    {
        if(ninode)
            magic(ninode);

        /* cheap way to spot rename inside yourself */
        if (udata.u_rename == ninode)
            udata.u_rename = NULLINODE;

        /* See if we are at a mount point */
        if(ninode)
            ninode = srch_mt(ninode);

        while(*name == '/')    /* Skip(possibly repeated) slashes */
            ++name;
        if(!*name)           /* No more components of path? */
            break;
        if(!ninode){
            udata.u_error = ENOENT;
            goto nodir;
        }
        i_deref(wd);
        wd = ninode;
        if(getmode(wd) != F_DIR){
            udata.u_error = ENOTDIR;
            goto nodir;
        }
        if(!(getperm(wd) & OTH_EX)){
            udata.u_error = EPERM;
            goto nodir;
        }

        /* See if we are going up through a mount point */
        if((wd == udata.u_root || (wd->c_num == ROOTINODE && wd->c_dev != root_dev)) &&
                name[0] == '.' && name[1] == '.' &&
                (name[2] == '/' || name[2] == '\0')){
            if (wd == udata.u_root) {
                ninode = wd;
                name += 2;
                continue;
            }
            temp = fs_tab_get(wd->c_dev)->m_fs->s_mntpt;
            ++temp->c_refs;
            i_deref(wd);
            wd = temp;
        }

        ninode = srch_dir(wd, name);

        while(*name != '/' && *name)
            ++name;
    }

    if(parent)
        *parent = wd;
    else
        i_deref(wd);

    if(!(parent || ninode))
        udata.u_error = ENOENT;

    return ninode;

nodir:
    if(parent)
        *parent = NULLINODE;
    i_deref(wd);
    return NULLINODE;
}
Пример #21
0
void doexit(uint16_t val)
{
	int16_t j;
	ptptr p;
	irqflags_t irq;

#ifdef DEBUG
	kprintf("process %d exiting %d\n", udata.u_ptab->p_pid, val);

	kprintf
	    ("udata.u_page %u, udata.u_ptab %p, udata.u_ptab->p_page %u\n",
	     udata.u_page, udata.u_ptab, udata.u_ptab->p_page);
#endif
	if (udata.u_ptab->p_pid == 1)
		panic(PANIC_KILLED_INIT);

	sync();		/* Not necessary, but a good idea. */

	irq = di();

	/* We are exiting, hold all signals  (they will never be
	   delivered). If we don't do this we might take a signal
	   while exiting which would be ... unfortunate */
	udata.u_ptab->p_held = 0xFFFFFFFFUL;
	udata.u_cursig = 0;

	/* Discard our memory before we blow away and reuse the memory */
	pagemap_free(udata.u_ptab);

	for (j = 0; j < UFTSIZE; ++j) {
		if (udata.u_files[j] != NO_FILE)
			doclose(j);
	}


	udata.u_ptab->p_exitval = val;

	i_deref(udata.u_cwd);
	i_deref(udata.u_root);

	/* Stash away child's execution tick counts in process table,
	 * overlaying some no longer necessary stuff.
	 *
	 * Pedantically POSIX says we should do this at the point of wait()
	 */
	udata.u_utime += udata.u_cutime;
	udata.u_stime += udata.u_cstime;
	memcpy(&(udata.u_ptab->p_priority), &udata.u_utime,
	       2 * sizeof(clock_t));

	for (p = ptab; p < ptab_end; ++p) {
		if (p->p_status == P_EMPTY || p == udata.u_ptab)
			continue;
		/* Set any child's parents to init */
		if (p->p_pptr == udata.u_ptab) {
			p->p_pptr = ptab;	/* ptab is always init */
			/* Suppose our child is a zombie and init has
			   SIGCLD blocked */
		        if (ptab[0].p_ignored & (1UL << SIGCHLD)) {
				p->p_status = P_EMPTY;
			} else {
				ssig(&ptab[0], SIGCHLD);
				wakeup(&ptab[0]);
			}
		}
		/* Send SIGHUP to any pgrp members and remove
		   them from our pgrp */
                if (p->p_pgrp == udata.u_ptab->p_pid) {
			p->p_pgrp = 0;
			ssig(p, SIGHUP);
			ssig(p, SIGCONT);
		}
	}
	tty_exit();
	irqrestore(irq);
#ifdef DEBUG
	kprintf
	    ("udata.u_page %u, udata.u_ptab %p, udata.u_ptab->p_page %u\n",
	     udata.u_page, udata.u_ptab, udata.u_ptab->p_page);
#endif
#ifdef CONFIG_ACCT
	acctexit(p);
#endif
        udata.u_page = 0xFFFFU;
        udata.u_page2 = 0xFFFFU;
        signal_parent(udata.u_ptab->p_pptr);
	nready--;
	nproc--;

	switchin(getproc());
	panic(PANIC_DOEXIT);
}
Пример #22
0
arg_t _open(void)
{
	int8_t uindex;
	int8_t oftindex;
	staticfast inoptr ino;
	int16_t perm;
	staticfast inoptr parent;
	char fname[FILENAME_LEN + 1];
	int trunc;
	int r;
	int w;
	int j;

	parent = NULLINODE;

	trunc = flag & O_TRUNC;
	r = (flag + 1) & 1;
	w = (flag + 1) & 2;

	if (O_ACCMODE(flag) == 3 || (flag & O_BADBITS)) {
		udata.u_error = EINVAL;
		return (-1);
	}
	if ((uindex = uf_alloc()) == -1)
		return (-1);

	if ((oftindex = oft_alloc()) == -1)
		goto nooft;

	ino = n_open(name, &parent);
	if (ino) {
		i_deref(parent);
		/* O_EXCL test */
		if ((flag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
			udata.u_error = EEXIST;
			goto idrop;
		}
	} else {
		/* The n_open failed */
		if (udata.u_error == EFAULT)
			goto cantopen;
		/* New file */
		if (!(flag & O_CREAT)) {
			udata.u_error = ENOENT;
			goto cantopen;
		}
		filename(name, fname);
		/* newfile drops parent for us */
		if (parent && (ino = newfile(parent, fname))) {
			ino->c_node.i_mode =
			    (F_REG | (mode & MODE_MASK & ~udata.u_mask));
			setftime(ino, A_TIME | M_TIME | C_TIME);
			wr_inode(ino);
		} else {
			udata.u_error = ENFILE;	/* FIXME, should be set in newfile
						   not bodged to a guessed code */
			goto cantopen;
		}
	}
	/* Book our slot in case we block opening a device */
	of_tab[oftindex].o_inode = ino;

	perm = getperm(ino);
	if ((r && !(perm & OTH_RD)) || (w && !(perm & OTH_WR))) {
		udata.u_error = EACCES;
		goto cantopen;
	}
	if (w) {
		if (getmode(ino) == F_DIR ) {
			udata.u_error = EISDIR;
			goto cantopen;
		}
		if (ino->c_flags & CRDONLY) {
			udata.u_error = EROFS;
			goto cantopen;
		}
	}

	if (isdevice(ino)) {
		inoptr *iptr = &of_tab[oftindex].o_inode;
		/* d_open may block and thus ino may become invalid as may
		   parent (but we don't need it again). It may also be changed
		   by the call to dev_openi */

		if (dev_openi(iptr, flag) != 0)
			goto cantopen;

		/* May have changed */
		/* get the static pointer back in case it changed via dev 
		   usage or just because we blocked */
		ino = *iptr;
	}

	if (trunc && getmode(ino) == F_REG) {
		if (f_trunc(ino))
			goto idrop;
		for (j = 0; j < OFTSIZE; ++j)
			/* Arguably should fix at read/write */
			if (of_tab[j].o_inode == ino)
				of_tab[j].o_ptr = 0;
	}

	udata.u_files[uindex] = oftindex;

	of_tab[oftindex].o_ptr = 0;
	of_tab[oftindex].o_access = flag;	/* Save the low bits only */
	if (flag & O_CLOEXEC)
		udata.u_cloexec |= (1 << oftindex);
	/* FIXME: ATIME ? */

/*
 *         Sleep process if no writer or reader
 */
	if (getmode(ino) == F_PIPE && of_tab[oftindex].o_refs == 1
	    && !(flag & O_NDELAY))
		psleep(ino);

        /* From the moment of the psleep ino is invalid */

	return (uindex);
      idrop:
	i_deref(ino);
      cantopen:
	oft_deref(oftindex);	/* This will call i_deref() */
      nooft:
	udata.u_files[uindex] = NO_FILE;
	return (-1);
}
Пример #23
0
arg_t _execve(void)
{
	/* We aren't re-entrant where this matters */
	uint8_t hdr[16];
	staticfast inoptr ino;
	char **nargv;		/* In user space */
	char **nenvp;		/* In user space */
	struct s_argblk *abuf, *ebuf;
	int argc;
	uint16_t progptr;
	uint16_t progload;
	staticfast uint16_t top;
	uint16_t bin_size;	/* Will need to be bigger on some cpus */
	uint16_t bss;

	top = ramtop;

	if (!(ino = n_open_lock(name, NULLINOPTR)))
		return (-1);

	if (!((getperm(ino) & OTH_EX) &&
	      (ino->c_node.i_mode & F_REG) &&
	      (ino->c_node.i_mode & (OWN_EX | OTH_EX | GRP_EX)))) {
		udata.u_error = EACCES;
		goto nogood;
	}

	setftime(ino, A_TIME);

	udata.u_offset = 0;
	udata.u_count = 16;
	udata.u_base = hdr;
	udata.u_sysio = true;

	readi(ino, 0);
	if (udata.u_done != 16) {
		udata.u_error = ENOEXEC;
		goto nogood;
	}

	if (!header_ok(hdr)) {
		udata.u_error = ENOEXEC;
		goto nogood2;
	}

	progload = hdr[7] << 8;
	if (progload == 0)
		progload = PROGLOAD;

	top = *(uint16_t *)(hdr + 8);
	if (top == 0)	/* Legacy 'all space' binary */
		top = ramtop;
	else	/* Requested an amount, so adjust for the base */
		top += progload;

	bss = *(uint16_t *)(hdr + 14);

	/* Binary doesn't fit */
	/* FIXME: review overflows */
	bin_size = ino->c_node.i_size;
	progptr = bin_size + 1024 + bss;
	if (progload < PROGLOAD || top - progload < progptr || progptr < bin_size) {
		udata.u_error = ENOMEM;
		goto nogood2;
	}

	udata.u_ptab->p_status = P_NOSLEEP;

	/* If we made pagemap_realloc keep hold of some defined area we
	   could in theory just move the arguments up or down as part of
	   the process - that would save us all this hassle but replace it
	   with new hassle */

	/* Gather the arguments, and put them in temporary buffers. */
	abuf = (struct s_argblk *) tmpbuf();
	/* Put environment in another buffer. */
	ebuf = (struct s_argblk *) tmpbuf();

	/* Read args and environment from process memory */
	if (rargs(argv, abuf) || rargs(envp, ebuf))
		goto nogood3;	/* SN */

	/* This must be the last test as it makes changes if it works */
	/* FIXME: once we sort out chmem we can make stack and data
	   two elements. We never allocate 'code' as there is no split I/D */
	/* This is only safe from deadlocks providing pagemap_realloc doesn't
	   sleep */
	if (pagemap_realloc(0, top - MAPBASE, 0))
		goto nogood3;

	/* From this point on we are commmited to the exec() completing */

	/* Core dump and ptrace permission logic */
#ifdef CONFIG_LEVEL_2
	/* Q: should uid == 0 mean we always allow core */
	if ((!(getperm(ino) & OTH_RD)) ||
		(ino->c_node.i_mode & (SET_UID | SET_GID)))
		udata.u_flags |= U_FLAG_NOCORE;
	else
		udata.u_flags &= ~U_FLAG_NOCORE;
#endif
	udata.u_top = top;
	udata.u_ptab->p_top = top;

	/* setuid, setgid if executable requires it */
	if (ino->c_node.i_mode & SET_UID)
		udata.u_euid = ino->c_node.i_uid;

	if (ino->c_node.i_mode & SET_GID)
		udata.u_egid = ino->c_node.i_gid;

	/* FIXME: In the execve case we may on some platforms have space
	   below PROGLOAD to clear... */

	/* We are definitely going to succeed with the exec,
	 * so we can start writing over the old program
	 */
	uput(hdr, (uint8_t *)progload, 16);
	/* At this point, we are committed to reading in and
	 * executing the program. This call must not block. */

	close_on_exec();

	/*
	 *  Read in the rest of the program, block by block. We rely upon
	 *  the optimization path in readi to spot this is a big move to user
	 *  space and move it directly.
	 */

	 progptr = progload + 16;
	 if (bin_size > 16) {
		bin_size -= 16;
		udata.u_base = (uint8_t *)progptr;		/* We copied the first block already */
		udata.u_count = bin_size;
		udata.u_sysio = false;
		readi(ino, 0);
		if (udata.u_done != bin_size)
			goto nogood4;
		progptr += bin_size;
	}
	/* Wipe the memory in the BSS. We don't wipe the memory above
	   that on 8bit boxes, but defer it to brk/sbrk() */
	uzero((uint8_t *)progptr, bss);

	/* Set initial break for program */
	udata.u_break = (int)ALIGNUP(progptr + bss);

	/* Turn off caught signals */
	memset(udata.u_sigvec, 0, sizeof(udata.u_sigvec));

	// place the arguments, environment and stack at the top of userspace memory,

	// Write back the arguments and the environment
	nargv = wargs(((char *) top - 2), abuf, &argc);
	nenvp = wargs((char *) (nargv), ebuf, NULL);

	// Fill in udata.u_name with program invocation name
	uget((void *) ugetw(nargv), udata.u_name, 8);
	memcpy(udata.u_ptab->p_name, udata.u_name, 8);

	tmpfree(abuf);
	tmpfree(ebuf);
	i_deref(ino);

	/* Shove argc and the address of argv just below envp
	   FIXME: should flip them in crt0.S of app for R2L setups
	   so we can get rid of the ifdefs */
#ifdef CONFIG_CALL_R2L	/* Arguments are stacked the 'wrong' way around */
	uputw((uint16_t) nargv, nenvp - 2);
	uputw((uint16_t) argc, nenvp - 1);
#else
	uputw((uint16_t) nargv, nenvp - 1);
	uputw((uint16_t) argc, nenvp - 2);
#endif

	/* Set stack pointer for the program */
	udata.u_isp = nenvp - 2;

	/* Start execution (never returns) */
	udata.u_ptab->p_status = P_RUNNING;
	doexec(progload);

	/* tidy up in various failure modes */
nogood4:
	/* Must not run userspace */
	ssig(udata.u_ptab, SIGKILL);
nogood3:
	udata.u_ptab->p_status = P_RUNNING;
	tmpfree(abuf);
	tmpfree(ebuf);
nogood2:
nogood:
	i_unlock_deref(ino);
	return (-1);
}
Пример #24
0
arg_t _execve(void)
{
	/* Not ideal on stack */
	struct binfmt_flat binflat;
	inoptr ino;
	char **nargv;		/* In user space */
	char **nenvp;		/* In user space */
	struct s_argblk *abuf, *ebuf;
	int argc;
	uint32_t bin_size;	/* Will need to be bigger on some cpus */
	uaddr_t progbase, top;
	uaddr_t go;
	uint32_t true_brk;

	if (!(ino = n_open(name, NULLINOPTR)))
		return (-1);

	if (!((getperm(ino) & OTH_EX) &&
	      (ino->c_node.i_mode & F_REG) &&
	      (ino->c_node.i_mode & (OWN_EX | OTH_EX | GRP_EX)))) {
		udata.u_error = EACCES;
		goto nogood;
	}

	setftime(ino, A_TIME);

	udata.u_offset = 0;
	udata.u_count = sizeof(struct binfmt_flat);
	udata.u_base = (void *)&binflat;
	udata.u_sysio = true;

	readi(ino, 0);
	if (udata.u_count != sizeof(struct binfmt_flat)) {
		udata.u_error = ENOEXEC;
		goto nogood;
	}

	
	/* FIXME: ugly - save this as valid_hdr modifies it */
	true_brk = binflat.bss_end;

	/* Hard coded for our 68K format. We don't quite use the ucLinux
	   names, we don't want to load a ucLinux binary in error! */
	if (memcmp(binflat.magic, "bFLT", 4) || !valid_hdr(ino, &binflat)) {
		udata.u_error = ENOEXEC;
		goto nogood2;
	}

	/* Memory needed */
	bin_size = binflat.bss_end + binflat.stack_size;

	/* Overflow ? */
	if (bin_size < binflat.bss_end) {
		udata.u_error = ENOEXEC;
		goto nogood2;
	}
	
	/* Gather the arguments, and put them in temporary buffers. */
	abuf = (struct s_argblk *) tmpbuf();
	/* Put environment in another buffer. */
	ebuf = (struct s_argblk *) tmpbuf();

	/* Read args and environment from process memory */
	if (rargs(argv, abuf) || rargs(envp, ebuf))
		goto nogood3;

	/* This must be the last test as it makes changes if it works */
	/* FIXME: need to update this to support split code/data and to fix
	   stack handling nicely */
	if (pagemap_realloc(0, bin_size, 0))
		goto nogood3;

	/* Core dump and ptrace permission logic */
#ifdef CONFIG_LEVEL_2
	/* Q: should uid == 0 mean we always allow core */
	if ((!(getperm(ino) & OTH_RD)) ||
		(ino->c_node.i_mode & (SET_UID | SET_GID)))
		udata.u_flags |= U_FLAG_NOCORE;
	else
		udata.u_flags &= ~U_FLAG_NOCORE;
#endif

	udata.u_codebase = progbase = pagemap_base();
	/* From this point on we are commmited to the exec() completing
	   so we can start writing over the old program */
	uput(&binflat, (uint8_t *)progbase, sizeof(struct binfmt_flat));

	/* setuid, setgid if executable requires it */
	if (ino->c_node.i_mode & SET_UID)
		udata.u_euid = ino->c_node.i_uid;

	if (ino->c_node.i_mode & SET_GID)
		udata.u_egid = ino->c_node.i_gid;

	top = progbase + bin_size;

//	kprintf("user space at %p\n", progbase);
//	kprintf("top at %p\n", progbase + bin_size);

	bin_size = binflat.reloc_start + 4 * binflat.reloc_count;
	go = (uint32_t)progbase + binflat.entry;

	close_on_exec();

	/*
	 *  Read in the rest of the program, block by block. We rely upon
	 *  the optimization path in readi to spot this is a big move to user
	 *  space and move it directly.
	 */

	 if (bin_size > sizeof(struct binfmt_flat)) {
		/* We copied the header already */
		bin_size -= sizeof(struct binfmt_flat);
		udata.u_base = (uint8_t *)progbase +
					sizeof(struct binfmt_flat);
		udata.u_count = bin_size;
		udata.u_sysio = false;
		readi(ino, 0);
		if (udata.u_count != bin_size)
			goto nogood4;
	}

	/* Header isn't counted in relocations */
	relocate(&binflat, progbase, bin_size);
	/* This may wipe the relocations */	
	uzero((uint8_t *)progbase + binflat.data_end,
		binflat.bss_end - binflat.data_end + binflat.stack_size);

	/* Use of brk eats into the stack allocation */

	/* Use the temporary we saved (hack) as we mangled bss_end */
	udata.u_break = udata.u_codebase + true_brk;

	/* Turn off caught signals */
	memset(udata.u_sigvec, 0, sizeof(udata.u_sigvec));

	/* place the arguments, environment and stack at the top of userspace memory. */

	/* Write back the arguments and the environment */
	nargv = wargs(((char *) top - 4), abuf, &argc);
	nenvp = wargs((char *) (nargv), ebuf, NULL);

	/* Fill in udata.u_name with Program invocation name */
	uget((void *) ugetl(nargv, NULL), udata.u_name, 8);
	memcpy(udata.u_ptab->p_name, udata.u_name, 8);

	tmpfree(abuf);
	tmpfree(ebuf);
	i_deref(ino);

	/* Shove argc and the address of argv just below envp */
	uputl((uint32_t) nargv, nenvp - 1);
	uputl((uint32_t) argc, nenvp - 2);

	// Set stack pointer for the program
	udata.u_isp = nenvp - 2;

	/*
	 * Sort of - it's a good way to deal with all the stupidity of
	 * random 68K platforms we will have to handle, and a nice place
	 * to stuff the signal trampoline 8)
	 */
	install_vdso();

//	kprintf("Go = %p ISP = %p\n", go, udata.u_isp);

	doexec(go);

nogood4:
	/* Must not run userspace */
	ssig(udata.u_ptab, SIGKILL);
nogood3:
	tmpfree(abuf);
	tmpfree(ebuf);
nogood2:
nogood:
	i_deref(ino);
	return (-1);
}