Beispiel #1
0
/**
 * @brief Checks access permissions to a memory area.
 * 
 * @param addr Address to be checked.
 * @param size Size of memory area.
 * @param mask Access permissions mask.
 * 
 * @returns Non-zero if access is authorized, and zero otherwise.
 */
PUBLIC int chkmem(const void *addr, size_t size, mode_t mask)
{
	int ret;              /* Return value.           */
	struct region *reg;   /* Working memory region.  */
	struct pregion *preg; /* Working process region. */
	
	/* Get associated process memory region. */
	if ((preg = findreg(curr_proc, ADDR(addr))) == NULL)
		return (-1);
	
	lockreg(reg = preg->reg);
	
	/* Not allowed. */
	if (!(accessreg(curr_proc, reg) & mask))
	{
		unlockreg(reg);
		return (-1);
	}
		
	ret = withinreg(preg, ADDR(addr));
	ret &= withinreg(preg, ADDR(addr) + size);

	unlockreg(reg);
	
	return (ret);
}
Beispiel #2
0
/*
 * Loads an ELF 32 executable.
 */
PRIVATE addr_t load_elf32(struct inode *inode)
{
	int i;                  /* Loop index.                    */
	addr_t addr;            /* Region address.                */
	addr_t entry;           /* Program entry point.           */
	struct elf32_fhdr *elf; /* ELF file header.               */
	struct elf32_phdr *seg; /* ELF Program header.            */
	block_t blk;            /* Working block number.          */
	buffer_t header;        /* File headers block buffer.     */
	struct region *reg;     /* Working memory region.         */
	struct pregion *preg;   /* Working process memory region. */
	
	blk = block_map(inode, 0, 0);
	
	/* Empty file. */
	if (blk == BLOCK_NULL)
	{
		curr_proc->errno = -ENOEXEC;
		return (0);
	}
	
	/* Read ELF file header. */
	header = bread(inode->dev, blk);
	elf = buffer_data(header);
	
	/* Bad ELF file. */
	if (!is_elf(elf))
	{
		brelse(header);
		curr_proc->errno = -ENOEXEC;
		return (0);
	}
	
	/* Bad ELF file. */
	if (elf->e_phoff + elf->e_phnum*elf->e_phentsize > BLOCK_SIZE)
	{
		brelse(header);
		curr_proc->errno = -ENOEXEC;
		return (0);
	}
	
	seg = (struct elf32_phdr *)((char *)buffer_data(header) + elf->e_phoff);
	
	/* Load segments. */
	for (i = 0; i < elf->e_phnum; i++)
	{
		/* Not loadable. */
		if (seg[i].p_type != PT_LOAD)
			continue;
		
		/* Broken executable. */
		if (seg[i].p_filesz > seg[i].p_memsz)
		{
			kprintf("broken executable");
			
			brelse(header);
			curr_proc->errno = -ENOEXEC;
			return (0);
		}
		
		addr = ALIGN(seg[i].p_vaddr, seg[i].p_align);
		
		/* Text section. */
		if (!(seg[i].p_flags ^ (PF_R | PF_X)))
		{
			preg = TEXT(curr_proc);
			reg = allocreg(S_IRUSR | S_IXUSR, seg[i].p_memsz, 0);
		}
		
		/* Data section. */
		else
		{
			preg = DATA(curr_proc);
			reg = allocreg(S_IRUSR | S_IWUSR, seg[i].p_memsz, 0);
		}
		
		/* Failed to allocate region. */
		if (reg == NULL)
		{
			brelse(header);
			curr_proc->errno = -ENOMEM;
			return (0);
		}
		
		/* Attach memory region. */
		if (attachreg(curr_proc, preg, addr, reg))
		{
			freereg(reg);
			brelse(header);
			curr_proc->errno = -ENOMEM;
			return (0);
		}
		
		loadreg(inode, reg, seg[i].p_offset, seg[i].p_filesz);
		
		unlockreg(reg);	
	}
	
	entry = elf->e_entry;
	
	brelse(header);
	
	return (entry);
}
Beispiel #3
0
/*
 * Executes a program.
 */
PUBLIC int sys_execve(const char *filename, const char **argv, const char **envp)
{
	int i;                /* Loop index.          */
	struct inode *inode;  /* File inode.          */
	struct region *reg;   /* Process region.      */
	addr_t entry;         /* Program entry point. */
	addr_t sp;            /* User stack pointer.  */
	char *name;           /* File name.           */
	char stack[ARG_MAX];  /* Stack size.          */

	/* Get file name. */
	if ((name = getname(filename)) == NULL)
		return (curr_proc->errno);

	/* Build arguments before freeing user memory. */
	kmemset(stack, 0, ARG_MAX);
	if (!(sp = buildargs(stack, ARG_MAX, argv, envp)))
	{
		putname(name);
		return (curr_proc->errno);
	}

	/* Get file's inode. */
	if ((inode = inode_name(name)) == NULL)
	{
		putname(name);
		return (curr_proc->errno);
	}

	/* Not a regular file. */
	if (!S_ISREG(inode->mode))
	{
		putname(name);
		inode_put(inode);
		return (-EACCES);
	}

	/* Not allowed. */
	if (!permission(inode->mode, inode->uid, inode->gid, curr_proc, MAY_EXEC, 0))
	{
		putname(name);
		inode_put(inode);
		return (-EACCES);
	}

	/* Close file descriptors. */
	for (i = 0; i < OPEN_MAX; i++)
	{
		if (curr_proc->close & (1 << i))
			do_close(i);
	}

	/* Detach process memory regions. */
	for (i = 0; i < NR_PREGIONS; i++)
		detachreg(curr_proc, &curr_proc->pregs[i]);
	
	/* Reset signal handlers. */
	curr_proc->restorer = NULL;
	for (i = 0; i < NR_SIGNALS; i++)
	{
		if (curr_proc->handlers[i] != SIG_DFL)
		{
			if (curr_proc->handlers[i] != SIG_IGN)
				curr_proc->handlers[i] = SIG_DFL;
		}
	}
	
	/* Load executable. */
	if (!(entry = load_elf32(inode)))
		goto die0;

	/* Attach stack region. */
	if ((reg = allocreg(S_IRUSR | S_IWUSR, PAGE_SIZE, REGION_DOWNWARDS)) == NULL)
		goto die0;
	if (attachreg(curr_proc, STACK(curr_proc), USTACK_ADDR - 1, reg))
		goto die1;
	unlockreg(reg);

	/* Attach heap region. */
	if ((reg = allocreg(S_IRUSR | S_IWUSR, PAGE_SIZE, REGION_UPWARDS)) == NULL)
		goto die0;
	if (attachreg(curr_proc, HEAP(curr_proc), UHEAP_ADDR, reg))
		goto die1;
	unlockreg(reg);
	
	inode_put(inode);
	putname(name);

	kmemcpy((void *)(USTACK_ADDR - ARG_MAX), stack, ARG_MAX);
	
	user_mode(entry, sp);
	
	/* Will not return. */
	return (0);

die1:
	unlockreg(reg);
	freereg(reg);
die0:
	inode_put(inode);
	putname(name);
	die(((SIGSEGV & 0xff) << 16) | (1 << 9));
	return (-1);
}