/* * copy arguments onto the stack in the normal way, then copy out * any ELF-like AUX entries used by the dynamic loading scheme. */ int osf1_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp) { struct osf1_exec_emul_arg *emul_arg = pack->ep_emul_arg; struct osf1_auxv ai[OSF1_MAX_AUX_ENTRIES], *a; char *prognameloc, *loadernameloc; size_t len; int error; if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) goto out; a = ai; memset(ai, 0, sizeof ai); prognameloc = *stackp + sizeof ai; if ((error = copyoutstr(emul_arg->exec_name, prognameloc, MAXPATHLEN + 1, NULL)) != 0) goto out; a->a_type = OSF1_AT_EXEC_FILENAME; a->a_un.a_ptr = prognameloc; a++; /* * if there's a loader, push additional auxv entries on the stack. */ if (emul_arg->flags & OSF1_EXEC_EMUL_FLAGS_HAVE_LOADER) { loadernameloc = prognameloc + MAXPATHLEN + 1; if ((error = copyoutstr(emul_arg->loader_name, loadernameloc, MAXPATHLEN + 1, NULL)) != 0) goto out; a->a_type = OSF1_AT_EXEC_LOADER_FILENAME; a->a_un.a_ptr = loadernameloc; a++; a->a_type = OSF1_AT_EXEC_LOADER_FLAGS; a->a_un.a_val = 0; if (pack->ep_vap->va_mode & S_ISUID) a->a_un.a_val |= OSF1_LDR_EXEC_SETUID_F; if (pack->ep_vap->va_mode & S_ISGID) a->a_un.a_val |= OSF1_LDR_EXEC_SETGID_F; if (l->l_proc->p_slflag & PSL_TRACED) a->a_un.a_val |= OSF1_LDR_EXEC_PTRACE_F; a++; } a->a_type = OSF1_AT_NULL; a->a_un.a_val = 0; a++; len = (a - ai) * sizeof(struct osf1_auxv); if ((error = copyout(ai, *stackp, len)) != 0) goto out; *stackp += len; out: exec_free_emul_arg(pack); return error; }
static void * linux_aout_copyargs(struct exec_package *pack, struct ps_strings *arginfo, void *stack, void *argp) { char **cpp = stack; char **stk = stack; char *dp, *sp; size_t len; void *nullp = NULL; int argc = arginfo->ps_nargvstr; int envc = arginfo->ps_nenvstr; if (copyout(&argc, cpp++, sizeof(argc))) return (NULL); /* leave room for envp and argv */ cpp += 2; if (copyout(&cpp, &stk[1], sizeof (cpp))) return (NULL); dp = (char *)(cpp + argc + envc + 2); sp = argp; /* XXX don't copy them out, remap them! */ arginfo->ps_argvstr = cpp; /* remember location of argv for later */ for (; --argc >= 0; sp += len, dp += len) if (copyout(&dp, cpp++, sizeof(dp)) || copyoutstr(sp, dp, ARG_MAX, &len)) return (NULL); if (copyout(&nullp, cpp++, sizeof(nullp))) return (NULL); if (copyout(&cpp, &stk[2], sizeof (cpp))) return (NULL); arginfo->ps_envstr = cpp; /* remember location of envp for later */ for (; --envc >= 0; sp += len, dp += len) if (copyout(&dp, cpp++, sizeof(dp)) || copyoutstr(sp, dp, ARG_MAX, &len)) return (NULL); if (copyout(&nullp, cpp++, sizeof(nullp))) return (NULL); return (cpp); }
int sys__lwp_getname(struct lwp *l, const struct sys__lwp_getname_args *uap, register_t *retval) { /* { syscallarg(lwpid_t) target; syscallarg(char *) name; syscallarg(size_t) len; } */ char name[MAXCOMLEN]; lwpid_t target; proc_t *p; lwp_t *t; if ((target = SCARG(uap, target)) == 0) target = l->l_lid; p = curproc; mutex_enter(p->p_lock); if ((t = lwp_find(p, target)) == NULL) { mutex_exit(p->p_lock); return ESRCH; } lwp_lock(t); if (t->l_name == NULL) name[0] = '\0'; else strcpy(name, t->l_name); lwp_unlock(t); mutex_exit(p->p_lock); return copyoutstr(name, SCARG(uap, name), SCARG(uap, len), NULL); }
/* * Given a memory name, return its associated serial id */ static int mmioctl_get_mem_sid(intptr_t data) { mem_name_t mem_name; void *buf; void *name; size_t name_len; size_t bufsize; int len, err; if ((bufsize = cpu_get_name_bufsize()) == 0) return (ENOTSUP); if ((err = mm_read_mem_name(data, &mem_name)) < 0) return (err); buf = kmem_alloc(bufsize, KM_SLEEP); if (mem_name.m_namelen > 1024) mem_name.m_namelen = 1024; /* cap at 1024 bytes */ name = kmem_alloc(mem_name.m_namelen, KM_SLEEP); if ((err = copyinstr((char *)mem_name.m_name, (char *)name, mem_name.m_namelen, &name_len)) != 0) { kmem_free(buf, bufsize); kmem_free(name, mem_name.m_namelen); return (err); } /* * Call into cpu specific code to do the lookup. */ if ((err = cpu_get_mem_sid(name, buf, bufsize, &len)) != 0) { kmem_free(buf, bufsize); kmem_free(name, mem_name.m_namelen); return (err); } if (len > mem_name.m_sidlen) { kmem_free(buf, bufsize); kmem_free(name, mem_name.m_namelen); return (ENAMETOOLONG); } if (copyoutstr(buf, (char *)mem_name.m_sid, mem_name.m_sidlen, NULL) != 0) { kmem_free(buf, bufsize); kmem_free(name, mem_name.m_namelen); return (EFAULT); } kmem_free(buf, bufsize); kmem_free(name, mem_name.m_namelen); return (0); }
void * copyargs(struct exec_package *pack, struct ps_strings *arginfo, void *stack, void *argp) { char **cpp = stack; char *dp, *sp; size_t len; void *nullp = NULL; long argc = arginfo->ps_nargvstr; int envc = arginfo->ps_nenvstr; if (copyout(&argc, cpp++, sizeof(argc))) return (NULL); dp = (char *) (cpp + argc + envc + 2 + pack->ep_emul->e_arglen); sp = argp; /* XXX don't copy them out, remap them! */ arginfo->ps_argvstr = cpp; /* remember location of argv for later */ for (; --argc >= 0; sp += len, dp += len) if (copyout(&dp, cpp++, sizeof(dp)) || copyoutstr(sp, dp, ARG_MAX, &len)) return (NULL); if (copyout(&nullp, cpp++, sizeof(nullp))) return (NULL); arginfo->ps_envstr = cpp; /* remember location of envp for later */ for (; --envc >= 0; sp += len, dp += len) if (copyout(&dp, cpp++, sizeof(dp)) || copyoutstr(sp, dp, ARG_MAX, &len)) return (NULL); if (copyout(&nullp, cpp++, sizeof(nullp))) return (NULL); return (cpp); }
/* * Given a syndrome, syndrome type, and address return the * associated memory name in the provided data buffer. */ static int mmioctl_get_mem_name(intptr_t data) { mem_name_t mem_name; void *buf; size_t bufsize; int len, err; if ((bufsize = cpu_get_name_bufsize()) == 0) return (ENOTSUP); if ((err = mm_read_mem_name(data, &mem_name)) < 0) return (err); buf = kmem_alloc(bufsize, KM_SLEEP); /* * Call into cpu specific code to do the lookup. */ if ((err = cpu_get_mem_name(mem_name.m_synd, mem_name.m_type, mem_name.m_addr, buf, bufsize, &len)) != 0) { kmem_free(buf, bufsize); return (err); } if (len >= mem_name.m_namelen) { kmem_free(buf, bufsize); return (ENOSPC); } if (copyoutstr(buf, (char *)mem_name.m_name, mem_name.m_namelen, NULL) != 0) { kmem_free(buf, bufsize); return (EFAULT); } kmem_free(buf, bufsize); return (0); }
void run_process(void *ptr, unsigned long num) { (void)num; int result; vaddr_t entrypoint, stackptr; // extract and free passed-in context struct new_process_context *ctxt = (struct new_process_context *)ptr; struct process *proc = ctxt->proc; struct vnode *v = ctxt->executable; int nargs = ctxt->nargs; char **args = ctxt->args; kfree(ctxt); // attach process to thread curthread->t_proc = proc; proc->ps_thread = curthread; // Activate address space as_activate(proc->ps_addrspace); // Load the executable result = load_elf(v, &entrypoint); if (result) { vfs_close(v); kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } // Done with the file now vfs_close(v); // Define the user stack in the address space result = as_define_stack(proc->ps_addrspace, &stackptr); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } // Copy out arguments userptr_t uargv[nargs + 1]; for (int i = 0; i < nargs; i++) { int aligned_length = WORD_ALIGN(strlen(args[i]) + 1); stackptr -= aligned_length; uargv[i] = (userptr_t)stackptr; size_t arg_len; result = copyoutstr(args[i], uargv[i], strlen(args[i]) + 1, &arg_len); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } } uargv[nargs] =(userptr_t)NULL; // Copy out the argv array itself stackptr -= (nargs + 1) * sizeof(userptr_t); result = copyout(uargv, (userptr_t)stackptr, (nargs + 1) * sizeof(userptr_t)); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } enter_new_process(nargs, (userptr_t)stackptr, stackptr, entrypoint); // enter_new_process() does not return panic("enter_new_process returned\n"); }
int sys_execv(const char* program, char** args, int* errno) { int ret; // simple error check // ************* if (program == NULL) { *errno = EFAULT; return -1; } // ************ // copies progname into kernel buffer // *************** char* fname = (char*)kmalloc(PATH_MAX); ret = copyinstr((userptr_t)program, fname, PATH_MAX, NULL); if (ret != 0) { *errno = EFAULT; return -1; } // opens executable // *************** struct vnode* v; ret = vfs_open(fname, O_RDONLY, &v); if (ret != 0) { *errno = ret; return -1; } // ************** // gets argc // ************** int i = 0; while (args[i] != NULL) { i++; } int argc = i; // ************* // copies all arguments into kernel buffer // ***************** char** argv; argv= (char**)kmalloc(PATH_MAX); ret = copyin(args, argv, sizeof(userptr_t)); if (ret != 0) { *errno = EFAULT; return -1; } for(i = 0; i < argc; i++) { argv[i]=(char*)kmalloc(PATH_MAX); ret = copyinstr((userptr_t)args[i],argv[i], PATH_MAX, NULL); if (ret != 0) { *errno = EFAULT; return -1; } } argv[argc] = NULL; // ******************* // error check // ************ if (curthread->t_vmspace != NULL) { as_destroy(curthread->t_vmspace); curthread->t_vmspace = NULL; } // ************** // creates new address space and loads elf into it // ************** curthread->t_vmspace = as_create(); if (curthread->t_vmspace == NULL) { vfs_close(v); *errno = ENOMEM; return -1; } vaddr_t entrypoint,stackptr; as_activate(curthread->t_vmspace); ret = load_elf(v,&entrypoint); if (ret != 0){ vfs_close(v); *errno = ret; return -1; } vfs_close(v); ret = as_define_stack(curthread->t_vmspace,&stackptr); if (ret != 0) { *errno = ret; return -1; } // ******************** // copies arguments into userstack and increments stack ptr // ************** unsigned int pstack[argc]; for (i = argc-1; i >= 0; i--) { int len = strlen(argv[i]) + 1; stackptr -= len; stackptr -= stackptr%4; ret = copyoutstr(argv[i], (userptr_t)stackptr, PATH_MAX, NULL); if (ret != 0) { *errno = EFAULT; return -1; } pstack[i] = stackptr; } pstack[argc] = (int)NULL; for (i = argc-1; i >= 0; i--) { stackptr -= 4; ret = copyout(&pstack[i], (userptr_t)stackptr, sizeof(pstack[i])); if (ret != 0) { *errno = EFAULT; return -1; } } // free unused memory for (i = 0; i < argc; i++) { kfree(argv[i]); } kfree(argv); kfree(fname); // ******************* // enters usermode, should not return // ******************* md_usermode(argc, (userptr_t)stackptr, stackptr, entrypoint); // ****************** // if usermode returns, that is an error // ********** *errno = EINVAL; return -1; // ************ }
int corectl(int subcode, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3) { int error = 0; proc_t *p; refstr_t *rp; size_t size; char *path; core_content_t content = CC_CONTENT_INVALID; struct core_globals *cg; zone_t *zone = curproc->p_zone; cg = zone_getspecific(core_zone_key, zone); ASSERT(cg != NULL); switch (subcode) { case CC_SET_OPTIONS: if ((error = secpolicy_coreadm(CRED())) == 0) { if (arg1 & ~CC_OPTIONS) error = EINVAL; else cg->core_options = (uint32_t)arg1; } break; case CC_GET_OPTIONS: return (cg->core_options); case CC_GET_GLOBAL_PATH: case CC_GET_DEFAULT_PATH: case CC_GET_PROCESS_PATH: if (subcode == CC_GET_GLOBAL_PATH) { mutex_enter(&cg->core_lock); if ((rp = cg->core_file) != NULL) refstr_hold(rp); mutex_exit(&cg->core_lock); } else if (subcode == CC_GET_DEFAULT_PATH) { rp = corectl_path_value(cg->core_default_path); } else { rp = NULL; mutex_enter(&pidlock); if ((p = prfind((pid_t)arg3)) == NULL || p->p_stat == SIDL) { mutex_exit(&pidlock); error = ESRCH; } else { mutex_enter(&p->p_lock); mutex_exit(&pidlock); mutex_enter(&p->p_crlock); if (!hasprocperm(p->p_cred, CRED())) error = EPERM; else if (p->p_corefile != NULL) rp = corectl_path_value(p->p_corefile); mutex_exit(&p->p_crlock); mutex_exit(&p->p_lock); } } if (rp == NULL) { if (error == 0 && suword8((void *)arg1, 0)) error = EFAULT; } else { error = copyoutstr(refstr_value(rp), (char *)arg1, (size_t)arg2, NULL); refstr_rele(rp); } break; case CC_SET_GLOBAL_PATH: case CC_SET_DEFAULT_PATH: if ((error = secpolicy_coreadm(CRED())) != 0) break; /* FALLTHROUGH */ case CC_SET_PROCESS_PATH: if ((size = MIN((size_t)arg2, MAXPATHLEN)) == 0) { error = EINVAL; break; } path = kmem_alloc(size, KM_SLEEP); error = copyinstr((char *)arg1, path, size, NULL); if (error == 0) { if (subcode == CC_SET_PROCESS_PATH) { error = set_proc_info((pid_t)arg3, path, 0); } else if (subcode == CC_SET_DEFAULT_PATH) { corectl_path_set(cg->core_default_path, path); } else if (*path != '\0' && *path != '/') { error = EINVAL; } else { refstr_t *nrp = refstr_alloc(path); mutex_enter(&cg->core_lock); rp = cg->core_file; if (*path == '\0') cg->core_file = NULL; else refstr_hold(cg->core_file = nrp); mutex_exit(&cg->core_lock); if (rp != NULL) refstr_rele(rp); refstr_rele(nrp); } } kmem_free(path, size); break; case CC_SET_GLOBAL_CONTENT: case CC_SET_DEFAULT_CONTENT: if ((error = secpolicy_coreadm(CRED())) != 0) break; /* FALLTHROUGH */ case CC_SET_PROCESS_CONTENT: error = copyin((void *)arg1, &content, sizeof (content)); if (error != 0) break; /* * If any unknown bits are set, don't let this charade * continue. */ if (content & ~CC_CONTENT_ALL) { error = EINVAL; break; } if (subcode == CC_SET_PROCESS_CONTENT) { error = set_proc_info((pid_t)arg2, NULL, content); } else if (subcode == CC_SET_DEFAULT_CONTENT) { corectl_content_set(cg->core_default_content, content); } else { mutex_enter(&cg->core_lock); cg->core_content = content; mutex_exit(&cg->core_lock); } break; case CC_GET_GLOBAL_CONTENT: content = cg->core_content; error = copyout(&content, (void *)arg1, sizeof (content)); break; case CC_GET_DEFAULT_CONTENT: content = corectl_content_value(cg->core_default_content); error = copyout(&content, (void *)arg1, sizeof (content)); break; case CC_GET_PROCESS_CONTENT: mutex_enter(&pidlock); if ((p = prfind((pid_t)arg2)) == NULL || p->p_stat == SIDL) { mutex_exit(&pidlock); error = ESRCH; break; } mutex_enter(&p->p_lock); mutex_exit(&pidlock); mutex_enter(&p->p_crlock); if (!hasprocperm(p->p_cred, CRED())) error = EPERM; else if (p->p_content == NULL) content = CC_CONTENT_NONE; else content = corectl_content_value(p->p_content); mutex_exit(&p->p_crlock); mutex_exit(&p->p_lock); if (error == 0) error = copyout(&content, (void *)arg1, sizeof (content)); break; default: error = EINVAL; break; } if (error) return (set_errno(error)); return (0); }
int sys_execv(char* progname, char** args){ struct vnode *v; vaddr_t stackptr, entrypoint; int result; int string_size = 0; //s_size int kargc = 0; //kargc int err; char ** kernel_args; //kargs size_t check; //tt //CHECKS BEFORE WE BEGIN!! if(args == NULL) return EFAULT; if(progname == NULL) return ENOEXEC; struct addrspace* temp =(struct addrspace*)kmalloc(sizeof(struct addrspace)); if(temp == NULL) return ENOMEM; while(args[kargc] != NULL){ kargc++; } //Copy the address space to the one on the kernel heap. err = as_copy(curthread->t_vmspace, &(temp)); //If there is an error on copy. if(err){ kfree(temp); return ENOMEM; } //make a copy of the kernel args on the heap. kernel_args = (char **)kmalloc((kargc)*sizeof(char*)); if(kernel_args == NULL){ kfree(kernel_args); return ENOMEM; } int i,j; //Transfer the items passed in to the kernel heap array. for(i = 0; i<kargc; i++){ string_size = strlen(args[i]); kernel_args[i] =(char *)kmalloc(string_size * sizeof(char)); //If there is not enough memory... if(kernel_args[i]== NULL){ kfree(temp); for(j =0; j<i; j++){ kfree(kernel_args[j]); } kfree(kernel_args); return ENOMEM; } //If we get here, we have successfully copied the arguments. Copy in now. err = copyinstr(args[i], kernel_args[i], string_size+1, &check); //Check if copyinstr Success/Fail if(err){ for(i = 0; i<kargc; i++){ kfree(kernel_args[i]); } kfree(temp); kfree(kernel_args); return err; } } kernel_args[kargc]= NULL; //NOW, WE FOLLOW THE SAME PROCEDURE AS RUNPROGRAM!! /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { kfree(temp); for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); return result; } //Destroy the old address space, and setup the new one! as_destroy(curthread->t_vmspace); curthread->t_vmspace = NULL; //Setup new vmspace. curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { curthread->t_vmspace = temp; for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); vfs_close(v); return ENOMEM; } /* Activate vmspace */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { as_destroy(curthread->t_vmspace); curthread->t_vmspace = temp; for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); //We now prepare the user stack by placing the arguments on it, like we did in runprogram. result = as_define_stack(curthread->t_vmspace, &stackptr); //If error: if (result) { as_destroy(curthread->t_vmspace); curthread->t_vmspace = temp; for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); return result; } // new addr space user stack vaddr_t new_args[kargc]; int padding; /*place all the strings on the stack*/ for(i = (kargc-1); i>=0 ; i--){ string_size = strlen(kernel_args[i]); padding = ((string_size / 4 ) + 1)*4; stackptr = stackptr - padding; //Do a copyout and check if success/fail err = copyoutstr(kernel_args[i], stackptr, string_size+1, &check); if(err){ return err; } //Success! new_args[i] = stackptr; } new_args[kargc] = NULL; for(i = kargc-1; i>=0 ; i--){ stackptr= stackptr- 4; err = copyout(&(new_args[i]), stackptr, 4); if(err){ return err; } } for(i =0; i<kargc; i++){ kfree(kernel_args[i]); } kfree(temp); kfree(kernel_args); /* Warp to user mode. */ md_usermode(kargc, stackptr, stackptr, entrypoint); }
int sys_execv(const char *progname, char**args) { kprintf("hello world"); struct vnode *v; vaddr_t entrypoint, stackptr; int result; int argc = getargc(args); /* Copy the arguments into the kernel buffer */ char** kbuffer = kmalloc(argc*sizeof(char*)); int i; for (i=0; i<argc; i++) { kbuffer[i] = kmalloc(strlen(args[i])*sizeof(char*)+1); copyinstr(args[i], kbuffer[i], strlen(args[i])*sizeof(char*)+1, NULL); } args = kbuffer; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* This is not the first process, we have to make sure the previous process address space is not NULL. */ assert(curthread->t_vmspace != NULL); /* Destroy the old process address space */ as_destroy(curthread->t_vmspace); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace == NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Free the current process user stack */ kfree(curthread->t_stack); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } /* copy arguments to user space */ char **args_u; /* user space arguments.(array of ptrs to string arguments.*/ /* string length of the arguments */ size_t argstrlen = getlen(argc, args); /* address space for the string arguments value. */ char* arg_str = (char *) stackptr - argstrlen; /* address space for the pointers to string arguments. */ args_u = (char **) arg_str - (argc + 1) * sizeof (char**); /* adjust the address so that its divisable by 4 */ args_u = (int) args_u - (int) args_u % 4; /* copy the arguments to the user address space */ int len; for (i = 0; i < argc; i++) { /* copy a single argument to the user address space */ copyoutstr(args[i], (userptr_t) arg_str, strlen(args[i]) + 1, &len); /* set the user argument to the current argument string pointer */ args_u[i] = arg_str; /* increment the argument pointer to the next argument */ arg_str += (strlen(args[i]) + 1) * sizeof (char); } /* set the n+1th argument to be NULL */ args_u[argc] = NULL; /* set the stackptr to the starting point of args_u and adjust the stack pointer */ stackptr = args_u - sizeof (char**) - ((int)args_u%8); /* Warp to user mode. */ md_usermode(argc, (userptr_t) args_u, stackptr, entrypoint); /*********************** end of A2 stuff *****************/ /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
int sys___execv(char * p_name,char **ar ) { struct vnode *p_vnode; vaddr_t stackptr; vaddr_t entrypoint; int result; size_t copied_length; char *kname; if(p_name==NULL) return EFAULT; if(ar==NULL) return EFAULT; if(p_name == '\0') return ENOEXEC; kname = (char *) kmalloc(sizeof(p_name)); result = copyinstr((const_userptr_t)p_name,kname,NAME_MAX,&copied_length); if(copied_length == 1) { kfree(kname); return EINVAL; } if(result) { kfree(kname); return result; } char **karguments1 = kmalloc(100*sizeof(char*)); result = copyin((const_userptr_t) ar,karguments1,(100*sizeof(char*))); if(result) { kfree(karguments1); kfree(kname); return result; } else kfree(karguments1); char **arguments_kernel =(char **) kmalloc(sizeof(char**)); result = copyin((const_userptr_t) ar,arguments_kernel,(sizeof(char**))); if(result) { kfree(kname); kfree(arguments_kernel); return result; } char **karguments = (char **) kmalloc(sizeof(char **)); int counter=0; size_t actual_lenght1; while(!(ar[counter]==NULL)) { int string_length = strlen(ar[counter])+1; karguments[counter] = (char *) kmalloc(sizeof(char) * string_length); result = copyinstr((const_userptr_t) ar[counter],karguments[counter],string_length,&actual_lenght1); if(result) { kfree(kname); kfree(arguments_kernel); return result; } counter++; } karguments[counter] = NULL; result = vfs_open(kname, O_RDONLY, 0, &p_vnode); if (result) { return result; } as_destroy(curthread->t_addrspace); //Create a new address space. curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(p_vnode); return ENOMEM; } //Activate it. as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(p_vnode, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(p_vnode); return result; } /* Done with the file now. */ vfs_close(p_vnode); //Get the pointer to the stack starting result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } //Now copy the arguments int count =0; char **karray= kmalloc(sizeof(char**)); size_t final_stack=0; while(karguments[count] != NULL) { int string_length = strlen(karguments[count])+1; char *k_des= karguments[count]; int new_length = string_length; if((string_length) % 4 != 0) { while(new_length%4 !=0) { new_length++; } for(int i=string_length;i<=new_length;i++) { k_des[i]= '\0'; } } //Argument aligned by 4 size_t final_length= (size_t)new_length; if(count==0) { final_stack= stackptr- final_length; } else { final_stack= (size_t)karray[count-1]- final_length; } size_t actual_length1; result= copyoutstr(k_des, (userptr_t) (final_stack), final_length, &actual_length1); if(result) { return result; } karray[count]= (char*)(final_stack); count++; } //End of While karray[count]= (char*)NULL; int value= count+1; int arr_length = (value+1)*sizeof(char*); final_stack= (size_t)karray[count-1]- arr_length; result= copyout(karray, (userptr_t) (final_stack),arr_length); if(result) { return result; } /* Warp to user mode. */ enter_new_process(count /*argc*/, (userptr_t)(final_stack) /*userspace addr of argv*/, final_stack, entrypoint); return 0; }
static int shmif_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct shmif_sc *sc = ifp->if_softc; struct ifdrv *ifd; char *path; int s, rv, memfd; s = splnet(); switch (cmd) { case SIOCGLINKSTR: ifd = data; if (sc->sc_backfilelen == 0) { rv = ENOENT; break; } ifd->ifd_len = sc->sc_backfilelen; if (ifd->ifd_cmd == IFLINKSTR_QUERYLEN) { rv = 0; break; } if (ifd->ifd_cmd != 0) { rv = EINVAL; break; } rv = copyoutstr(sc->sc_backfile, ifd->ifd_data, MIN(sc->sc_backfilelen, ifd->ifd_len), NULL); break; case SIOCSLINKSTR: if (ifp->if_flags & IFF_UP) { rv = EBUSY; break; } ifd = data; if (ifd->ifd_cmd == IFLINKSTR_UNSET) { finibackend(sc); rv = 0; break; } else if (ifd->ifd_cmd != 0) { rv = EINVAL; break; } else if (sc->sc_backfile) { rv = EBUSY; break; } if (ifd->ifd_len > MAXPATHLEN) { rv = E2BIG; break; } else if (ifd->ifd_len < 1) { rv = EINVAL; break; } path = kmem_alloc(ifd->ifd_len, KM_SLEEP); rv = copyinstr(ifd->ifd_data, path, ifd->ifd_len, NULL); if (rv) { kmem_free(path, ifd->ifd_len); break; } rv = rumpuser_open(path, RUMPUSER_OPEN_RDWR | RUMPUSER_OPEN_CREATE, &memfd); if (rv) { kmem_free(path, ifd->ifd_len); break; } rv = initbackend(sc, memfd); if (rv) { kmem_free(path, ifd->ifd_len); rumpuser_close(memfd); break; } sc->sc_backfile = path; sc->sc_backfilelen = ifd->ifd_len; break; default: rv = ether_ioctl(ifp, cmd, data); if (rv == ENETRESET) rv = 0; break; } splx(s); return rv; }
STATIC int eval_parameter(connection_t *conn, negotiation_state_t *state, negotiation_parameter_t *par) { uint32_t n = par->val.nval[0]; size_t sz; text_key_t key = par->key; bool sent = (state->kflags[key] & NS_SENT) != 0; state->kflags[key] |= NS_RECEIVED; switch (key) { /* * keys connected to security negotiation */ case K_AuthMethod: if (n) { DEBOUT(("eval_par: AuthMethod nonzero (%d)\n", n)); return ISCSI_STATUS_NEGOTIATION_ERROR; } break; case K_Auth_CHAP_Algorithm: case K_Auth_CHAP_Challenge: case K_Auth_CHAP_Identifier: case K_Auth_CHAP_Name: case K_Auth_CHAP_Response: DEBOUT(("eval_par: Authorization Key in Operational Phase\n")); return ISCSI_STATUS_NEGOTIATION_ERROR; /* * keys we always send */ case K_DataDigest: state->DataDigest = n; if (!sent) set_key_n(state, key, n); break; case K_HeaderDigest: state->HeaderDigest = n; if (!sent) set_key_n(state, key, n); break; case K_ErrorRecoveryLevel: state->ErrorRecoveryLevel = n; if (!sent) set_key_n(state, key, n); break; case K_ImmediateData: state->ImmediateData = n; if (!sent) set_key_n(state, key, n); break; case K_InitialR2T: state->InitialR2T = n; if (!sent) set_key_n(state, key, n); break; case K_MaxRecvDataSegmentLength: state->MaxRecvDataSegmentLength = n; /* this is basically declarative, not negotiated */ /* (each side has its own value) */ break; /* * keys we don't always send, so we may have to reflect the value */ case K_DefaultTime2Retain: state->DefaultTime2Retain = n = min(state->DefaultTime2Retain, n); if (!sent) set_key_n(state, key, n); break; case K_DefaultTime2Wait: state->DefaultTime2Wait = n = min(state->DefaultTime2Wait, n); if (!sent) set_key_n(state, key, n); break; case K_MaxConnections: if (state->MaxConnections) state->MaxConnections = n = min(state->MaxConnections, n); else state->MaxConnections = n; if (!sent) set_key_n(state, key, n); break; case K_MaxOutstandingR2T: state->MaxOutstandingR2T = n; if (!sent) set_key_n(state, key, n); break; case K_FirstBurstLength: state->FirstBurstLength = n; if (!sent) set_key_n(state, key, n); break; case K_MaxBurstLength: state->MaxBurstLength = n; if (!sent) set_key_n(state, key, n); break; case K_IFMarker: case K_OFMarker: /* not (yet) supported */ if (!sent) set_key_n(state, key, 0); break; case K_IFMarkInt: case K_OFMarkInt: /* it's a range, and list_num will be 1, so this will reply "Reject" */ if (!sent) set_key_n(state, key, 0); break; case K_DataPDUInOrder: case K_DataSequenceInOrder: /* values are don't care */ if (!sent) set_key_n(state, key, n); break; case K_NotUnderstood: /* return "NotUnderstood" */ set_key_s(state, key, par->val.sval); break; /* * Declarative keys (no response required) */ case K_TargetAddress: /* ignore for now... */ break; case K_TargetAlias: if (conn->login_par->is_present.TargetAlias) { copyoutstr(par->val.sval, conn->login_par->TargetAlias, ISCSI_STRING_LENGTH - 1, &sz); /* do anything with return code?? */ } break; case K_TargetPortalGroupTag: /* ignore for now... */ break; default: DEBOUT(("eval_par: Invalid parameter type %d\n", par->key)); return ISCSI_STATUS_NEGOTIATION_ERROR; } return 0; }
int runprogram(char *progname, unsigned int argc, char**args) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ #if OPT_A3 curthread->t_vmspace->elf_file = kstrdup(progname); #endif result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } /*********************** stuff for A2 *******************/ char **args_u; /* user space arguments.(array of ptrs to string arguments.*/ /* string length of the arguments */ size_t argstrlen = getlen(argc, args); /* address space for the string arguments value. */ char *arg_str = (char *)stackptr - argstrlen; /* address space for the pointers to string arguments. */ args_u = (char **)arg_str - (argc+1)*sizeof(char**); /* adjust the address so that its divisable by 4 */ args_u = (int)args_u - (int)args_u%4; /* copy the arguments to the user address space */ int len; int i; for (i=0; i<argc; i++){ /* copy a single argument to the user address space */ copyoutstr(args[i], (userptr_t)arg_str, strlen(args[i])+1, &len); /* set the user argument to the current argument string pointer */ args_u[i] = arg_str; /* increment the argument pointer to the next argument */ arg_str += (strlen(args[i])+1)*sizeof(char); } /* set the n+1th argument to be NULL */ args_u[argc] = NULL; /* set the stackptr to the starting point of args_u and adjust the stack pointer */ stackptr = args_u - sizeof(char**) - ((int)args_u%8); /* Warp to user mode. */ md_usermode(argc, (userptr_t) args_u, stackptr, entrypoint); /*********************** end of A2 stuff *****************/ /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
int sys_execv(userptr_t progname, userptr_t args){ /*This function implements the execv functionality*/ size_t get, offset; struct vnode *v; vaddr_t entrypoint, stackptr; userptr_t userdest; int i=0, append_zero, argc=0, result, part=0; char *buf_mem; int n=0; struct addrspace *old_addr = curthread->t_vmspace; char **usr_args = (char**)args; buf_mem = (void *) kmalloc(sizeof(void *)); result = copyin((const_userptr_t)args,buf_mem,4); if (result){ kfree(buf_mem); return result; } lock_acquire(execv_lock); kfree(buf_mem); while(usr_args[argc] != NULL){ argc++; } size_t len_string[argc]; userptr_t user_argv[argc]; char *args_buf = kmalloc(PAGE_SIZE*sizeof(char)); // Check user pointer buf_mem = (char *)kmalloc(1024*sizeof(char)); if (buf_mem == NULL){ result = ENOMEM; kfree(args_buf); } result = copyinstr((const_userptr_t)progname,buf_mem,1024,&get); if (result){ kfree(buf_mem); } //Implementation from runprogram from here /* Open the file. */ result = vfs_open((char *)progname, O_RDONLY, &v); if (result) { kfree(buf_mem); } // Keep old addrspace in case of failure struct addrspace *new_addr = as_create(); if (new_addr == NULL){ result = ENOMEM; vfs_close(v); } while (usr_args[i] != NULL){ result = copyinstr((const_userptr_t)usr_args[i], &args_buf[part], PAGE_SIZE, &len_string[i]); if (result){ as_destroy(new_addr); } part += len_string[i]; i++; } /* Swap addrspace and Activate it*/ curthread->t_vmspace = new_addr; as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); } /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); } // Copy args to new addrspace offset = 0; for (i=argc-1; i>-1; i--){ part -= len_string[i]; // readjust inherited part index append_zero = (4 - (len_string[i]%4) ) % 4; // Word align offset += append_zero; offset += len_string[i]; user_argv[i] = (userptr_t)(stackptr - offset); result = copyoutstr((const char*)&args_buf[part], user_argv[i], len_string[i], &get); if (result){ curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); } } // Copy pointers to argv userdest = user_argv[0] - 4 * (argc+1); stackptr = (vaddr_t)userdest; // Set stack pointer for (i=0; i<argc; i++){ result = copyout((const void *)&user_argv[i], userdest, 4); if (result) curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); userdest += 4; } // Wrap up kfree(args_buf); vfs_close(v); /* Warp to user mode. */ md_usermode(argc, (userptr_t)stackptr, stackptr, entrypoint); lock_release(execv_lock); return EINVAL; }
int sys_execv(const char *prog_path, char **args) { int spl = splhigh(); // the prog_path is in user space, we need to copy it into kernel space if(prog_path == NULL) { return EINVAL; } // frist the program path char* program = (char *) kmalloc(MAX_PATH_LEN * sizeof(char)); int size; int result = copyinstr((const_userptr_t) prog_path, program, MAX_PATH_LEN, &size); if(result) { kfree(program); return EFAULT; } // arguments char** argv = (char**) kmalloc(sizeof(char**)); // char** argv; result = copyin((const_userptr_t)args, argv, sizeof(char **)); if(result) { kfree(program); kfree(argv); return EFAULT; } // count the number of arguments int i = 0; while(args[i] != NULL){ argv[i] = (char*) kmalloc(sizeof(char) * MAX_ARG_LEN); if(copyinstr((const_userptr_t) args[i], argv[i], MAX_ARG_LEN, &size) != 0) { return EFAULT; } i++; } argv[i] = NULL; // runprogram_exev_syscall(program, argv, i); /*********************** runprogram starts*****************/ struct vnode *v; vaddr_t entrypoint, stackptr; result = vfs_open(program, O_RDONLY, &v); if (result) { return result; } // destroy the old addrspace if(curthread->t_vmspace != NULL){ as_destroy(curthread->t_vmspace); curthread->t_vmspace = NULL; } assert(curthread->t_vmspace == NULL); // Create a new address space. curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } // Activate it. as_activate(curthread->t_vmspace); // Load the executable. result = load_elf(v, &entrypoint); // Load an ELF executable user program into the current address space and // returns the entry point (initial PC) for the program in ENTRYPOINT. if (result) { vfs_close(v); return result; } vfs_close(v); result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { // thread_exit destroys curthread->t_vmspace return result; } int narg = i - 1; int j; for(j = 0; j < narg; ++j){ int len = 1 + strlen(argv[j]); len = ROUNDUP(len, 8); stackptr -= len; result = copyoutstr(argv[j],(userptr_t)stackptr, len, &len); if(result){ return result; } argv[j] = (char*)stackptr; } argv[i] = NULL; size_t arg_size = (narg + 1) * sizeof(char*); arg_size = ROUNDUP(arg_size, 8); // align the stackptr to 8 byte aligned stackptr -= arg_size; // stackptr -= stackptr % 8; copyout(argv, stackptr, (narg + 1) * 4); md_usermode(i, stackptr, stackptr, entrypoint); panic("md_usermode returned\n"); return EINVAL; }
static int virtif_ioctl(struct ifnet *ifp, u_long cmd, void *data) { struct virtif_sc *sc = ifp->if_softc; int rv; switch (cmd) { #ifdef RUMP_VIF_LINKSTR struct ifdrv *ifd; size_t linkstrlen; #ifndef RUMP_VIF_LINKSTRMAX #define RUMP_VIF_LINKSTRMAX 4096 #endif case SIOCGLINKSTR: ifd = data; if (!sc->sc_linkstr) { rv = ENOENT; break; } linkstrlen = strlen(sc->sc_linkstr)+1; if (ifd->ifd_cmd == IFLINKSTR_QUERYLEN) { ifd->ifd_len = linkstrlen; rv = 0; break; } if (ifd->ifd_cmd != 0) { rv = ENOTTY; break; } rv = copyoutstr(sc->sc_linkstr, ifd->ifd_data, MIN(ifd->ifd_len,linkstrlen), NULL); break; case SIOCSLINKSTR: if (ifp->if_flags & IFF_UP) { rv = EBUSY; break; } ifd = data; if (ifd->ifd_cmd == IFLINKSTR_UNSET) { panic("unset linkstr not implemented"); } else if (ifd->ifd_cmd != 0) { rv = ENOTTY; break; } else if (sc->sc_linkstr) { rv = EBUSY; break; } if (ifd->ifd_len > RUMP_VIF_LINKSTRMAX) { rv = E2BIG; break; } else if (ifd->ifd_len < 1) { rv = EINVAL; break; } sc->sc_linkstr = kmem_alloc(ifd->ifd_len, KM_SLEEP); rv = copyinstr(ifd->ifd_data, sc->sc_linkstr, ifd->ifd_len, NULL); if (rv) { kmem_free(sc->sc_linkstr, ifd->ifd_len); break; } rv = virtif_create(ifp); if (rv) { kmem_free(sc->sc_linkstr, ifd->ifd_len); } break; #endif /* RUMP_VIF_LINKSTR */ default: if (!sc->sc_linkstr) rv = ENXIO; else rv = ether_ioctl(ifp, cmd, data); if (rv == ENETRESET) rv = 0; break; } return rv; }
/*ARGSUSED*/ int dump_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred, int *rvalp) { uint64_t size; uint64_t dumpsize_in_pages; int error = 0; char *pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP); char uuidbuf[36 + 1]; size_t len; vnode_t *vp; switch (cmd) { case DIOCGETDUMPSIZE: if (dump_conflags & DUMP_ALL) size = ptob((uint64_t)physmem) / DUMP_COMPRESS_RATIO; else { /* * We can't give a good answer for the DUMP_CURPROC * because we won't know which process to use until it * causes a panic. We'll therefore punt and give the * caller the size for the kernel. * * This kernel size equation takes care of the * boot time kernel footprint and also accounts * for availrmem changes due to user explicit locking. * Refer to common/vm/vm_page.c for an explanation * of these counters. */ dumpsize_in_pages = (physinstalled - obp_pages - availrmem - anon_segkp_pages_locked - k_anoninfo.ani_mem_resv - pages_locked - pages_claimed - pages_useclaim); /* * Protect against vm vagaries. */ if (dumpsize_in_pages > (uint64_t)physmem) dumpsize_in_pages = (uint64_t)physmem; size = ptob(dumpsize_in_pages) / DUMP_COMPRESS_RATIO; } if (copyout(&size, (void *)arg, sizeof (size)) < 0) error = EFAULT; break; case DIOCGETCONF: mutex_enter(&dump_lock); *rvalp = dump_conflags; if (dumpvp && !(dumpvp->v_flag & VISSWAP)) *rvalp |= DUMP_EXCL; mutex_exit(&dump_lock); break; case DIOCSETCONF: mutex_enter(&dump_lock); if (arg == DUMP_KERNEL || arg == DUMP_ALL || arg == DUMP_CURPROC) dump_conflags = arg; else error = EINVAL; mutex_exit(&dump_lock); break; case DIOCGETDEV: mutex_enter(&dump_lock); if (dumppath == NULL) { mutex_exit(&dump_lock); error = ENODEV; break; } (void) strcpy(pathbuf, dumppath); mutex_exit(&dump_lock); error = copyoutstr(pathbuf, (void *)arg, MAXPATHLEN, NULL); break; case DIOCSETDEV: case DIOCTRYDEV: if ((error = copyinstr((char *)arg, pathbuf, MAXPATHLEN, NULL)) != 0 || (error = lookupname(pathbuf, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp)) != 0) break; mutex_enter(&dump_lock); if (vp->v_type == VBLK) error = dumpinit(vp, pathbuf, cmd == DIOCTRYDEV); else error = ENOTBLK; mutex_exit(&dump_lock); VN_RELE(vp); break; case DIOCDUMP: mutex_enter(&dump_lock); if (dumpvp == NULL) error = ENODEV; else if (dumpvp->v_flag & VISSWAP) error = EBUSY; else dumpsys(); mutex_exit(&dump_lock); break; case DIOCSETUUID: if ((error = copyinstr((char *)arg, uuidbuf, sizeof (uuidbuf), &len)) != 0) break; if (len != 37) { error = EINVAL; break; } error = dump_set_uuid(uuidbuf); break; case DIOCGETUUID: error = copyoutstr(dump_get_uuid(), (void *)arg, 37, NULL); break; default: error = ENXIO; } kmem_free(pathbuf, MAXPATHLEN); return (error); }
int runprogram(char *progname, char** args, int num) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; int s_size = 0; int kargc = num; int i=0, err; size_t tt; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } if(args!=NULL) { vaddr_t new_args[kargc]; vaddr_t new_argv; int w_size; /*word alligned size of string*/ /*place all the strings on the stack*/ /*carefully ignore the first element because contains the program name*/ for(i = (kargc-1); i>=0 ; i--) { s_size = strlen(args[i]); w_size = ((s_size / 4 ) + 1)*4; stackptr -= w_size; err = copyoutstr(args[i], stackptr, s_size+1, &tt); if(err!=0){ kprintf("2: err %d, the official length is %d, the given length is %d \n ", err, tt, s_size+1); return err; } new_args[i] = stackptr; } kprintf("finished all my strlens \n"); /*place all the pointers to the strings on the stack*/ new_args[kargc] = NULL; for(i = kargc; i>=0 ; i--){ stackptr-= 4; err = copyout(&(new_args[i]), stackptr, 4); if(err!=0){ kprintf("3: err %d \n ", err); return err; } } /* Warp to user mode. */ md_usermode(kargc, stackptr, stackptr, entrypoint); } else md_usermode(0, NULL, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, int argc, char** args) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } /* Initialize an array of pointers that stores the pointer to the * string arguments in the user stack */ char** argv = (char **)kmalloc((argc + 1) * sizeof(char*)); if (argv == NULL) { return ENOMEM; } argv[argc] = 0; int i; size_t actual; int total = 0; /* Copy string arguments from kernel memory onto the user stack, * and store the user pointer to the argument in argv */ for (i = argc - 1; i >= 0; i--) { int len = strlen(args[i]) + 1; total = total + len; stackptr = stackptr - len; copyoutstr(args[i], (userptr_t)stackptr, len, &actual); argv[i] = (char *)stackptr; } /* Add any necessary padding to the user stack */ int padding = 4 - (total % 4); if (padding) { stackptr = stackptr - padding; } /* Copy the array of user pointers argv onto the user stack */ for (i = argc; i >= 0; i--) { stackptr = stackptr - 4; copyout(&argv[i], (userptr_t)stackptr, 4); } kfree(argv); /* Warp to user mode. */ enter_new_process(argc, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **argv, unsigned long argc) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; pid_t pidRetVal; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create filetable for process*/ curthread->ft = create_process_filetable(); if(curthread->ft == NULL) { vfs_close(v); return ENOMEM; } /* Initialize STDIN, STDOUT, STDERR */ struct ft_node* standardIn = create_ft_node(); struct ft_node* standardOut = create_ft_node(); struct ft_node* standardErr = create_ft_node(); char console1[] = "con:"; result = vfs_open(console1, O_RDONLY, &standardIn->v); if(result) { kprintf("Cannot open STDIN\n"); vfs_close(v); return result; } standardIn->mode = O_RDONLY; array_add(curthread->ft->file_descriptors, standardIn); char console2[] = "con:"; result = vfs_open(console2, O_WRONLY, &standardOut->v); if(result) { kprintf("Cannot open STDOUT\n"); vfs_close(v); return result; } standardOut->mode = O_WRONLY; array_add(curthread->ft->file_descriptors, standardOut); char console3[] = "con:"; result = vfs_open(console3, O_WRONLY, &standardErr->v); if(result) { kprintf("Cannot open STDERR\n"); vfs_close(v); return result; } standardErr->mode = O_WRONLY; array_add(curthread->ft->file_descriptors, standardErr); /* Allocate initial PID for this first program */ result = allocate_pid(&pidRetVal); if(result) { kprintf("Could not allocate PID\n"); vfs_close(v); return result; } curthread->PID = pidRetVal; ((struct p_node *)array_getguy(pid_table, curthread->PID))->is_interested = 0; /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ vfs_close(v); return result; } //kprintf("finished loadelf in runprog\n"); /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } vaddr_t stackptrv[argc+1]; int i; size_t actual; for(i = argc-1; i >= 0; i--) { int len = strlen(argv[i]); len++; int padding = len % 4; stackptr -= len + (4 - padding); result = copyoutstr(argv[i], (userptr_t)stackptr, len, &actual); if(result) { return result; } stackptrv[i] = stackptr; } stackptrv[argc] = 0; for(i = argc; i >= 0; i--) { stackptr -= sizeof(vaddr_t); result = copyout(&stackptrv[i], (userptr_t)stackptr, sizeof(vaddr_t)); if(result) { return result; } } //kprintf("Before usernmode\n"); /* Warp to user mode. */ md_usermode(argc /*argc*/, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
runprogram(char *progname) #endif { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } #if OPT_A2 // How much space do we need for args in stack? // We need space for each pointer (4argc) // We need space for each character, including NULL termination, plus // padding to make multiples of 4 int stringSpace = 0; for (unsigned long i = 0; i < argc; i++) { stringSpace += strlen(argv[i]) + 1; } // Align stack pointer to an 8-byte alignment while ((stackptr - (4*argc) - stringSpace) % 8 != 0) { stackptr--; } // Use a vaddr array to track the addresses the strings end up in // One bigger than argc to also have the pointer to the final NULL // value vaddr_t stringAddr[argc+1]; // Copy argument strings onto stack // Array must end with NULL pointer, so do that first stackptr -= 4; copyout((void *)NULL, (userptr_t)stackptr, (size_t)4); stringAddr[argc] = stackptr; for (int i = argc-1; i >= 0; i--) { stackptr -= strlen(argv[i]) + 1; while (stackptr % 4 != 0) stackptr--; copyoutstr(argv[i], (userptr_t)stackptr, (size_t)strlen(argv[i]), NULL); stringAddr[i] = stackptr; } // Now use the stored addresses of the string to add the appropriate // pointers to the stack for (int i = argc; i >= 0; i--) { stackptr -= sizeof(vaddr_t); copyout(&stringAddr[i], (userptr_t)stackptr, sizeof(vaddr_t)); } /* Warp to user mode. */ enter_new_process(argc /*argc*/, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); #else /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); #endif /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int runprogram(char *progname, unsigned long argc, char **argv) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ #if OPT_A3 as = as_create(progname); #else as = as_create(); #endif if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); // find the stack pointer if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } //add stuff stackptr = stackptr - (argc + 1)*sizeof(vaddr_t); //subtract number of arguments + 1 (space for pointers) unsigned long i; unsigned int len; unsigned int len2; char **buf = (char **)stackptr; // argv for(i=0; i<argc; i++){ len = (strlen(argv[i])+1)*(sizeof(char)); // first str length + null char stackptr = stackptr - len; // adjust stack pointer for length of str buf[i] = (char*)stackptr; // assign pointer to argv[i] copyoutstr((void *)argv[i],(userptr_t)buf[i],len,&len2); // copy to userstack } unsigned int remainder = stackptr % 8; if(remainder != 0){ stackptr = stackptr - remainder; } // pass arguments to user program /* Warp to user mode. */ enter_new_process(argc, (userptr_t)buf /*userspace addr of argv*/, stackptr, entrypoint); // stores into trap->a0 as argc // stores trap->a1 as argv // sets stack pointer /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char** args, size_t nargs) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; int argc = 0; while(args[argc] != NULL) { argc++; } /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } #if OPT_A2 while(stackptr %8 != 0) stackptr--; vaddr_t argptr[argc + 1]; for (int i = argc - 1; i >= 0; i--) { stackptr -= strlen(args[i]) + 1; result = copyoutstr(args[i], (userptr_t) stackptr, strlen(args[i]) + 1, NULL); if(result) return result; argptr[i] = stackptr; } while(stackptr % 4 != 0) stackptr--; //int hack = (int) nargs; argptr[nargs] = 0; for (int i = argc; i >= 0; i--) { stackptr -= ROUNDUP(sizeof(vaddr_t), 4); result = copyout(&argptr[i], (userptr_t) stackptr, sizeof(vaddr_t)); if(result) return result; } #endif /* Warp to user mode. */ enter_new_process(nargs /*argc*/, (userptr_t) stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(char *progname, char **args, int *err) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Validations */ if (progname == NULL) { *err = EFAULT; return -1; } if (args == NULL || (int *)args == (int *)0x40000000 || (int *)args == (int *)0x80000000) { *err = EFAULT; return -1; } /* Count number of arguments and total size of input */ int args_count = 0; for (;args_count < ARG_MAX && args[args_count] != NULL; args_count++); if (args_count > ARG_MAX) { *err = E2BIG; return -1; } /* Copy File name */ char *progname_copy = (char *) kmalloc(sizeof(char) * NAME_MAX); size_t actual = 0; result = copyinstr((userptr_t)progname, progname_copy, NAME_MAX, &actual); if (result) { kfree(progname_copy); *err = result; return -1; } if (strlen(progname_copy) == 0) { kfree(progname_copy); *err = EINVAL; return -1; } /* Allocate Kernel Memory for arguments */ char **args_copy = (char **) kmalloc(sizeof(char *) * args_count); int c_args_count = 0, arg_size = 0, padded_size = 0; for (;c_args_count < args_count; c_args_count++) { if ((int *)args[c_args_count] == (int *)0x40000000 || (int *)args[c_args_count] == (int *)0x80000000) { kfree(progname_copy); *err = EFAULT; return -1; } } c_args_count = 0; /* Calculate total length accounting for padding */ for (;c_args_count < args_count; c_args_count++) { arg_size = strlen(args[c_args_count]) + 1; args_copy[c_args_count] = (char *) kmalloc(sizeof(char) * arg_size); copyinstr((userptr_t)args[c_args_count], args_copy[c_args_count], arg_size, &actual); padded_size += arg_size; if (padded_size % 4) { padded_size += (4 - (padded_size % 4)) % 4; } } /* Open the file. */ result = vfs_open(progname_copy, O_RDONLY, 0, &v); if (result) { kfree(progname_copy); *err = result; return -1; } /* Destroy the current process's address space to create a new one. */ as = curproc->p_addrspace; curproc->p_addrspace = NULL; as_destroy(as); /* We should be a new process. */ KASSERT(proc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as == NULL) { kfree(progname_copy); vfs_close(v); *err = ENOMEM; return -1; } /* Switch to it and activate it. */ proc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ kfree(progname_copy); vfs_close(v); *err = result; return -1; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ kfree(progname_copy); *err = result; return -1; } stackptr -= padded_size; char **arg_address = (char **) kmalloc(sizeof(char *) * args_count + 1); /* Copy arguments into user stack */ for(int i = 0; i < args_count; i++) { arg_size = strlen(args_copy[i]) + 1; if (arg_size % 4) { arg_size += (4 - arg_size % 4) % 4; } /* Store address of arguments */ arg_address[i] = (char *)stackptr; copyoutstr(args_copy[i], (userptr_t)stackptr, arg_size, &actual); stackptr += arg_size; } /* Add Null Pointer at the end */ arg_address[args_count] = 0; stackptr -= padded_size; stackptr -= (args_count + 1) * sizeof(char *); /* Copy address locations into user stack*/ for (int i = 0; i < args_count + 1; i++) { copyout((arg_address + i), (userptr_t)stackptr, sizeof(char *)); stackptr += sizeof(char *); } /* Reset pointer to start of the stack */ stackptr -= ((args_count + 1) * sizeof(char *)); kfree(progname_copy); c_args_count = 0; for (;c_args_count < args_count; c_args_count++) { kfree(args_copy[c_args_count]); } kfree(args_copy); kfree(arg_address); /* Warp to user mode. */ enter_new_process(args_count /*argc*/, (userptr_t) stackptr /*userspace addr of argv*/, (userptr_t) stackptr /*userspace addr of environment*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); *err = EINVAL; return -1; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **args, int argc) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; // Variables for argument passing int i, pad; size_t offset, get; userptr_t userdest; size_t got[argc]; userptr_t user_argv[argc]; // Count length of each arg i = 0; for (i=0; i<argc; i++){ got[i] = strlen(args[i]) + 1; // Need +1 to account for /0 } /* We enforce that the kernel is only allowed to start ONE user process * directly through runprogram with PID_MIN as its pid. Thereafter any * new user process needs to be forked from existing ones. */ KASSERT(process_table[PID_MIN] == NULL); curthread->pid = PID_MIN; stdio_init(); /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } // Copy args to new addrspace offset = 0; for (i=argc-1; i>-1; i--){ pad = (4 - (got[i]%4) ) % 4; // Word align offset += pad; offset += got[i]; user_argv[i] = (userptr_t)(stackptr - offset); result = copyoutstr((const char*)args[i], user_argv[i], got[i], &get); if (result){ return result; } } // Copy pointers to argv userdest = user_argv[0] - 4 * (argc+1); stackptr = (vaddr_t)userdest; // Set stack pointer for (i=0; i<argc; i++){ result = copyout((const void *)&user_argv[i], userdest, 4); if (result){ return result; } userdest += 4; } /* Warp to user mode. */ enter_new_process(argc, (userptr_t)stackptr, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Copy arguments onto the stack in the normal way, but add some * extra information in case of dynamic binding. */ int exec_darwin_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp) { struct exec_macho_emul_arg *emea; struct exec_macho_object_header *macho_hdr; struct proc *p = l->l_proc; char **cpp, *dp, *sp, *progname; size_t len; void *nullp = NULL; long argc, envc; int error; /* * Prepare the comm pages */ if ((error = darwin_commpage_map(p)) != 0) return error; /* * Set up the stack */ *stackp = (char *)(((unsigned long)*stackp - 1) & ~0xfUL); emea = (struct exec_macho_emul_arg *)pack->ep_emul_arg; if (emea->dynamic == 1) { macho_hdr = (struct exec_macho_object_header *)emea->macho_hdr; error = copyout(&macho_hdr, *stackp, sizeof(macho_hdr)); if (error != 0) return error; *stackp += sizeof(macho_hdr); } cpp = (char **)*stackp; argc = arginfo->ps_nargvstr; envc = arginfo->ps_nenvstr; if ((error = copyout(&argc, cpp++, sizeof(argc))) != 0) return error; dp = (char *) (cpp + argc + envc + 4); if ((error = copyoutstr(emea->filename, dp, (ARG_MAX < MAXPATHLEN) ? ARG_MAX : MAXPATHLEN, &len)) != 0) return error; progname = dp; dp += len; sp = argp; arginfo->ps_argvstr = cpp; /* remember location of argv for later */ for (; --argc >= 0; sp += len, dp += len) if ((error = copyout(&dp, cpp++, sizeof(dp))) != 0 || (error = copyoutstr(sp, dp, ARG_MAX, &len)) != 0) return error; if ((error = copyout(&nullp, cpp++, sizeof(nullp))) != 0) return error; arginfo->ps_envstr = cpp; /* remember location of envp for later */ for (; --envc >= 0; sp += len, dp += len) if ((error = copyout(&dp, cpp++, sizeof(dp))) != 0 || (error = copyoutstr(sp, dp, ARG_MAX, &len)) != 0) return error; if ((error = copyout(&nullp, cpp++, sizeof(nullp))) != 0) return error; if ((error = copyout(&progname, cpp++, sizeof(progname))) != 0) return error; if ((error = copyout(&nullp, cpp++, sizeof(nullp))) != 0) return error; *stackp = (char *)cpp; /* We don't need this anymore */ free(pack->ep_emul_arg, M_TEMP); pack->ep_emul_arg = NULL; return 0; }
runprogram(char *progname) #endif { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; //kprintf("bla0\n"); /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } //kprintf("bla1\n"); /* We should be a new process. */ KASSERT(curproc_getas() == NULL); //kprintf("bla2\n"); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } //kprintf("bla3\n"); /* Switch to it and activate it. */ curproc_setas(as); as_activate(); //kprintf("bla4\n"); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } //kprintf("bla5\n"); /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } #if OPT_A2 //kprintf("bla6\n"); if(args == NULL){ return EFAULT; } // copy args to user size_t len = sizeof(char *) * (num + 1); char **copyargs = kmalloc(len); for(unsigned long int i = 0; i < num; i++){ len = strlen(args[i]) + 1; stackptr = stackptr - ROUNDUP(len, 8);//? limit or valid stackptr //new result = copyoutstr(args[i], (userptr_t)stackptr, len, NULL);//new if(result){ kfree(copyargs); return result; } copyargs[i] = (char *)stackptr; } copyargs[num] = NULL; // copy arr len = sizeof(char *) * (num + 1); stackptr = stackptr - ROUNDUP(len, 8); result = copyout(copyargs, (userptr_t)stackptr, len); kfree(copyargs); if(result){ return result; } userptr_t stackk = (userptr_t)stackptr; enter_new_process(num /*argc*/, stackk /*userspace addr of argv*/, stackptr, entrypoint); #else /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); #endif /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
void mips_syscall(struct trapframe *tf) { int callno; int32_t retval; int err; int s,act; char *d; //convert user level pointers to user level pointers assert(curspl==0); callno = tf->tf_v0; /* * Initialize retval to 0. Many of the system calls don't * really return a value, just 0 for success and -1 on * error. Since retval is the value returned on success, * initialize it to 0 by default; thus it's not necessary to * deal with it except for calls that return other values, * like write. */ retval = 0; switch (callno) { case SYS_reboot: err = sys_reboot(tf->tf_a0); break; // syscall.h has all the callno numbers for differnt syscalls case SYS_fork: err = sysfork(&retval,tf); break; case SYS_getpid : err = sysgetpid(&retval); break; case SYS_write : s=splhigh(); char *c = (char *)tf->tf_a1; kprintf("%c",*c); retval = 1; splx(s); err=0; break; case SYS_read : d = (char *)kmalloc(sizeof(char)*((tf->tf_a2)+1)); //char *b; //b = (char *)kmalloc(sizeof(char)*((tf->tf_a2)+1)); d[0] = getch(); d[1] ='\0'; putch(d[0]); putch('\n'); s=splhigh(); copyoutstr(d,(userptr_t)(tf->tf_a1),(tf->tf_a2)+1,&act); //DEBUG(1,"actual: %d tf size: %d\n",act,(tf->tf_a2)+1); //copyinstr((tf->tf_a1),b,(tf->tf_a2)+1,&act); //DEBUG(1,"copied bacl:%s\n",b); err=0; kfree(d); retval = strlen(d)+1; splx(s); break; case SYS_waitpid : err = syswaitpid(tf->tf_a0,(int *)tf->tf_a1,tf->tf_a2,&retval); //syswaitpid(&retval); break; case SYS__exit : err = sysexit(&retval,tf); break; case SYS_execv: err=sysexecv((char*)tf->tf_a0, (char**)tf->tf_a1); break; case SYS_sbrk: err = sys_sbrk((int)tf->tf_a0, &retval); break; default: kprintf("Unknown syscall %d\n", callno); err = ENOSYS; break; } if (err) { /* * Return the error code. This gets converted at * userlevel to a return value of -1 and the error * code in errno. */ tf->tf_v0 = err; tf->tf_a3 = 1; /* signal an error */ } else { /* Success. */ tf->tf_v0 = retval; tf->tf_a3 = 0; /* signal no error */ } /* * Now, advance the program counter, to avoid restarting * the syscall over and over again. */ tf->tf_epc += 4; /* Make sure the syscall code didn't forget to lower spl */ assert(curspl==0); }