Changeset View
Standalone View
sys/kern/kern_exec.c
Show First 20 Lines • Show All 235 Lines • ▼ Show 20 Lines | ||||||||||
/* | /* | |||||||||
* Each of the items is a pointer to a `const struct execsw', hence the | * Each of the items is a pointer to a `const struct execsw', hence the | |||||||||
* double pointer here. | * double pointer here. | |||||||||
*/ | */ | |||||||||
static const struct execsw **execsw; | static const struct execsw **execsw; | |||||||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | |||||||||
struct execve_args { | struct execve_args { | |||||||||
char *fname; | char *fname; | |||||||||
char **argv; | char **argv; | |||||||||
char **envv; | char **envv; | |||||||||
}; | }; | |||||||||
#endif | #endif | |||||||||
int | int | |||||||||
sys_execve(struct thread *td, struct execve_args *uap) | sys_execve(struct thread *td, struct execve_args *uap) | |||||||||
{ | { | |||||||||
struct image_args args; | struct image_args args; | |||||||||
struct vmspace *oldvmspace; | struct vmspace *oldvmspace; | |||||||||
▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | do_execve(struct thread *td, struct image_args *args, struct mac *mac_p, | |||||||||
struct image_params image_params, *imgp; | struct image_params image_params, *imgp; | |||||||||
struct vattr attr; | struct vattr attr; | |||||||||
int (*img_first)(struct image_params *); | int (*img_first)(struct image_params *); | |||||||||
struct pargs *oldargs = NULL, *newargs = NULL; | struct pargs *oldargs = NULL, *newargs = NULL; | |||||||||
struct sigacts *oldsigacts = NULL, *newsigacts = NULL; | struct sigacts *oldsigacts = NULL, *newsigacts = NULL; | |||||||||
#ifdef KTRACE | #ifdef KTRACE | |||||||||
struct ktr_io_params *kiop; | struct ktr_io_params *kiop; | |||||||||
#endif | #endif | |||||||||
struct vnode *oldtextvp = NULL, *newtextvp; | struct vnode *oldtextvp, *newtextvp; | |||||||||
int credential_changing; | struct vnode *oldtextdvp, *newtextdvp; | |||||||||
char *oldbinname, *newbinname; | ||||||||||
bool credential_changing; | ||||||||||
#ifdef MAC | #ifdef MAC | |||||||||
struct label *interpvplabel = NULL; | struct label *interpvplabel = NULL; | |||||||||
int will_transition; | bool will_transition; | |||||||||
#endif | #endif | |||||||||
#ifdef HWPMC_HOOKS | #ifdef HWPMC_HOOKS | |||||||||
struct pmckern_procexec pe; | struct pmckern_procexec pe; | |||||||||
#endif | #endif | |||||||||
int error, i, orig_osrel; | int error, i, orig_osrel; | |||||||||
uint32_t orig_fctl0; | uint32_t orig_fctl0; | |||||||||
Elf_Brandinfo *orig_brandinfo; | Elf_Brandinfo *orig_brandinfo; | |||||||||
size_t freepath_size; | ||||||||||
static const char fexecv_proc_title[] = "(fexecv)"; | static const char fexecv_proc_title[] = "(fexecv)"; | |||||||||
imgp = &image_params; | imgp = &image_params; | |||||||||
oldtextvp = oldtextdvp = NULL; | ||||||||||
newtextvp = newtextdvp = NULL; | ||||||||||
markj: Initializing oldtextdvp twice. I think it is technically safe to leave newtextvp uninitialized. | ||||||||||
Done Inline ActionsPerhaps yes, but following the mix of success/failure paths on the function exit is risky. kib: Perhaps yes, but following the mix of success/failure paths on the function exit is risky. | ||||||||||
Done Inline ActionsI prefer the explicit initialization as well. I just wasn't sure if it was intentional. markj: I prefer the explicit initialization as well. I just wasn't sure if it was intentional. | ||||||||||
newbinname = oldbinname = NULL; | ||||||||||
#ifdef KTRACE | #ifdef KTRACE | |||||||||
kiop = NULL; | kiop = NULL; | |||||||||
#endif | #endif | |||||||||
/* | /* | |||||||||
* Lock the process and set the P_INEXEC flag to indicate that | * Lock the process and set the P_INEXEC flag to indicate that | |||||||||
* it should be left alone until we're done here. This is | * it should be left alone until we're done here. This is | |||||||||
* necessary to avoid race conditions - e.g. in ptrace() - | * necessary to avoid race conditions - e.g. in ptrace() - | |||||||||
Show All 28 Lines | #endif | |||||||||
* Translate the file name. namei() returns a vnode pointer | * Translate the file name. namei() returns a vnode pointer | |||||||||
* in ni_vp among other things. | * in ni_vp among other things. | |||||||||
* | * | |||||||||
* XXXAUDIT: It would be desirable to also audit the name of the | * XXXAUDIT: It would be desirable to also audit the name of the | |||||||||
* interpreter if this is an interpreted binary. | * interpreter if this is an interpreted binary. | |||||||||
*/ | */ | |||||||||
if (args->fname != NULL) { | if (args->fname != NULL) { | |||||||||
NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW | | NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW | | |||||||||
SAVENAME | AUDITVNODE1, UIO_SYSSPACE, args->fname, td); | SAVENAME | AUDITVNODE1 | WANTPARENT, | |||||||||
UIO_SYSSPACE, args->fname, td); | ||||||||||
} | } | |||||||||
SDT_PROBE1(proc, , , exec, args->fname); | SDT_PROBE1(proc, , , exec, args->fname); | |||||||||
interpret: | interpret: | |||||||||
if (args->fname != NULL) { | if (args->fname != NULL) { | |||||||||
#ifdef CAPABILITY_MODE | #ifdef CAPABILITY_MODE | |||||||||
/* | /* | |||||||||
* While capability mode can't reach this point via direct | * While capability mode can't reach this point via direct | |||||||||
* path arguments to execve(), we also don't allow | * path arguments to execve(), we also don't allow | |||||||||
* interpreters to be used in capability mode (for now). | * interpreters to be used in capability mode (for now). | |||||||||
* Catch indirect lookups and return a permissions error. | * Catch indirect lookups and return a permissions error. | |||||||||
*/ | */ | |||||||||
if (IN_CAPABILITY_MODE(td)) { | if (IN_CAPABILITY_MODE(td)) { | |||||||||
error = ECAPMODE; | error = ECAPMODE; | |||||||||
goto exec_fail; | goto exec_fail; | |||||||||
} | } | |||||||||
#endif | #endif | |||||||||
error = namei(&nd); | error = namei(&nd); | |||||||||
if (error) | if (error) | |||||||||
goto exec_fail; | goto exec_fail; | |||||||||
newtextvp = nd.ni_vp; | newtextvp = nd.ni_vp; | |||||||||
newtextdvp = nd.ni_dvp; | ||||||||||
nd.ni_dvp = NULL; | ||||||||||
newbinname = malloc(nd.ni_cnd.cn_namelen + 1, M_PARGS, | ||||||||||
M_WAITOK); | ||||||||||
memcpy(newbinname, nd.ni_cnd.cn_nameptr, nd.ni_cnd.cn_namelen); | ||||||||||
newbinname[nd.ni_cnd.cn_namelen] = '\0'; | ||||||||||
imgp->vp = newtextvp; | imgp->vp = newtextvp; | |||||||||
} else { | } else { | |||||||||
AUDIT_ARG_FD(args->fd); | AUDIT_ARG_FD(args->fd); | |||||||||
/* | /* | |||||||||
* Descriptors opened only with O_EXEC or O_RDONLY are allowed. | * Descriptors opened only with O_EXEC or O_RDONLY are allowed. | |||||||||
*/ | */ | |||||||||
error = fgetvp_exec(td, args->fd, &cap_fexecve_rights, &newtextvp); | error = fgetvp_exec(td, args->fd, &cap_fexecve_rights, | |||||||||
&newtextvp); | ||||||||||
if (error) | if (error) | |||||||||
goto exec_fail; | goto exec_fail; | |||||||||
vn_lock(newtextvp, LK_SHARED | LK_RETRY); | vn_lock(newtextvp, LK_SHARED | LK_RETRY); | |||||||||
AUDIT_ARG_VNODE1(newtextvp); | AUDIT_ARG_VNODE1(newtextvp); | |||||||||
imgp->vp = newtextvp; | imgp->vp = newtextvp; | |||||||||
} | } | |||||||||
/* | /* | |||||||||
Show All 31 Lines | #endif | |||||||||
* environment in mind, and will therefore almost certainly operate | * environment in mind, and will therefore almost certainly operate | |||||||||
* incorrectly. In principle there's no reason that setugid | * incorrectly. In principle there's no reason that setugid | |||||||||
* applications might not be useful in capability mode, so we may want | * applications might not be useful in capability mode, so we may want | |||||||||
* to reconsider this conservative design choice in the future. | * to reconsider this conservative design choice in the future. | |||||||||
* | * | |||||||||
* XXXMAC: For the time being, use NOSUID to also prohibit | * XXXMAC: For the time being, use NOSUID to also prohibit | |||||||||
* transitions on the file system. | * transitions on the file system. | |||||||||
*/ | */ | |||||||||
credential_changing = 0; | credential_changing = false; | |||||||||
credential_changing |= (attr.va_mode & S_ISUID) && | credential_changing |= (attr.va_mode & S_ISUID) && | |||||||||
oldcred->cr_uid != attr.va_uid; | oldcred->cr_uid != attr.va_uid; | |||||||||
credential_changing |= (attr.va_mode & S_ISGID) && | credential_changing |= (attr.va_mode & S_ISGID) && | |||||||||
oldcred->cr_gid != attr.va_gid; | oldcred->cr_gid != attr.va_gid; | |||||||||
#ifdef MAC | #ifdef MAC | |||||||||
will_transition = mac_vnode_execve_will_transition(oldcred, imgp->vp, | will_transition = mac_vnode_execve_will_transition(oldcred, imgp->vp, | |||||||||
interpvplabel, imgp); | interpvplabel, imgp) != 0; | |||||||||
credential_changing |= will_transition; | credential_changing |= will_transition; | |||||||||
#endif | #endif | |||||||||
/* Don't inherit PROC_PDEATHSIG_CTL value if setuid/setgid. */ | /* Don't inherit PROC_PDEATHSIG_CTL value if setuid/setgid. */ | |||||||||
if (credential_changing) | if (credential_changing) | |||||||||
imgp->proc->p_pdeathsig = 0; | imgp->proc->p_pdeathsig = 0; | |||||||||
if (credential_changing && | if (credential_changing && | |||||||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | if (oldcred->cr_svuid != oldcred->cr_uid || | |||||||||
change_svgid(imgp->newcred, imgp->newcred->cr_gid); | change_svgid(imgp->newcred, imgp->newcred->cr_gid); | |||||||||
} | } | |||||||||
} | } | |||||||||
/* The new credentials are installed into the process later. */ | /* The new credentials are installed into the process later. */ | |||||||||
/* | /* | |||||||||
* Do the best to calculate the full path to the image file. | * Do the best to calculate the full path to the image file. | |||||||||
*/ | */ | |||||||||
if (args->fname != NULL && args->fname[0] == '/') | if (args->fname != NULL) { | |||||||||
if (args->fname[0] == '/') { | ||||||||||
imgp->execpath = args->fname; | imgp->execpath = args->fname; | |||||||||
else { | } else { | |||||||||
VOP_UNLOCK(imgp->vp); | VOP_UNLOCK(imgp->vp); | |||||||||
if (vn_fullpath(imgp->vp, &imgp->execpath, &imgp->freepath) != 0) | freepath_size = MAXPATHLEN; | |||||||||
if (vn_fullpath_hardlink(&nd, &imgp->execpath, | ||||||||||
&imgp->freepath, &freepath_size) != 0) | ||||||||||
imgp->execpath = args->fname; | imgp->execpath = args->fname; | |||||||||
vn_lock(imgp->vp, LK_SHARED | LK_RETRY); | vn_lock(imgp->vp, LK_SHARED | LK_RETRY); | |||||||||
} | } | |||||||||
} else { | ||||||||||
VOP_UNLOCK(imgp->vp); | ||||||||||
if (vn_fullpath(imgp->vp, &imgp->execpath, | ||||||||||
&imgp->freepath) != 0) | ||||||||||
imgp->execpath = args->fname; | ||||||||||
vn_lock(imgp->vp, LK_SHARED | LK_RETRY); | ||||||||||
} | ||||||||||
/* | /* | |||||||||
* If the current process has a special image activator it | * If the current process has a special image activator it | |||||||||
* wants to try first, call it. For example, emulating shell | * wants to try first, call it. For example, emulating shell | |||||||||
* scripts differently. | * scripts differently. | |||||||||
*/ | */ | |||||||||
error = -1; | error = -1; | |||||||||
if ((img_first = imgp->proc->p_sysent->sv_imgact_try) != NULL) | if ((img_first = imgp->proc->p_sysent->sv_imgact_try) != NULL) | |||||||||
Show All 30 Lines | if (imgp->interpreted) { | |||||||||
* something is a script where text reference is active. | * something is a script where text reference is active. | |||||||||
* The vnode lock is held over this entire period | * The vnode lock is held over this entire period | |||||||||
* so nothing should illegitimately be blocked. | * so nothing should illegitimately be blocked. | |||||||||
*/ | */ | |||||||||
MPASS(imgp->textset); | MPASS(imgp->textset); | |||||||||
VOP_UNSET_TEXT_CHECKED(newtextvp); | VOP_UNSET_TEXT_CHECKED(newtextvp); | |||||||||
imgp->textset = false; | imgp->textset = false; | |||||||||
/* free name buffer and old vnode */ | /* free name buffer and old vnode */ | |||||||||
if (args->fname != NULL) | ||||||||||
NDFREE(&nd, NDF_ONLY_PNBUF); | ||||||||||
#ifdef MAC | #ifdef MAC | |||||||||
mac_execve_interpreter_enter(newtextvp, &interpvplabel); | mac_execve_interpreter_enter(newtextvp, &interpvplabel); | |||||||||
#endif | #endif | |||||||||
if (imgp->opened) { | if (imgp->opened) { | |||||||||
VOP_CLOSE(newtextvp, FREAD, td->td_ucred, td); | VOP_CLOSE(newtextvp, FREAD, td->td_ucred, td); | |||||||||
imgp->opened = 0; | imgp->opened = false; | |||||||||
} | } | |||||||||
vput(newtextvp); | vput(newtextvp); | |||||||||
if (args->fname != NULL) { | ||||||||||
MPASS(nd.ni_dvp == NULL); | ||||||||||
Done Inline ActionsDon't we unconditionally set nd.ni_dvp = NULL above? i.e. the dvp reference is unconditionally transferred to newtextdvp after the namei() call. markj: Don't we unconditionally set `nd.ni_dvp = NULL` above? i.e. the dvp reference is… | ||||||||||
Done Inline ActionsSo yes this is true there, I changed the vrele to assert that ni_dvp == NULL. I want the vrele(ni_dvp) to be left as is on exec_fail_dealloc: label. I think that technically ni_dvp cannot be non-null there, but it is too fragile to assume on the recovery path. kib: So yes this is true there, I changed the vrele to assert that ni_dvp == NULL.
I want the vrele… | ||||||||||
Done Inline ActionsActually I do not understand how this works. Doesn't the use of vn_fullpath_hardlink() assume that ni_dvp != NULL? markj: Actually I do not understand how this works. Doesn't the use of vn_fullpath_hardlink() assume… | ||||||||||
Done Inline ActionsRight, there were too many moves around. So I did one more, lets calculate the execpath right after namei(). I like the move on its own, because it naturally fit into fexecve(2) path of calculating execpath, also removing one vnode relock. Then ni_dvp is not used anywhere except this args->fname != NULL path. Also I think it is possible to eliminate second NDINIT() by moving first one under the same if() branch. kib: Right, there were too many moves around.
So I did one more, lets calculate the execpath right… | ||||||||||
if (newtextdvp != NULL) { | ||||||||||
vrele(newtextdvp); | ||||||||||
newtextdvp = NULL; | ||||||||||
} | ||||||||||
NDFREE(&nd, NDF_ONLY_PNBUF); | ||||||||||
free(newbinname, M_PARGS); | ||||||||||
newbinname = NULL; | ||||||||||
} | ||||||||||
Done Inline ActionsIt took me a while to convince myself that we do not need to set imgp->vp = NULL here, but maybe it would be worthwhile anyway. markj: It took me a while to convince myself that we do not need to set `imgp->vp = NULL` here, but… | ||||||||||
Done Inline Actionsimgp is fully reset on interpreter recycle, I will add the reset. kib: imgp is fully reset on interpreter recycle, I will add the reset. | ||||||||||
vm_object_deallocate(imgp->object); | vm_object_deallocate(imgp->object); | |||||||||
imgp->object = NULL; | imgp->object = NULL; | |||||||||
execve_nosetid(imgp); | execve_nosetid(imgp); | |||||||||
imgp->execpath = NULL; | imgp->execpath = NULL; | |||||||||
free(imgp->freepath, M_TEMP); | free(imgp->freepath, M_TEMP); | |||||||||
imgp->freepath = NULL; | imgp->freepath = NULL; | |||||||||
/* set new name to that of the interpreter */ | /* set new name to that of the interpreter */ | |||||||||
NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW | | ||||||||||
SAVENAME, UIO_SYSSPACE, imgp->interpreter_name, td); | ||||||||||
args->fname = imgp->interpreter_name; | args->fname = imgp->interpreter_name; | |||||||||
NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW | | ||||||||||
SAVENAME | WANTPARENT, | ||||||||||
UIO_SYSSPACE, imgp->interpreter_name, td); | ||||||||||
goto interpret; | goto interpret; | |||||||||
} | } | |||||||||
/* | /* | |||||||||
* NB: We unlock the vnode here because it is believed that none | * NB: We unlock the vnode here because it is believed that none | |||||||||
* of the sv_copyout_strings/sv_fixup operations require the vnode. | * of the sv_copyout_strings/sv_fixup operations require the vnode. | |||||||||
*/ | */ | |||||||||
VOP_UNLOCK(imgp->vp); | VOP_UNLOCK(imgp->vp); | |||||||||
▲ Show 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | #endif | |||||||||
*/ | */ | |||||||||
if (imgp->newcred != NULL) { | if (imgp->newcred != NULL) { | |||||||||
proc_set_cred(p, imgp->newcred); | proc_set_cred(p, imgp->newcred); | |||||||||
crfree(oldcred); | crfree(oldcred); | |||||||||
oldcred = NULL; | oldcred = NULL; | |||||||||
} | } | |||||||||
/* | /* | |||||||||
* Store the vp for use in procfs. This vnode was referenced by namei | * Store the vp for use in kern.proc.pathname. This vnode was | |||||||||
* or fgetvp_exec. | * referenced by namei or fgetvp_exec. | |||||||||
Done Inline Actions
markj: | ||||||||||
*/ | */ | |||||||||
oldtextvp = p->p_textvp; | oldtextvp = p->p_textvp; | |||||||||
p->p_textvp = newtextvp; | p->p_textvp = newtextvp; | |||||||||
oldtextdvp = p->p_textdvp; | ||||||||||
p->p_textdvp = newtextdvp; | ||||||||||
newtextdvp = NULL; | ||||||||||
oldbinname = p->p_binname; | ||||||||||
p->p_binname = newbinname; | ||||||||||
newbinname = NULL; | ||||||||||
#ifdef KDTRACE_HOOKS | #ifdef KDTRACE_HOOKS | |||||||||
/* | /* | |||||||||
* Tell the DTrace fasttrap provider about the exec if it | * Tell the DTrace fasttrap provider about the exec if it | |||||||||
* has declared an interest. | * has declared an interest. | |||||||||
*/ | */ | |||||||||
if (dtrace_fasttrap_exec) | if (dtrace_fasttrap_exec) | |||||||||
dtrace_fasttrap_exec(p); | dtrace_fasttrap_exec(p); | |||||||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | if (error != 0) { | |||||||||
p->p_fctl0 = orig_fctl0; | p->p_fctl0 = orig_fctl0; | |||||||||
p->p_elf_brandinfo = orig_brandinfo; | p->p_elf_brandinfo = orig_brandinfo; | |||||||||
} | } | |||||||||
if (imgp->firstpage != NULL) | if (imgp->firstpage != NULL) | |||||||||
exec_unmap_first_page(imgp); | exec_unmap_first_page(imgp); | |||||||||
if (imgp->vp != NULL) { | if (imgp->vp != NULL) { | |||||||||
if (args->fname) | ||||||||||
NDFREE(&nd, NDF_ONLY_PNBUF); | ||||||||||
if (imgp->opened) | if (imgp->opened) | |||||||||
VOP_CLOSE(imgp->vp, FREAD, td->td_ucred, td); | VOP_CLOSE(imgp->vp, FREAD, td->td_ucred, td); | |||||||||
if (imgp->textset) | if (imgp->textset) | |||||||||
VOP_UNSET_TEXT_CHECKED(imgp->vp); | VOP_UNSET_TEXT_CHECKED(imgp->vp); | |||||||||
if (error != 0) | if (error != 0) | |||||||||
vput(imgp->vp); | vput(imgp->vp); | |||||||||
else | else | |||||||||
VOP_UNLOCK(imgp->vp); | VOP_UNLOCK(imgp->vp); | |||||||||
if (args->fname != NULL) { | ||||||||||
if (nd.ni_dvp != NULL) | ||||||||||
vrele(nd.ni_dvp); | ||||||||||
NDFREE(&nd, NDF_ONLY_PNBUF); | ||||||||||
} | } | |||||||||
if (newtextdvp != NULL) | ||||||||||
vrele(newtextdvp); | ||||||||||
free(newbinname, M_PARGS); | ||||||||||
} | ||||||||||
if (imgp->object != NULL) | if (imgp->object != NULL) | |||||||||
vm_object_deallocate(imgp->object); | vm_object_deallocate(imgp->object); | |||||||||
free(imgp->freepath, M_TEMP); | free(imgp->freepath, M_TEMP); | |||||||||
if (error == 0) { | if (error == 0) { | |||||||||
if (p->p_ptevents & PTRACE_EXEC) { | if (p->p_ptevents & PTRACE_EXEC) { | |||||||||
Show All 21 Lines | ||||||||||
#endif | #endif | |||||||||
exec_free_args(args); | exec_free_args(args); | |||||||||
/* | /* | |||||||||
* Handle deferred decrement of ref counts. | * Handle deferred decrement of ref counts. | |||||||||
*/ | */ | |||||||||
if (oldtextvp != NULL) | if (oldtextvp != NULL) | |||||||||
vrele(oldtextvp); | vrele(oldtextvp); | |||||||||
if (oldtextdvp != NULL) | ||||||||||
vrele(oldtextdvp); | ||||||||||
free(oldbinname, M_PARGS); | ||||||||||
#ifdef KTRACE | #ifdef KTRACE | |||||||||
ktr_io_params_free(kiop); | ktr_io_params_free(kiop); | |||||||||
#endif | #endif | |||||||||
pargs_drop(oldargs); | pargs_drop(oldargs); | |||||||||
pargs_drop(newargs); | pargs_drop(newargs); | |||||||||
if (oldsigacts != NULL) | if (oldsigacts != NULL) | |||||||||
sigacts_free(oldsigacts); | sigacts_free(oldsigacts); | |||||||||
if (euip != NULL) | if (euip != NULL) | |||||||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | #if VM_NRESERVLEVEL > 0 | |||||||||
if ((object->flags & OBJ_COLORED) == 0) { | if ((object->flags & OBJ_COLORED) == 0) { | |||||||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | |||||||||
vm_object_color(object, 0); | vm_object_color(object, 0); | |||||||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | |||||||||
} | } | |||||||||
#endif | #endif | |||||||||
error = vm_page_grab_valid_unlocked(&m, object, 0, | error = vm_page_grab_valid_unlocked(&m, object, 0, | |||||||||
VM_ALLOC_COUNT(VM_INITIAL_PAGEIN) | | VM_ALLOC_COUNT(VM_INITIAL_PAGEIN) | | |||||||||
VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY | VM_ALLOC_WIRED); | VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY | VM_ALLOC_WIRED); | |||||||||
if (error != VM_PAGER_OK) | if (error != VM_PAGER_OK) | |||||||||
return (EIO); | return (EIO); | |||||||||
imgp->firstpage = sf_buf_alloc(m, 0); | imgp->firstpage = sf_buf_alloc(m, 0); | |||||||||
imgp->image_header = (char *)sf_buf_kva(imgp->firstpage); | imgp->image_header = (char *)sf_buf_kva(imgp->firstpage); | |||||||||
return (0); | return (0); | |||||||||
} | } | |||||||||
Show All 32 Lines | exec_new_vmspace(struct image_params *imgp, struct sysentvec *sv) | |||||||||
struct thread *td = curthread; | struct thread *td = curthread; | |||||||||
vm_object_t obj; | vm_object_t obj; | |||||||||
struct rlimit rlim_stack; | struct rlimit rlim_stack; | |||||||||
vm_offset_t sv_minuser, stack_addr; | vm_offset_t sv_minuser, stack_addr; | |||||||||
vm_map_t map; | vm_map_t map; | |||||||||
vm_prot_t stack_prot; | vm_prot_t stack_prot; | |||||||||
u_long ssiz; | u_long ssiz; | |||||||||
imgp->vmspace_destroyed = 1; | imgp->vmspace_destroyed = true; | |||||||||
imgp->sysent = sv; | imgp->sysent = sv; | |||||||||
if (p->p_sysent->sv_onexec_old != NULL) | if (p->p_sysent->sv_onexec_old != NULL) | |||||||||
p->p_sysent->sv_onexec_old(td); | p->p_sysent->sv_onexec_old(td); | |||||||||
itimers_exec(p); | itimers_exec(p); | |||||||||
EVENTHANDLER_DIRECT_INVOKE(process_exec, p, imgp); | EVENTHANDLER_DIRECT_INVOKE(process_exec, p, imgp); | |||||||||
▲ Show 20 Lines • Show All 683 Lines • ▼ Show 20 Lines | #endif | |||||||||
imgp->textset = true; | imgp->textset = true; | |||||||||
/* | /* | |||||||||
* Call filesystem specific open routine (which does nothing in the | * Call filesystem specific open routine (which does nothing in the | |||||||||
* general case). | * general case). | |||||||||
*/ | */ | |||||||||
error = VOP_OPEN(vp, FREAD, td->td_ucred, td, NULL); | error = VOP_OPEN(vp, FREAD, td->td_ucred, td, NULL); | |||||||||
if (error == 0) | if (error == 0) | |||||||||
imgp->opened = 1; | imgp->opened = true; | |||||||||
return (error); | return (error); | |||||||||
} | } | |||||||||
/* | /* | |||||||||
* Exec handler registration | * Exec handler registration | |||||||||
*/ | */ | |||||||||
int | int | |||||||||
exec_register(const struct execsw *execsw_arg) | exec_register(const struct execsw *execsw_arg) | |||||||||
▲ Show 20 Lines • Show All 179 Lines • ▼ Show 20 Lines | sbuf_drain_core_output(void *arg, const char *data, int len) | |||||||||
* those routines when dumping a live process. In our case we | * those routines when dumping a live process. In our case we | |||||||||
* can safely release the lock before draining and acquire | * can safely release the lock before draining and acquire | |||||||||
* again after. | * again after. | |||||||||
*/ | */ | |||||||||
locked = PROC_LOCKED(p); | locked = PROC_LOCKED(p); | |||||||||
if (locked) | if (locked) | |||||||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | |||||||||
if (cp->comp != NULL) | if (cp->comp != NULL) | |||||||||
error = compressor_write(cp->comp, __DECONST(char *, data), len); | error = compressor_write(cp->comp, __DECONST(char *, data), | |||||||||
len); | ||||||||||
else | else | |||||||||
error = core_write(cp, __DECONST(void *, data), len, cp->offset, | error = core_write(cp, __DECONST(void *, data), len, cp->offset, | |||||||||
UIO_SYSSPACE, NULL); | UIO_SYSSPACE, NULL); | |||||||||
if (locked) | if (locked) | |||||||||
PROC_LOCK(p); | PROC_LOCK(p); | |||||||||
if (error != 0) | if (error != 0) | |||||||||
return (-error); | return (-error); | |||||||||
cp->offset += len; | cp->offset += len; | |||||||||
return (len); | return (len); | |||||||||
} | } |
Initializing oldtextdvp twice. I think it is technically safe to leave newtextvp uninitialized.