Example #1
0
bool
copy_from_user(struct mm_struct *mm, void *dst, const void *src, size_t len, bool writable) {
    if (!user_mem_check(mm, (uintptr_t)src, len, writable)) {
        return 0;
    }
    memcpy(dst, src, len);
    return 1;
}
Example #2
0
bool
copy_to_user(struct mm_struct *mm, void *dst, const void *src, size_t len) {
    if (!user_mem_check(mm, (uintptr_t)dst, len, 1)) {
        return 0;
    }
    memcpy(dst, src, len);
    return 1;
}
Example #3
0
//
// Checks that environment 'env' is allowed to access the range
// of memory [va, va+len) with permissions 'perm | PTE_U | PTE_P'.
// If it can, then the function simply returns.
// If it cannot, 'env' is destroyed and, if env is the current
// environment, this function will not return.
//
void
user_mem_assert(struct Env *env, const void *va, size_t len, int perm)
{
	if (user_mem_check(env, va, len, perm | PTE_U) < 0) {
		cprintf("[%08x] user_mem_check assertion failure for "
			"va %08x\n", env->env_id, user_mem_check_addr);
		env_destroy(env);	// may not return
	}
}
Example #4
0
int
sys_get_home_dir(char* buf) {
	int r;
	if(curenv->user == -1)
		return -1;
	if((r = user_mem_check(curenv, buf, MAX_PATH_LENGTH, PTE_U|PTE_W)) <0) {
		cprintf("SYS_get_logged_user_name: %08x\n",r);
		return r;
	}
	memmove(buf,"/home/stam",11);
	return 0;
}
Example #5
0
int
sys_update_current_path(char* buf) {
	int r;
	if(curenv->user == -1)
		return -1;
	if((r = user_mem_check(curenv, buf, MAX_PATH_LENGTH, PTE_U)) <0) {
		cprintf("SYS_get_logged_user_name: %08x\n",r);
		return r;
	}
	
	memmove(users[curenv->user].path,buf,MAX_PATH_LENGTH);
	return 0;
}
Example #6
0
int
sys_get_logged_user_name(char* buf) {
	int r;
	if(curenv->user == -1)
		return -1;
	if((r = user_mem_check(curenv, buf, MAX_USER_LENGTH, PTE_U|PTE_W)) <0) {
		cprintf("SYS_get_logged_user_name: %08x\n",r);
		return r;
	}
	
	memmove(buf,users[curenv->user].user,MAX_USER_LENGTH);
	return 0;
}
Example #7
0
int ipc_event_recv(int *pid_store, int *event_store, unsigned int timeout)
{
	if (event_store == NULL) {
		return -E_INVAL;
	}

	struct mm_struct *mm = current->mm;
	if (pid_store != NULL) {
		if (!user_mem_check(mm, (uintptr_t) pid_store, sizeof(int), 1)) {
			return -E_INVAL;
		}
	}
	if (!user_mem_check(mm, (uintptr_t) event_store, sizeof(int), 1)) {
		return -E_INVAL;
	}

	unsigned long saved_ticks;
	timer_t __timer, *timer =
	    ipc_timer_init(timeout, &saved_ticks, &__timer);

	int pid, event, ret;
	if ((ret = recv_event(&pid, &event, timer)) == 0) {
		lock_mm(mm);
		{
			ret = -E_INVAL;
			if (pid_store == NULL
			    || copy_to_user(mm, pid_store, &pid, sizeof(int))) {
				if (copy_to_user
				    (mm, event_store, &event, sizeof(int))) {
					ret = 0;
				}
			}
		}
		unlock_mm(mm);
		return ret;
	}
	return ipc_check_timeout(timeout, saved_ticks);
}
/**
 * Read a word from the container process's vm when we are in the main one
 *     This is only used to 'touch' the page as read so the page table will be right.
 *     See 'copy_from_user' in arch/um/mm/vmm.c for details.
 * @param proc the PCB whose container process will be touched
 * @param addr the address of the word to be touched (should be valid in the container process)
 * @param data the data to be read (of no use now)
 * @return 0 on success, or a negative otherwise
 */
