/* * 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; }
int osf1_exec_ecoff_probe(struct lwp *l, struct exec_package *epp) { struct ecoff_exechdr *execp = (struct ecoff_exechdr *)epp->ep_hdr; struct osf1_exec_emul_arg *emul_arg; int error; /* check if the binary is osf1 ecoff */ if (execp->f.f_magic != ECOFF_MAGIC_ALPHA) return ENOEXEC; /* set up the exec package emul arg as appropriate */ emul_arg = kmem_alloc(sizeof(*emul_arg), KM_SLEEP); epp->ep_emul_arg = emul_arg; epp->ep_emul_arg_free = osf1_free_emul_arg; emul_arg->flags = 0; /* this cannot overflow because both are size PATH_MAX */ strcpy(emul_arg->exec_name, epp->ep_kname); /* do any special object file handling */ switch (execp->f.f_flags & ECOFF_FLAG_OBJECT_TYPE_MASK) { case ECOFF_OBJECT_TYPE_SHARABLE: /* can't exec a shared library! */ #if 0 uprintf("can't execute OSF/1 shared libraries\n"); #endif error = ENOEXEC; break; case ECOFF_OBJECT_TYPE_CALL_SHARED: error = osf1_exec_ecoff_dynamic(l, epp); break; default: /* just let the normal ECOFF handlers deal with it. */ error = 0; break; } if (error) { exec_free_emul_arg(epp); kill_vmcmds(&epp->ep_vmcmds); /* if any */ } return (error); }
/* * Copy arguments onto the stack in the normal way, but add some * extra information in case of dynamic binding. */ int linux32_elf32_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp) { Aux32Info ai[LINUX32_ELF_AUX_ENTRIES], *a; uint32_t randbytes[4]; struct elf_args *ap; struct vattr *vap; size_t len; int error; if ((error = netbsd32_copyargs(l, pack, arginfo, stackp, argp)) != 0) return error; a = ai; memset(ai, 0, sizeof(ai)); /* * Push extra arguments on the stack needed by dynamically * linked binaries and static binaries as well. */ a->a_type = AT_PAGESZ; a->a_v = PAGE_SIZE; a++; if ((ap = (struct elf_args *)pack->ep_emul_arg)) { a->a_type = AT_PHDR; a->a_v = ap->arg_phaddr; a++; a->a_type = AT_PHENT; a->a_v = ap->arg_phentsize; a++; a->a_type = AT_PHNUM; a->a_v = ap->arg_phnum; a++; a->a_type = AT_BASE; a->a_v = ap->arg_interp; a++; a->a_type = AT_FLAGS; a->a_v = 0; a++; a->a_type = AT_ENTRY; a->a_v = ap->arg_entry; a++; exec_free_emul_arg(pack); } /* Linux-specific items */ a->a_type = LINUX_AT_CLKTCK; a->a_v = hz; a++; vap = pack->ep_vap; a->a_type = LINUX_AT_UID; a->a_v = kauth_cred_getuid(l->l_cred); a++; a->a_type = LINUX_AT_EUID; a->a_v = ((vap->va_mode & S_ISUID) ? vap->va_uid : kauth_cred_geteuid(l->l_cred)); a++; a->a_type = LINUX_AT_GID; a->a_v = kauth_cred_getgid(l->l_cred); a++; a->a_type = LINUX_AT_EGID; a->a_v = ((vap->va_mode & S_ISGID) ? vap->va_gid : kauth_cred_getegid(l->l_cred)); a++; a->a_type = LINUX_AT_SECURE; a->a_v = 0; a++; a->a_type = LINUX_AT_RANDOM; a->a_v = NETBSD32PTR32I(*stackp); a++; #if 0 /* XXX: increase LINUX32_ELF_AUX_ENTRIES if we enable those things */ a->a_type = LINUX_AT_SYSINFO; a->a_v = NETBSD32PTR32I(&esdp->kernel_vsyscall[0]); a++; a->a_type = LINUX_AT_SYSINFO_EHDR; a->a_v = NETBSD32PTR32I(&esdp->elfhdr); a++; a->a_type = LINUX_AT_HWCAP; a->a_v = LINUX32_CPUCAP; a++; a->a_type = LINUX_AT_PLATFORM; a->a_v = NETBSD32PTR32I(&esdp->hw_platform[0]); a++; #endif a->a_type = AT_NULL; a->a_v = 0; a++; randbytes[0] = cprng_strong32(); randbytes[1] = cprng_strong32(); randbytes[2] = cprng_strong32(); randbytes[3] = cprng_strong32(); len = sizeof(randbytes); if ((error = copyout(randbytes, *stackp, len)) != 0) return error; *stackp += len; #if 0 memcpy(esd.kernel_vsyscall, linux32_kernel_vsyscall, sizeof(linux32_kernel_vsyscall)); memcpy(&esd.elfhdr, eh, sizeof(*eh)); strcpy(esd.hw_platform, LINUX32_PLATFORM); /* * Copy out the ELF auxiliary table and hw platform name */ if ((error = copyout(&esd, esdp, sizeof(esd))) != 0) return error; *stackp += sizeof(esd); #endif len = (a - ai) * sizeof(Aux32Info); KASSERT(len <= LINUX32_ELF_AUX_ENTRIES * sizeof(Aux32Info)); if ((error = copyout(ai, *stackp, len)) != 0) return error; *stackp += len; return 0; }
int svr4_32_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp) { size_t len; AuxInfo ai[SVR4_32_AUX_ARGSIZ], *a, *platform=NULL, *exec=NULL; struct elf_args *ap; extern char machine_model[]; int error; if ((error = netbsd32_copyargs(l, pack, arginfo, stackp, argp)) != 0) return error; a = ai; memset(ai, 0, sizeof(ai)); /* * Push extra arguments on the stack needed by dynamically * linked binaries */ if ((ap = (struct elf_args *)pack->ep_emul_arg)) { struct proc *p = curproc; /* XXXXX */ a->a_type = AT_SUN_PLATFORM; platform = a; /* Patch this later. */ a++; a->a_type = AT_SUN_EXECNAME; exec = a; /* Patch this later. */ a++; a->a_type = AT_PHDR; a->a_v = ap->arg_phaddr; a++; a->a_type = AT_PHENT; a->a_v = ap->arg_phentsize; a++; a->a_type = AT_PHNUM; a->a_v = ap->arg_phnum; a++; a->a_type = AT_ENTRY; a->a_v = ap->arg_entry; a++; a->a_type = AT_BASE; a->a_v = ap->arg_interp; a++; if (sun_flags) { a->a_type = AT_FLAGS; a->a_v = sun_flags; a++; } a->a_type = AT_PAGESZ; a->a_v = PAGE_SIZE; a++; a->a_type = AT_EUID; a->a_v = kauth_cred_geteuid(l->l_cred); a++; a->a_type = AT_RUID; a->a_v = kauth_cred_getuid(l->l_cred); a++; a->a_type = AT_EGID; a->a_v = kauth_cred_getegid(l->l_cred); a++; a->a_type = AT_RGID; a->a_v = kauth_cred_getgid(l->l_cred); a++; if (sun_hwcap) { a->a_type = AT_SUN_HWCAP; a->a_v = sun_hwcap; a++; } exec_free_emul_arg(pack); } a->a_type = AT_NULL; a->a_v = 0; a++; len = (a - ai) * sizeof(AuxInfo); if (platform) { char *ptr = (char *)a; const char *path = NULL; /* Copy out the platform name. */ platform->a_v = (u_long)(*stackp) + len; /* XXXX extremely inefficient.... */ strcpy(ptr, machine_model); ptr += strlen(machine_model) + 1; len += strlen(machine_model) + 1; if (exec) { path = pack->ep_resolvedname; /* Copy out the file we're executing. */ exec->a_v = (u_long)(*stackp) + len; strcpy(ptr, path); len += strlen(ptr)+1; } /* Round to 32-bits */ len = (len+7)&~0x7L; } if ((error = copyout(ai, *stackp, len)) != 0) return error; *stackp += len; return error; }
int svr4_32_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp) { size_t len; AuxInfo ai[SVR4_32_AUX_ARGSIZ], *a; struct elf_args *ap; int error; if ((error = netbsd32_copyargs(l, pack, arginfo, stackp, argp)) != 0) return error; a = ai; memset(ai, 0, sizeof(ai)); /* * Push extra arguments on the stack needed by dynamically * linked binaries */ if ((ap = (struct elf_args *)pack->ep_emul_arg)) { a->a_type = AT_PHDR; a->a_v = ap->arg_phaddr; a++; a->a_type = AT_PHENT; a->a_v = ap->arg_phentsize; a++; a->a_type = AT_PHNUM; a->a_v = ap->arg_phnum; a++; a->a_type = AT_PAGESZ; a->a_v = PAGE_SIZE; a++; a->a_type = AT_BASE; a->a_v = ap->arg_interp; a++; a->a_type = AT_ENTRY; a->a_v = ap->arg_entry; a++; if (sun_flags) { a->a_type = AT_FLAGS; a->a_v = sun_flags; a++; } exec_free_emul_arg(pack); } a->a_type = AT_NULL; a->a_v = 0; a++; len = (a - ai) * sizeof(AuxInfo); if ((error = copyout(ai, *stackp, len)) != 0) return error; *stackp += len; return 0; }
int ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp) { struct linux_extra_stack_data64 *esdp, esd; struct elf_args *ap; struct vattr *vap; Elf_Ehdr *eh; Elf_Phdr *ph; u_long phsize; Elf_Addr phdr = 0; int error; int i; if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) return error; /* * Push extra arguments on the stack needed by dynamically * linked binaries and static binaries as well. */ memset(&esd, 0, sizeof(esd)); esdp = (struct linux_extra_stack_data64 *)(*stackp); ap = (struct elf_args *)pack->ep_emul_arg; vap = pack->ep_vap; eh = (Elf_Ehdr *)pack->ep_hdr; /* * We forgot this, so we need to reload it now. XXX keep track of it? */ if (ap == NULL) { phsize = eh->e_phnum * sizeof(Elf_Phdr); ph = (Elf_Phdr *)kmem_alloc(phsize, KM_SLEEP); error = exec_read_from(l, pack->ep_vp, eh->e_phoff, ph, phsize); if (error != 0) { for (i = 0; i < eh->e_phnum; i++) { if (ph[i].p_type == PT_PHDR) { phdr = ph[i].p_vaddr; break; } } } kmem_free(ph, phsize); } /* * The exec_package doesn't have a proc pointer and it's not * exactly trivial to add one since the credentials are * changing. XXX Linux uses curlwp's credentials. * Why can't we use them too? */ i = 0; esd.ai[i].a_type = LINUX_AT_HWCAP; esd.ai[i++].a_v = rcr4(); esd.ai[i].a_type = AT_PAGESZ; esd.ai[i++].a_v = PAGE_SIZE; esd.ai[i].a_type = LINUX_AT_CLKTCK; esd.ai[i++].a_v = hz; esd.ai[i].a_type = AT_PHDR; esd.ai[i++].a_v = (ap ? ap->arg_phaddr: phdr); esd.ai[i].a_type = AT_PHENT; esd.ai[i++].a_v = (ap ? ap->arg_phentsize : eh->e_phentsize); esd.ai[i].a_type = AT_PHNUM; esd.ai[i++].a_v = (ap ? ap->arg_phnum : eh->e_phnum); esd.ai[i].a_type = AT_BASE; esd.ai[i++].a_v = (ap ? ap->arg_interp : 0); esd.ai[i].a_type = AT_FLAGS; esd.ai[i++].a_v = 0; esd.ai[i].a_type = AT_ENTRY; esd.ai[i++].a_v = (ap ? ap->arg_entry : eh->e_entry); esd.ai[i].a_type = LINUX_AT_EGID; esd.ai[i++].a_v = ((vap->va_mode & S_ISGID) ? vap->va_gid : kauth_cred_getegid(l->l_cred)); esd.ai[i].a_type = LINUX_AT_GID; esd.ai[i++].a_v = kauth_cred_getgid(l->l_cred); esd.ai[i].a_type = LINUX_AT_EUID; esd.ai[i++].a_v = ((vap->va_mode & S_ISUID) ? vap->va_uid : kauth_cred_geteuid(l->l_cred)); esd.ai[i].a_type = LINUX_AT_UID; esd.ai[i++].a_v = kauth_cred_getuid(l->l_cred); esd.ai[i].a_type = LINUX_AT_SECURE; esd.ai[i++].a_v = 0; esd.ai[i].a_type = LINUX_AT_PLATFORM; esd.ai[i++].a_v = (Elf_Addr)&esdp->hw_platform[0]; esd.ai[i].a_type = AT_NULL; esd.ai[i++].a_v = 0; #ifdef DEBUG_LINUX if (i != LINUX_ELF_AUX_ENTRIES) { printf("linux_elf64_copyargs: %d Aux entries\n", i); return EINVAL; } #endif strcpy(esd.hw_platform, LINUX_PLATFORM); exec_free_emul_arg(pack); /* * Copy out the ELF auxiliary table and hw platform name */ if ((error = copyout(&esd, esdp, sizeof(esd))) != 0) return error; *stackp += sizeof(esd); return 0; }
/* * Copy arguments onto the stack in the normal way, but add some * extra information in case of dynamic binding. */ int netbsd32_elf32_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp) { size_t len; AuxInfo ai[ELF_AUX_ENTRIES], *a; struct elf_args *ap; int error; if ((error = netbsd32_copyargs(l, pack, arginfo, stackp, argp)) != 0) return error; a = ai; /* * Push extra arguments on the stack needed by dynamically * linked binaries */ if ((ap = (struct elf_args *)pack->ep_emul_arg)) { a->a_type = AT_PHDR; a->a_v = ap->arg_phaddr; a++; a->a_type = AT_PHENT; a->a_v = ap->arg_phentsize; a++; a->a_type = AT_PHNUM; a->a_v = ap->arg_phnum; a++; a->a_type = AT_PAGESZ; a->a_v = PAGE_SIZE; a++; a->a_type = AT_BASE; a->a_v = ap->arg_interp; a++; a->a_type = AT_FLAGS; a->a_v = 0; a++; a->a_type = AT_ENTRY; a->a_v = ap->arg_entry; a++; a->a_type = AT_EUID; a->a_v = kauth_cred_geteuid(l->l_cred); a++; a->a_type = AT_RUID; a->a_v = kauth_cred_getuid(l->l_cred); a++; a->a_type = AT_EGID; a->a_v = kauth_cred_getegid(l->l_cred); a++; a->a_type = AT_RGID; a->a_v = kauth_cred_getgid(l->l_cred); a++; exec_free_emul_arg(pack); } a->a_type = AT_NULL; a->a_v = 0; a++; len = (a - ai) * sizeof(AuxInfo); if ((error = copyout(ai, *stackp, len)) != 0) return error; *stackp += len; return 0; }
/* * Copy arguments onto the stack in the normal way, but add some * extra information in case of dynamic binding. */ int ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp) { size_t len; AuxInfo ai[LINUX_ELF_AUX_ENTRIES], *a; struct elf_args *ap; int error; struct vattr *vap; if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0) return error; a = ai; /* * Push extra arguments used by glibc on the stack. */ a->a_type = AT_PAGESZ; a->a_v = PAGE_SIZE; a++; if ((ap = (struct elf_args *)pack->ep_emul_arg)) { a->a_type = AT_PHDR; a->a_v = ap->arg_phaddr; a++; a->a_type = AT_PHENT; a->a_v = ap->arg_phentsize; a++; a->a_type = AT_PHNUM; a->a_v = ap->arg_phnum; a++; a->a_type = AT_BASE; a->a_v = ap->arg_interp; a++; a->a_type = AT_FLAGS; a->a_v = 0; a++; a->a_type = AT_ENTRY; a->a_v = ap->arg_entry; a++; exec_free_emul_arg(pack); } /* Linux-specific items */ a->a_type = LINUX_AT_CLKTCK; a->a_v = hz; a++; vap = pack->ep_vap; a->a_type = LINUX_AT_UID; a->a_v = kauth_cred_getuid(l->l_cred); a++; a->a_type = LINUX_AT_EUID; if (vap->va_mode & S_ISUID) a->a_v = vap->va_uid; else a->a_v = kauth_cred_geteuid(l->l_cred); a++; a->a_type = LINUX_AT_GID; a->a_v = kauth_cred_getgid(l->l_cred); a++; a->a_type = LINUX_AT_EGID; if (vap->va_mode & S_ISGID) a->a_v = vap->va_gid; else a->a_v = kauth_cred_getegid(l->l_cred); a++; a->a_type = AT_NULL; a->a_v = 0; a++; len = (a - ai) * sizeof(AuxInfo); if ((error = copyout(ai, *stackp, len)) != 0) return error; *stackp += len; return 0; }