Пример #1
0
static long zerofill(unsigned long start, unsigned long end, int prot)
{
	unsigned long pg_start = PAGE_NEXT(start),
	              pg_end   = PAGE_NEXT(end),
	              padd_len = pg_start-start;

	if (start > end)
		return -1;

	if (prot & PROT_WRITE)
		memset((void *)start, 0, padd_len);

	return do_mmap2(pg_start, pg_end-pg_start, prot,
	                MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
}
Пример #2
0
static unsigned long get_mmap_base(elf_bin_t *elf)
{
	unsigned long addr, pg_start, pg_end, mmap_min = ULONG_MAX, mmap_max = 0;
	int i;

	for (i=0; i<elf->hdr.e_phnum; i++) 
		if ( elf->phdr[i].p_type == PT_LOAD)
		{
			pg_start = PAGE_BASE(elf->phdr[i].p_vaddr);
			pg_end   = PAGE_NEXT(elf->phdr[i].p_vaddr + elf->phdr[i].p_memsz);

			if (pg_start < mmap_min)
				mmap_min = pg_start;

			if (pg_end > mmap_max)
				mmap_max = pg_end;
		}

	if (mmap_min > mmap_max)
		mmap_min = mmap_max;

	addr = do_mmap2(mmap_min, mmap_max-mmap_min, PROT_NONE,
	                MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

	if (addr & PG_MASK) /* not on page boundary -> error code */
		return addr;

	sys_munmap(addr, mmap_max-mmap_min);

	return addr-mmap_min;
}
Пример #3
0
/**  ユーザ空間へのアクセス許可があることを確認する(実装部)
     @param[in] as    検査対象の仮想アドレス空間
     @param[in] start 検査開始アドレス
     @param[in] count 検査範囲のアドレス長(単位:バイト)
     @param[in] prot  検査するアクセス権(仮想メモリ領域の保護属性)
     @retval    true  対象範囲に物理ページが存在し, 必要なアクセス権がある
     @retval    false 対象範囲に物理ページが存在しないか, 必要なアクセス権がない
 */
static bool
user_area_can_access_nolock(vm *as, void *start, size_t count, vma_prot prot) {
	int             rc;
	void     *pg_start;
	void       *pg_end;
	vma          *vmap;

	kassert( as != NULL );

	pg_start = (void *)PAGE_START((uintptr_t)start);
	pg_end = ( PAGE_ALIGNED( (uintptr_t)(start + count) ) ? 
	    ( start + count ) : ( (void *)PAGE_NEXT( (uintptr_t)(start + count) ) ) );

	rc = _vm_find_vma_nolock(as, pg_start, &vmap);
	if ( rc != 0 )
		goto can_not_access;

	if ( vmap->end < pg_end )
		goto can_not_access;

	if ( !( vmap->prot & prot ) )
		goto can_not_access;

	return true;

can_not_access:
	return false;
}
Пример #4
0
static char	unmap_page(char *previous, char *mem, char *next)
{
	if (!has_one_page_available())
		return (0);
	if (previous)
		*PAGE_NEXT(previous) = next;
	else
		get_page_list(0, next);
	munmap((void *)mem, *PAGE_SIZE(mem));
	return (0);
}
Пример #5
0
/** sbrkシステムコールの実処理
    @param[in] sbrk    sbrkメッセージ
    @param[in] src     呼出元エンドポイント
    @retval    0       正常に更新した
    @retval   -ENOMEM  メモリ不足により更新に失敗した
 */
static int
handle_sbrk(vm_sys_sbrk *sbrk,endpoint src) {
	int            rc;
	thread       *thr;
	void     *cur_end;
	void     *new_end;
	intrflags   flags;

	acquire_all_thread_lock( &flags );

	thr = thr_find_thread_by_tid_nolock(src);
	if ( thr == NULL ) {

		rc = -ENOENT;
		goto unlock_out;
	}

	rc = proc_expand_heap(thr->p, NULL, &cur_end);

	if ( rc != 0 ) 
		goto unlock_out;

	if ( sbrk->inc == 0 ) {
		
		rc = 0;
		goto success_out;
	}

	new_end = ( PAGE_ALIGNED( (uintptr_t)(cur_end + sbrk->inc) ) ) ? 
		( (void *)( cur_end + sbrk->inc ) )  :
		( (void *)PAGE_NEXT( (uintptr_t)(cur_end + sbrk->inc) ) );

	if ( new_end < thr->p->heap->start ) {
	
		rc = -EINVAL;
		goto unlock_out;
	}

	rc = proc_expand_heap(thr->p, new_end, &cur_end);
	if ( rc != 0 ) 
		goto unlock_out;

success_out:
	release_all_thread_lock(&flags);

	if ( rc == 0 ) 
		sbrk->old_heap_end = cur_end;

	return 0;

unlock_out:
	release_all_thread_lock(&flags);
	return rc;
}
Пример #6
0
static unsigned long set_brk(elf_bin_t *bin)
{
	unsigned long new_brk = 0, v_end, i;

	for (i=0; i<bin->hdr.e_phnum; i++) 
		if ( bin->phdr[i].p_type == PT_LOAD)
		{
			v_end = PAGE_NEXT(bin->phdr[i].p_vaddr+bin->phdr[i].p_memsz);

			if ( (bin->phdr[i].p_type == PT_LOAD) && (new_brk < v_end) )
				new_brk = v_end;
		}

	return (new_brk == set_brk_min(new_brk)) ? 0 : -1;
}
Пример #7
0
static char has_one_page_available()
{
	char 	*mem;
	char	av;

	av = 0;
	mem = get_page_list(0, (void *)-1);
	while (mem && av != 3)
	{
		if (*PAGE_SIZE(mem) == get_alloc_size(TINY))
			av |= 1;
		else if (*PAGE_SIZE(mem) == get_alloc_size(SMALL))
			av |= 2;
		mem = *PAGE_NEXT(mem);
	}
	return (av == 3);
}
Пример #8
0
static char	delete_ptrs_page(char *ptr)
{
	char	*mem;
	char	*previous;
	char	*next;

	previous = NULL;
	mem = get_page_list(0, (void *)-1);
	while (mem)
	{
		next = *PAGE_NEXT(mem);
		if (ptr >= mem + PAGE_META && ptr < mem + *PAGE_SIZE(mem))
			return (evaluate_freeable(ptr, previous, mem, next));
		previous = mem;
		mem = next;
	}
	return (0);
}
Пример #9
0
static long mmap_prog_section(elf_bin_t *elf, Elf32_Phdr *p)
{
	unsigned long base = elf->base, brk_, bss, addr, pg_off, size;
	int prot = 0;

	if (p->p_flags & PF_R)
		prot |= PROT_READ;		
	if (p->p_flags & PF_W)
		prot |= PROT_WRITE;		
	if (p->p_flags & PF_X)
		prot |= PROT_EXEC;

	addr = PAGE_BASE(base+p->p_vaddr);
	size = PAGE_NEXT(base+p->p_vaddr + p->p_filesz) - addr;
	pg_off = p->p_offset/PG_SIZE;

	bss = base + p->p_vaddr + p->p_filesz;
	brk_ = base + p->p_vaddr + p->p_memsz;

	if ( ((p->p_vaddr-p->p_offset) & PG_MASK) || (bss > brk_) )
		return -1;

	addr = do_mmap2(addr, size, prot, MAP_PRIVATE|MAP_FIXED, elf->fd, pg_off);

	if (addr & PG_MASK) /* not on page boundary -> error code */
		return addr;

	if (elf->brk < brk_)
		elf->brk = brk_;

	if (elf->bss < bss)
		elf->bss = bss;

	/* linux does not fill in bss sections
	 * between load segments for interpreters;
	 * makes no difference to the standard ld.so
	 */
	addr = zerofill(bss, brk_, prot);

	if (addr & PG_MASK) /* not on page boundary -> error code */
		return addr;

	return 0;
}
Пример #10
0
/* relocate the stack */
static long get_stack_random_shift(long *auxv)
{
	return 0x1000000 - (PAGE_NEXT((long)get_aux(auxv, AT_EXECFN)) & 0xfff000);
}
Пример #11
0
/** プロセス間でデータをコピーする
    @param[in] dest_as  コピー先の仮想アドレス空間
    @param[in] src_as   コピー元の仮想アドレス空間
    @param[in] dest     コピー先のアドレス
    @param[in] src      コピー元のアドレス
    @param[in] count    コピーするバイト数
    @return    コピーしたバイト数
    @return    -ENOMEM バッファページが獲得できない
    @return    -EFAULT ページが存在しない
    @note      カーネルストレートマップ領域間でメモリコピーを行うことで
               アドレス空間の切り替えを行わないようにする
	       また、自プロセスの空間のmutexを取ると互いの空間のロック待ちで
	       デッドロックするため, プリエンプションを禁止にして自プロセス内の
	       他のスレッドが割り込まないようにし, 自プロセスのアドレス空間の
	       mutexを取らないようにする。
 */
static int
inter_user_copy(vm *dest_as, vm *src_as, void *dest, const void *src, size_t count) {
	int                 rc;
	size_t             len;
	uintptr_t   src_kvaddr;
	vma_prot      src_prot;
	uintptr_t  dest_kvaddr;
	vma_prot     dest_prot;
	void            *saddr;
	void            *daddr;
	size_t         src_len;
	size_t        dest_len;
	size_t         cpy_len;
	void         *new_page;
	vma              *vmap;

	kassert( src_as != NULL );
	kassert( src_as->p != NULL );
	kassert( dest_as != NULL );
	kassert( dest_as->p != NULL );

	/*  アドレス空間とアドレスの範囲がユーザ空間に収まることを確認  */
	if ( ( (uintptr_t)src >= KERN_VMA_BASE ) || ( (uintptr_t)dest >= KERN_VMA_BASE ) )
		return -EFAULT;

	if ( ( dest_as->p == hal_refer_kernel_proc() ) ||
	    ( src_as->p == hal_refer_kernel_proc() ) )
		return -EFAULT;

	/*  自CPUの同一プロセス内のスレッドがアドレス空間を操作
	 *   しないことを保証するためにプリエンプションを抑止
	 */
	ti_disable_dispatch();  

	/*  相手の空間のロック(mutex)を取る  */
	if ( &current->p->vm == dest_as ) 
		mutex_lock( &src_as->asmtx );
	else 
		mutex_lock( &dest_as->asmtx );
	
	saddr = (void *)src;
	daddr = dest;

	for( len = count; len > 0; ) {
		
		/*
		 * コピー元/コピー先ページを取得する
		 */
		if ( src_as->p == hal_refer_kernel_proc() )
			src_kvaddr = PAGE_START(saddr);
		else {

			rc = hal_translate_user_page(src_as, (uintptr_t)saddr,
			    &src_kvaddr, &src_prot);
			if ( rc != 0 ) {
				
				/*
				 * ページ未割り当て時はページを割当てる
				 */
				rc = _vm_find_vma_nolock(src_as, saddr, &vmap);
				if ( rc != 0 )
					goto unlock_out;

				if ( vmap->prot == VMA_PROT_NONE )
					goto unlock_out;

				rc = get_free_page(&new_page);
				if ( rc != 0 )
					goto unlock_out;

				memset(new_page, 0, PAGE_SIZE);
				rc = hal_map_user_page(src_as, (uintptr_t)saddr, 
				    (uintptr_t)new_page, vmap->prot );
				if ( rc != 0 ) {
					
					free_page(new_page);
					goto unlock_out;
				}
			}
		}

		if ( dest_as->p == hal_refer_kernel_proc() )
			dest_kvaddr = PAGE_START(daddr);
		else {

			rc = hal_translate_user_page(dest_as, (uintptr_t)daddr,
			    &dest_kvaddr, &dest_prot);
			if ( rc != 0 ) {
				
				/*
				 * ページ未割り当て時はページを割当てる
				 */
				rc = _vm_find_vma_nolock(dest_as, daddr, &vmap);
				if ( rc != 0 )
					goto unlock_out;

				if ( vmap->prot == VMA_PROT_NONE )
					goto unlock_out;

				rc = get_free_page(&new_page);
				if ( rc != 0 )
					goto unlock_out;

				memset(new_page, 0, PAGE_SIZE);
				rc = hal_map_user_page(dest_as, (uintptr_t)daddr, 
				    (uintptr_t)new_page, vmap->prot );
				if ( rc != 0 ) {
					
					free_page(new_page);
					goto unlock_out;
				}
			}
		}

		/*
		 * src/destともページ内に収まる分だけコピーする
		 */
		src_len = PAGE_NEXT(saddr) - (uintptr_t)saddr;
		dest_len = PAGE_NEXT(daddr) - (uintptr_t)daddr;
		cpy_len = ( src_len <= dest_len ) ? ( src_len ) : ( dest_len );
		if ( cpy_len > len )
			cpy_len = len;

		len -= cpy_len;
		while( cpy_len > 0 ) {

			*(char *)(dest_kvaddr + ( (uintptr_t)daddr - PAGE_START(daddr) ) ) 
				= *(char *)(src_kvaddr +
				    ( (uintptr_t)saddr - PAGE_START(saddr) ) );
			--cpy_len;
			++saddr;
			++daddr;
		}
	}

	rc = count - len;

unlock_out:
	if ( &current->p->vm == dest_as ) 
		mutex_unlock( &src_as->asmtx );
	else 
		mutex_unlock( &dest_as->asmtx );

	ti_enable_dispatch();

	return rc;
}