int
host_getvalue (struct proc_struct *proc,
			   uintptr_t addr, uint32_t* data) 
{
	if (!user_mem_check(proc->mm, addr, sizeof (uintptr_t), 0)) {
        return -1;
    }
	
	struct stub_stack *stub_stack = proc->arch.host->stub_stack;
	struct stub_frame *frame = current_stub_frame (stub_stack);
	frame->eax = 0;
	frame->ebx = addr;
	int ret = host_syscall_in_child (proc);
	if (data != NULL)
		*data = ret;
	return 0;
}
Example #9
0
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	// LAB 5: Your code here.
	// Remember to check whether the user has supplied us with a good
	// address!
	struct Env *env;
	int r;
	if ((r = envid2env(envid, &env, 1)) < 0)
		return r; /*-E_BAD_ENV*/
	if ((r = user_mem_check(curenv, tf, sizeof(struct Trapframe), PTE_U | PTE_P)) < 0)
		return r;

	env->env_tf = *tf;
	env->env_tf.tf_eflags |= FL_IF;
	return 0;
//	panic("sys_env_set_trapframe not implemented");
}
Example #10
0
/**
 * Write a word to the container process's vm when we are in the main one
 *     This is only used to 'touch' the page as written so the page table will be right.
 *     See 'copy_to_user' in arch/um/mm/vmm.c for details.
 * @param proc the PCB whose container process will be touched
 * @param addr the address of the word to be touched (should be valid in the container process)
 * @param data the data to be written (of no use now)
 * @return 0 on success, or a negative otherwise
 */
int 
host_assign (struct proc_struct *proc,
			 uintptr_t addr, uint32_t data) 
{
	if (!user_mem_check(proc->mm, addr, sizeof (uintptr_t), 1)) {
		kprintf ("try assigning invalid address: 0x%x\n", addr);
        return -1;
    }

	/* Use stub call so that the page table will be modified properly */
	struct stub_stack *stub_stack = proc->arch.host->stub_stack;
	struct stub_frame *frame = current_stub_frame (stub_stack);
	frame->eax = -1;
	frame->ebx = addr;
	frame->ecx = data;
	
	return host_syscall_in_child (proc);
}
Example #11
0
/* sysfile_get cwd - get current working directory */
int
sysfile_getcwd(char *buf, size_t len) {
    struct mm_struct *mm = current->mm;
    if (len == 0) {
        return -E_INVAL;
    }

    int ret = -E_INVAL;
    lock_mm(mm);
    {
        if (user_mem_check(mm, (uintptr_t)buf, len, 1)) {
            struct iobuf __iob, *iob = iobuf_init(&__iob, buf, len, 0);
            ret = vfs_getcwd(iob);
        }
    }
    unlock_mm(mm);
    return ret;
}
Example #12
0
static int  
sys_proc_save(envid_t envid, struct proc *ps)  
{  
    	struct Env *e;  
    	struct Page *pg;  
    	int offset;  
    	//save env    
   	if (envid2env(envid, &e, 1) <0)  
        	return -E_BAD_ENV;  
    	if (user_mem_check(curenv, ps, sizeof(struct proc), PTE_U|PTE_W|PTE_P) <0)  
        	return -E_FAULT;  
    	ps->env = *e;  
    	//save stack  
    	if ((pg=page_lookup(e->env_pgdir, (void *)(USTACKTOP-PGSIZE), NULL))==NULL)  
        	return -E_FAULT;  
    	
    	memmove(ps->stack, page2kva(pg), PGSIZE);  
   	// cprintf("process %x has been saved\n", envid);  
    	return 0;
}  
Example #13
0
int
sysfile_pipe(int *fd_store) {
    struct mm_struct *mm = current->mm;
    int ret, fd[2];
    if (!user_mem_check(mm, (uintptr_t)fd_store, sizeof(fd), 1)) {
        return -E_INVAL;
    }
    if ((ret = file_pipe(fd)) == 0) {
        lock_mm(mm);
        {
            if (!copy_to_user(mm, fd_store, fd, sizeof(fd))) {
                ret = -E_INVAL;
            }
        }
        unlock_mm(mm);
        if (ret != 0) {
            file_close(fd[0]), file_close(fd[1]);
        }
    }
    return ret;
}
Example #14
0
//restore one process  
static int  
sys_proc_resume(envid_t envid, struct proc *ps)  
{  
    struct Env *e;  
    struct Page *pg;  
    int offset;
 
    if (envid2env(envid, &e, 1) <0)  
        return -E_BAD_ENV;  
    if (user_mem_check(curenv, ps, sizeof(struct proc), PTE_U|PTE_P) <0)  
        return -E_FAULT;  
    
    *e = ps->env;  
    
    if ((pg=page_lookup(e->env_pgdir, (void *)(USTACKTOP-PGSIZE), NULL))==NULL)  
        return -E_FAULT;  
    
    memmove(page2kva(pg), ps->stack, PGSIZE);      
    
    return 0;  
}  
Example #15
0
bool
copy_string(struct mm_struct *mm, char *dst, const char *src, size_t maxn) {
    size_t alen, part = ROUNDDOWN((uintptr_t)src + PGSIZE, PGSIZE) - (uintptr_t)src;
    while (1) {
        if (part > maxn) {
            part = maxn;
        }
        if (!user_mem_check(mm, (uintptr_t)src, part, 0)) {
            return 0;
        }
        if ((alen = strnlen(src, part)) < part) {
            memcpy(dst, src, alen + 1);
            return 1;
        }
        if (part == maxn) {
            return 0;
        }
        memcpy(dst, src, part);
        dst += part, src += part, maxn -= part;
        part = PGSIZE;
    }
}
Example #16
0
// Send packet
static int
sys_send_packet(void *va, unsigned int size) {
	int perm;
	int offset;
	int r;
	struct Page *p;
	
	perm = PTE_U;
	if(va + size >= (void *)UTOP) {
		cprintf("SYS_send_packet: above UTOP\n");
		return -E_INVAL;
	}
	if((r = user_mem_check(curenv, va, size, perm)) <0) {
		cprintf("SYS_send_packet: %08x\n",r);
		return r;
	}
	if(size > MAX_ETH_FRAME_SIZE)  {
		//should fix the size ...
		cprintf("SYS_send_packet: size is too big!");
		return -E_INVAL; //better return?
	}
	//cprintf("Transmitting.......\n\n\n\n");
	return e100_send_packet(va, size);	
}
Example #17
0
// do_wait - wait one OR any children with PROC_ZOMBIE state, and free memory space of kernel stack
//         - proc struct of this child.
// NOTE: only after do_wait function, all resources of the child proces are free.
int do_wait(int pid, int *code_store)
{
	struct mm_struct *mm = current->mm;
	if (code_store != NULL) {
		if (!user_mem_check(mm, (uintptr_t) code_store, sizeof(int), 1)) {
			return -E_INVAL;
		}
	}

	struct proc_struct *proc, *cproc;
	bool intr_flag, haskid;
repeat:
	cproc = current;
	haskid = 0;
	if (pid != 0) {
		proc = find_proc(pid);
		if (proc != NULL) {
			do {
				if (proc->parent == cproc) {
					haskid = 1;
					if (proc->state == PROC_ZOMBIE) {
						goto found;
					}
					break;
				}
				cproc = next_thread(cproc);
			} while (cproc != current);
		}
	} else {
		do {
			proc = cproc->cptr;
			for (; proc != NULL; proc = proc->optr) {
				haskid = 1;
				if (proc->state == PROC_ZOMBIE) {
					goto found;
				}
			}
			cproc = next_thread(cproc);
		} while (cproc != current);
	}
	if (haskid) {
		current->state = PROC_SLEEPING;
		current->wait_state = WT_CHILD;
		schedule();
		may_killed();
		goto repeat;
	}
	return -E_BAD_PROC;

found:
	if (proc == idleproc || proc == initproc) {
		panic("wait idleproc or initproc.\n");
	}
	int exit_code = proc->exit_code;
	spin_lock_irqsave(&proc_lock, intr_flag);
	{
		unhash_proc(proc);
		remove_links(proc);
	}
	spin_unlock_irqrestore(&proc_lock, intr_flag);
	put_kstack(proc);
	kfree(proc);

	int ret = 0;
	if (code_store != NULL) {
		lock_mm(mm);
		{
			if (!copy_to_user
			    (mm, code_store, &exit_code, sizeof(int))) {
				ret = -E_INVAL;
			}
		}
		unlock_mm(mm);
	}
	return ret;
}
Example #18
0
// debuginfo_eip(addr, info)
//
//	Fill in the 'info' structure with information about the specified
//	instruction address, 'addr'.  Returns 0 if information was found, and
//	negative if not.  But even if it returns negative it has stored some
//	information into '*info'.
//
int
debuginfo_eip(uintptr_t addr, struct Eipdebuginfo *info)
{
	const struct Stab *stabs, *stab_end;
	const char *stabstr, *stabstr_end;
	int lfile, rfile, lfun, rfun, lline, rline;

	// Initialize *info
	info->eip_file = "<unknown>";
	info->eip_line = 0;
	info->eip_fn_name = "<unknown>";
	info->eip_fn_namelen = 9;
	info->eip_fn_addr = addr;
	info->eip_fn_narg = 0;

	// Find the relevant set of stabs
	if (addr >= ULIM) {
		stabs = __STAB_BEGIN__;
		stab_end = __STAB_END__;
		stabstr = __STABSTR_BEGIN__;
		stabstr_end = __STABSTR_END__;
	} else {
		// The user-application linker script, user/user.ld,
		// puts information about the application's stabs (equivalent
		// to __STAB_BEGIN__, __STAB_END__, __STABSTR_BEGIN__, and
		// __STABSTR_END__) in a structure located at virtual address
		// USTABDATA.
		const struct UserStabData *usd = (const struct UserStabData *) USTABDATA;

		// Make sure this memory is valid.
		// Return -1 if it is not.  Hint: Call user_mem_check.
		// LAB 3: Your code here.
		if(user_mem_check(curenv, usd, sizeof(struct UserStabData), PTE_U) < 0)
		{
			return -1;
		}

		stabs = usd->stabs;
		stab_end = usd->stab_end;
		stabstr = usd->stabstr;
		stabstr_end = usd->stabstr_end;

		// Make sure the STABS and string table memory is valid.
		// LAB 3: Your code here.
		if(user_mem_check(curenv, stabs, stab_end-stabs, PTE_U) < 0)
		{
			return -1;
		}
		
		if(user_mem_check(curenv, stabstr, stabstr_end-stabstr, PTE_U) < 0)
		{
			return -1;
		}
	}

	// String table validity checks
	if (stabstr_end <= stabstr || stabstr_end[-1] != 0)
		return -1;

	// Now we find the right stabs that define the function containing
	// 'eip'.  First, we find the basic source file containing 'eip'.
	// Then, we look in that source file for the function.  Then we look
	// for the line number.
	
	// Search the entire set of stabs for the source file (type N_SO).
	lfile = 0;
	rfile = (stab_end - stabs) - 1;
	stab_binsearch(stabs, &lfile, &rfile, N_SO, addr);
	if (lfile == 0)
		return -1;

	// Search within that file's stabs for the function definition
	// (N_FUN).
	lfun = lfile;
	rfun = rfile;
	stab_binsearch(stabs, &lfun, &rfun, N_FUN, addr);

	if (lfun <= rfun) {
		// stabs[lfun] points to the function name
		// in the string table, but check bounds just in case.
		if (stabs[lfun].n_strx < stabstr_end - stabstr)
			info->eip_fn_name = stabstr + stabs[lfun].n_strx;
		info->eip_fn_addr = stabs[lfun].n_value;
		addr -= info->eip_fn_addr;
		// Search within the function definition for the line number.
		lline = lfun;
		rline = rfun;
	} else {
		// Couldn't find function stab!  Maybe we're in an assembly
		// file.  Search the whole file for the line number.
		info->eip_fn_addr = addr;
		lline = lfile;
		rline = rfile;
	}
	// Ignore stuff after the colon.
	info->eip_fn_namelen = strfind(info->eip_fn_name, ':') - info->eip_fn_name;

	
	// Search within [lline, rline] for the line number stab.
	// If found, set info->eip_line to the right line number.
	// If not found, return -1.
	//
	// Hint:
	//	There's a particular stabs type used for line numbers.
	//	Look at the STABS documentation and <inc/stab.h> to find
	//	which one.
	// Your code here.
	stab_binsearch(stabs, &lline, &rline, N_SLINE, addr);
	if (lline <= rline)
	{
		info->eip_line = stabs[lline].n_desc;
	}
	else
	{
		return -1;
	}

	
	// Search backwards from the line number for the relevant filename
	// stab.
	// We can't just use the "lfile" stab because inlined functions
	// can interpolate code from a different file!
	// Such included source files use the N_SOL stab type.
	while (lline >= lfile
	       && stabs[lline].n_type != N_SOL
	       && (stabs[lline].n_type != N_SO || !stabs[lline].n_value))
		lline--;
	if (lline >= lfile && stabs[lline].n_strx < stabstr_end - stabstr)
		info->eip_file = stabstr + stabs[lline].n_strx;


	// Set eip_fn_narg to the number of arguments taken by the function,
	// or 0 if there was no containing function.
	if (lfun < rfun)
		for (lline = lfun + 1;
		     lline < rfun && stabs[lline].n_type == N_PSYM;
		     lline++)
			info->eip_fn_narg++;
	
	return 0;
}
Example #19
0
int
do_linux_waitpid(int pid, int *code_store) {
    struct mm_struct *mm = current->mm;
    if (code_store != NULL) {
        if (!user_mem_check(mm, (uintptr_t)code_store, sizeof(int), 1)) {
            return -E_INVAL;
        }
    }

    struct proc_struct *proc, *cproc;
    bool intr_flag, haskid;
repeat:
    cproc = current;
    haskid = 0;
    if (pid > 0) {
        proc = find_proc(pid);
        if (proc != NULL) {
            do {
                if (proc->parent == cproc) {
                    haskid = 1;
                    if (proc->state == PROC_ZOMBIE) {
                        goto found;
                    }
                    break;
                }
                cproc = next_thread(cproc);
            } while (cproc != current);
        }
    }
    /* we do NOT have group id, so..*/
    else if(pid==0 || pid==-1){ /* pid == 0 */
        do {
            proc = cproc->cptr;
            for (; proc != NULL; proc = proc->optr) {
                haskid = 1;
                if (proc->state == PROC_ZOMBIE) {
                    goto found;
                }
            }
            cproc = next_thread(cproc);
        } while (cproc != current);
    }else{ //pid<-1
      //TODO
      return -E_INVAL;
    }
    if (haskid) {
        current->state = PROC_SLEEPING;
        current->wait_state = WT_CHILD;
        schedule();
        may_killed();
        goto repeat;
    }
    return -E_BAD_PROC;

found:
    if (proc == idleproc || proc == initproc) {
        panic("wait idleproc or initproc.\n");
    }
    int exit_code = proc->exit_code;
    int return_pid = proc->pid;
    local_intr_save(intr_flag);
    {
        unhash_proc(proc);
        remove_links(proc);
    }
    local_intr_restore(intr_flag);
    put_kstack(proc);
    kfree(proc);

    int ret = 0;
    if (code_store != NULL) {
        lock_mm(mm);
        {
            int status = exit_code << 8;
            if (!copy_to_user(mm, code_store, &status, sizeof(int))) {
                ret = -E_INVAL;
            }
        }
        unlock_mm(mm);
    }
    return (ret == 0) ? return_pid : ret;
}