Date: Wed, 17 Dec 2008 20:20:48 +0300 From: Chagin Dmitry <dchagin@freebsd.org> To: "M. Warner Losh" <imp@bsdimp.com> Cc: arch@freebsd.org Subject: Re: Removing some cruft... Message-ID: <20081217172047.GA2884@dchagin.dialup.corbina.ru> In-Reply-To: <20081216.161638.644659879.imp@bsdimp.com> References: <20081216.131845.-1739986974.imp@bsdimp.com> <20081216212746.GA28834@freebsd.org> <20081216.161638.644659879.imp@bsdimp.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, Dec 16, 2008 at 04:16:38PM -0700, M. Warner Losh wrote: > In message: <20081216212746.GA28834@freebsd.org> > Roman Divacky <rdivacky@freebsd.org> writes: > : On Tue, Dec 16, 2008 at 01:18:45PM -0700, M. Warner Losh wrote: > : > I was looking at the MIPS elf stuff based on a submission of some > : > 64-bit support. In doing so, I discovered a number of 'unused' types > : > that appear to have comments that indicate that they can be removed > : > now and were just slavishly copied from arch to arch to arch. > : > > : > /* > : > * The following non-standard values are used for passing information > : > * from John Polstra's testbed program to the dynamic linker. These > : > * are expected to go away soon. > : > * > : > * Unfortunately, these overlap the Linux non-standard values, so they > : > * must not be used in the same context. > : > */ > : > #define AT_BRK 10 /* Starting point for sbrk and brk. */ > : > #define AT_DEBUG 11 /* Debugging level. */ > : > > : > These have be slavishly copied to arm, powerpc, sparc64, ia64, mips, > : > sun4v and amd64. All these files have nearly identical comments > : > (except powerpc, which changes the value). > : > > : > The only place these are used in the kernel is in the Linux! > : > emulation in i386/linux/linux_sysvec.c and > : > amd64/linux32/linux32_sysvec.c: > : > > : > if (args->trace) > : > AUXARGS_ENTRY(pos, AT_DEBUG, 1); > : > > : > Since AT_DEBUG and AT_UID have the same value, and we look at AT_UID > : > later, we wind up passing the wrong value for AT_UID. Fortunately, we > : > don't use AT_UID for anything in the tree.... > : > : I cannot find any reference of AT_DEBUG in linux 2.6.16 sources and it > : indeed looks bogus... > > What do you think of the following patch? > > Warner > Hi, I am ready to offer more radical patch :) Move all Linux aux entry types to a new file compat/linux/linux_elf.h Add two new aux entries which improve work of futexes. Please review. thnx! diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h index a4c7f79..3c2cd20 100644 --- a/sys/amd64/include/elf.h +++ b/sys/amd64/include/elf.h @@ -81,16 +81,8 @@ __ElfType(Auxinfo); #define AT_BASE 7 /* Interpreter's base address. */ #define AT_FLAGS 8 /* Flags (unused for i386). */ #define AT_ENTRY 9 /* Where interpreter should transfer control. */ -/* - * The following non-standard values are used in Linux ELF binaries. - */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ -#define AT_COUNT 15 /* Count of defined aux entry types. */ +#define AT_COUNT 10 /* Count of defined aux entry types. */ /* * Relocation types. diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h index e0ffcdf..3f04555 100644 --- a/sys/amd64/linux32/linux.h +++ b/sys/amd64/linux32/linux.h @@ -108,6 +108,12 @@ typedef struct { #define LINUX_CTL_MAXNAME 10 +#define LINUX_AT_SYSINFO 32 +#define LINUX_AT_SYSINFO_EHDR 33 +#define LINUX_AT_COUNT 16 /* Count of used aux entry types. + * Keep this synchronized with + * elf_linux_fixup() code. + */ struct l___sysctl_args { l_uintptr_t name; diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c index aaa7458..2777e84 100644 --- a/sys/amd64/linux32/linux32_sysvec.c +++ b/sys/amd64/linux32/linux32_sysvec.c @@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$"); #include <amd64/linux32/linux.h> #include <amd64/linux32/linux32_proto.h> +#include <compat/linux/linux_elf.h> #include <compat/linux/linux_emul.h> #include <compat/linux/linux_mib.h> #include <compat/linux/linux_signal.h> @@ -106,6 +107,8 @@ MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures"); #define LINUX_SYS_linux_rt_sendsig 0 #define LINUX_SYS_linux_sendsig 0 +const char linux_platform[] = "i686"; +static int linux_szplatform; extern char linux_sigcode[]; extern int linux_szsigcode; @@ -246,7 +249,12 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) { Elf32_Auxargs *args; Elf32_Addr *base; - Elf32_Addr *pos; + Elf32_Addr *pos, *uplatform; + struct linux32_ps_strings *arginfo; + + arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS; + uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szsigcode - + linux_szplatform); KASSERT(curthread->td_proc == imgp->proc, ("unsafe elf_linux_fixup(), should be curproc")); @@ -254,8 +262,8 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) args = (Elf32_Auxargs *)imgp->auxargs; pos = base + (imgp->args->argc + imgp->args->envc + 2); - if (args->execfd != -1) - AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd); + AUXARGS_ENTRY_32(pos, LINUX_AT_HWCAP, cpu_feature); + AUXARGS_ENTRY_32(pos, LINUX_AT_CLKTCK, hz); AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY_32(pos, AT_PHENT, args->phent); AUXARGS_ENTRY_32(pos, AT_PHNUM, args->phnum); @@ -263,10 +271,14 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) AUXARGS_ENTRY_32(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY_32(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY_32(pos, AT_BASE, args->base); - AUXARGS_ENTRY_32(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); - AUXARGS_ENTRY_32(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); - AUXARGS_ENTRY_32(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); - AUXARGS_ENTRY_32(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); + AUXARGS_ENTRY_32(pos, LINUX_AT_SECURE, 0); + AUXARGS_ENTRY_32(pos, LINUX_AT_UID, imgp->proc->p_ucred->cr_ruid); + AUXARGS_ENTRY_32(pos, LINUX_AT_EUID, imgp->proc->p_ucred->cr_svuid); + AUXARGS_ENTRY_32(pos, LINUX_AT_GID, imgp->proc->p_ucred->cr_rgid); + AUXARGS_ENTRY_32(pos, LINUX_AT_EGID, imgp->proc->p_ucred->cr_svgid); + AUXARGS_ENTRY_32(pos, LINUX_AT_PLATFORM, PTROUT(uplatform)); + if (args->execfd != -1) + AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd); AUXARGS_ENTRY_32(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); @@ -851,27 +863,31 @@ static register_t * linux_copyout_strings(struct image_params *imgp) { int argc, envc; - u_int32_t *vectp; + uint32_t *vectp; char *stringp, *destp; - u_int32_t *stack_base; + uint32_t *stack_base; struct linux32_ps_strings *arginfo; - int sigcodesz; /* * Calculate string base and vector table pointers. * Also deal with signal trampoline code for this exec type. */ arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS; - sigcodesz = *(imgp->proc->p_sysent->sv_szsigcode); - destp = (caddr_t)arginfo - sigcodesz - SPARE_USRSPACE - - roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *)); + destp = (caddr_t)arginfo - linux_szsigcode - SPARE_USRSPACE - + linux_szplatform - roundup((ARG_MAX - imgp->args->stringspace), + sizeof(char *)); /* * install sigcode */ - if (sigcodesz) - copyout(imgp->proc->p_sysent->sv_sigcode, - ((caddr_t)arginfo - sigcodesz), sigcodesz); + copyout(imgp->proc->p_sysent->sv_sigcode, + ((caddr_t)arginfo - linux_szsigcode), linux_szsigcode); + + /* + * Install LINUX_PLATFORM + */ + copyout(linux_platform, ((caddr_t)arginfo - linux_szsigcode - + linux_szplatform), linux_szplatform); /* * If we have a valid auxargs ptr, prepare some room @@ -883,22 +899,22 @@ linux_copyout_strings(struct image_params *imgp) * lower compatibility. */ imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size - : (AT_COUNT * 2); + : (LINUX_AT_COUNT * 2); /* * The '+ 2' is for the null pointers at the end of each of * the arg and env vector sets,and imgp->auxarg_size is room * for argument of Runtime loader. */ - vectp = (u_int32_t *) (destp - (imgp->args->argc + imgp->args->envc + 2 + - imgp->auxarg_size) * sizeof(u_int32_t)); + vectp = (uint32_t *) (destp - (imgp->args->argc + + imgp->args->envc + 2 + imgp->auxarg_size) * sizeof(uint32_t)); } else /* * The '+ 2' is for the null pointers at the end of each of * the arg and env vector sets */ - vectp = (u_int32_t *) - (destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t)); + vectp = (uint32_t *) (destp - (imgp->args->argc + + imgp->args->envc + 2) * sizeof(uint32_t)); /* * vectp also becomes our initial stack base @@ -916,14 +932,14 @@ linux_copyout_strings(struct image_params *imgp) /* * Fill in "ps_strings" struct for ps, w, etc. */ - suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp); suword32(&arginfo->ps_nargvstr, argc); /* * Fill in argument portion of vector table. */ for (; argc > 0; --argc) { - suword32(vectp++, (u_int32_t)(intptr_t)destp); + suword32(vectp++, (uint32_t)(intptr_t)destp); while (*stringp++ != 0) destp++; destp++; @@ -932,14 +948,14 @@ linux_copyout_strings(struct image_params *imgp) /* a null vector table pointer separates the argp's from the envp's */ suword32(vectp++, 0); - suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp); suword32(&arginfo->ps_nenvstr, envc); /* * Fill in environment portion of vector table. */ for (; envc > 0; --envc) { - suword32(vectp++, (u_int32_t)(intptr_t)destp); + suword32(vectp++, (uint32_t)(intptr_t)destp); while (*stringp++ != 0) destp++; destp++; @@ -1088,6 +1104,8 @@ linux_elf_modevent(module_t mod, int type, void *data) NULL, 1000); if (bootverbose) printf("Linux ELF exec handler installed\n"); + linux_szplatform = roundup(strlen(linux_platform) + 1, + sizeof(char *)); } else printf("cannot insert Linux ELF brand handler\n"); break; diff --git a/sys/arm/include/elf.h b/sys/arm/include/elf.h index c516864..48260e1 100644 --- a/sys/arm/include/elf.h +++ b/sys/arm/include/elf.h @@ -70,13 +70,8 @@ __ElfType(Auxinfo); #define AT_BASE 7 /* Interpreter's base address. */ #define AT_FLAGS 8 /* Flags (unused). */ #define AT_ENTRY 9 /* Where interpreter should transfer control. */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ -#define AT_COUNT 15 /* Count of defined aux entry types. */ +#define AT_COUNT 10 /* Count of defined aux entry types. */ #define R_ARM_COUNT 33 /* Count of defined relocation types. */ diff --git a/sys/compat/linux/linux_elf.h b/sys/compat/linux/linux_elf.h new file mode 100644 index 0000000..680e39b --- /dev/null +++ b/sys/compat/linux/linux_elf.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2008 Chagin Dmitry + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LINUX_ELF_H_ +#define _LINUX_ELF_H_ + +/* + * Non-standard aux entry types used in Linux ELF binaries. + */ + +#define LINUX_AT_NOTELF 10 /* Program is not ELF ?? */ +#define LINUX_AT_UID 11 /* Real uid. */ +#define LINUX_AT_EUID 12 /* Effective uid. */ +#define LINUX_AT_GID 13 /* Real gid. */ +#define LINUX_AT_EGID 14 /* Effective gid. */ +#define LINUX_AT_PLATFORM 15 /* String identifying CPU */ +#define LINUX_AT_HWCAP 16 /* CPU capabilities */ +#define LINUX_AT_CLKTCK 17 /* frequency at which times() increments */ +#define LINUX_AT_SECURE 23 /* secure mode boolean */ +#define LINUX_AT_BASE_PLATFORM 24 /* string identifying real platform, may + * differ from AT_PLATFORM. + */ +#define LINUX_AT_EXECFN 31 /* filename of program */ + +#endif /* !_LINUX_ELF_H_ */ diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 93f4297..cf14da3 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -92,10 +92,6 @@ __FBSDID("$FreeBSD$"); #include <compat/linux/linux_emul.h> #include <compat/linux/linux_misc.h> -#ifdef __i386__ -#include <machine/cputypes.h> -#endif - #define BSD_TO_LINUX_SIGNAL(sig) \ (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) @@ -731,34 +727,8 @@ linux_newuname(struct thread *td, struct linux_newuname_args *args) *p = '\0'; break; } -#ifdef __i386__ - { - const char *class; + strlcpy(utsname.machine, linux_platform, LINUX_MAX_UTSNAME); - switch (cpu_class) { - case CPUCLASS_686: - class = "i686"; - break; - case CPUCLASS_586: - class = "i586"; - break; - case CPUCLASS_486: - class = "i486"; - break; - default: - class = "i386"; - } - strlcpy(utsname.machine, class, LINUX_MAX_UTSNAME); - } -#elif defined(__amd64__) /* XXX: Linux can change 'personality'. */ -#ifdef COMPAT_LINUX32 - strlcpy(utsname.machine, "i686", LINUX_MAX_UTSNAME); -#else - strlcpy(utsname.machine, "x86_64", LINUX_MAX_UTSNAME); -#endif /* COMPAT_LINUX32 */ -#else /* something other than i386 or amd64 - assume we and Linux agree */ - strlcpy(utsname.machine, machine, LINUX_MAX_UTSNAME); -#endif /* __i386__ */ mtx_lock(&hostname_mtx); strlcpy(utsname.domainname, V_domainname, LINUX_MAX_UTSNAME); mtx_unlock(&hostname_mtx); diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h index c80a432..2cdb3c3 100644 --- a/sys/compat/linux/linux_misc.h +++ b/sys/compat/linux/linux_misc.h @@ -45,4 +45,6 @@ #define LINUX_MREMAP_MAYMOVE 1 #define LINUX_MREMAP_FIXED 2 +extern const char linux_platform[]; + #endif /* _LINUX_MISC_H_ */ diff --git a/sys/compat/svr4/svr4.h b/sys/compat/svr4/svr4.h index 84ee720..261e3e9 100644 --- a/sys/compat/svr4/svr4.h +++ b/sys/compat/svr4/svr4.h @@ -36,4 +36,11 @@ extern struct sysentvec svr4_sysvec; #define COMPAT_SVR4_SOLARIS2 -#endif +#define SVR4_AT_UID 11 /* Real uid. */ +#define SVR4_AT_EUID 12 /* Effective uid. */ +#define SVR4_AT_GID 13 /* Real gid. */ +#define SVR4_AT_EGID 14 /* Effective gid. */ + +#define SVR4_AT_COUNT 15 /* Count of defined aux entry types. */ + +#endif /* !_LINUX_ELF_H_ */ diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c index 0030e3a..24a742c 100644 --- a/sys/compat/svr4/svr4_sysvec.c +++ b/sys/compat/svr4/svr4_sysvec.c @@ -163,6 +163,115 @@ extern struct sysent svr4_sysent[]; extern int svr4_szsigcode; extern char svr4_sigcode[]; + +/* + * Copy strings out to the new process address space, constructing new arg + * and env vector tables. Return a pointer to the base so that it can be used + * as the initial stack pointer. + */ +static register_t * +svr4_copyout_strings(struct image_params *imgp) +{ + int argc, envc; + char **vectp; + char *stringp, *destp; + register_t *stack_base; + struct ps_strings *arginfo; + struct proc *p; + + /* + * Calculate string base and vector table pointers. + * Also deal with signal trampoline code for this exec type. + */ + p = imgp->proc; + arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; + destp = (caddr_t)arginfo - svr4_szsigcode - SPARE_USRSPACE - + roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *)); + + copyout(p->p_sysent->sv_sigcode, ((caddr_t)arginfo - + svr4_szsigcode), svr4_szsigcode); + + /* + * If we have a valid auxargs ptr, prepare some room + * on the stack. + */ + if (imgp->auxargs) { + /* + * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for + * lower compatibility. + */ + imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size : + (SVR4_AT_COUNT * 2); + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets,and imgp->auxarg_size is room + * for argument of Runtime loader. + */ + vectp = (char **)(destp - (imgp->args->argc + + imgp->args->envc + 2 + imgp->auxarg_size) * + sizeof(char *)); + + } else { + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets + */ + vectp = (char **)(destp - (imgp->args->argc + imgp->args->envc + 2) * + sizeof(char *)); + } + + /* + * vectp also becomes our initial stack base + */ + stack_base = (register_t *)vectp; + + stringp = imgp->args->begin_argv; + argc = imgp->args->argc; + envc = imgp->args->envc; + + /* + * Copy out strings - arguments and environment. + */ + copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); + + /* + * Fill in "ps_strings" struct for ps, w, etc. + */ + suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); + suword(&arginfo->ps_nargvstr, argc); + + /* + * Fill in argument portion of vector table. + */ + for (; argc > 0; --argc) { + suword(vectp++, (long)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* a null vector table pointer separates the argp's from the envp's */ + suword(vectp++, 0); + + suword(&arginfo->ps_envstr, (long)(intptr_t)vectp); + suword(&arginfo->ps_nenvstr, envc); + + /* + * Fill in environment portion of vector table. + */ + for (; envc > 0; --envc) { + suword(vectp++, (long)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* end of vector table is a null pointer */ + suword(vectp, 0); + + return (stack_base); +} + struct sysentvec svr4_sysvec = { .sv_size = SVR4_SYS_MAXSYSCALL, .sv_table = svr4_sysent, @@ -187,7 +296,7 @@ struct sysentvec svr4_sysvec = { .sv_usrstack = USRSTACK, .sv_psstrings = PS_STRINGS, .sv_stackprot = VM_PROT_ALL, - .sv_copyout_strings = exec_copyout_strings, + .sv_copyout_strings = svr4_copyout_strings, .sv_setregs = exec_setregs, .sv_fixlimit = NULL, .sv_maxssiz = NULL, @@ -227,10 +336,10 @@ svr4_fixup(register_t **stack_base, struct image_params *imgp) AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); - AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); - AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); - AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); - AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); + AUXARGS_ENTRY(pos, SVR4_AT_UID, imgp->proc->p_ucred->cr_ruid); + AUXARGS_ENTRY(pos, SVR4_AT_EUID, imgp->proc->p_ucred->cr_svuid); + AUXARGS_ENTRY(pos, SVR4_AT_GID, imgp->proc->p_ucred->cr_rgid); + AUXARGS_ENTRY(pos, SVR4_AT_EGID, imgp->proc->p_ucred->cr_svgid); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); @@ -307,3 +416,4 @@ static moduledata_t svr4_elf_mod = { }; DECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); MODULE_DEPEND(svr4elf, streams, 1, 1, 1); + diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h index f9c7ee5..46478c0 100644 --- a/sys/i386/linux/linux.h +++ b/sys/i386/linux/linux.h @@ -102,6 +102,12 @@ typedef struct { #define LINUX_CTL_MAXNAME 10 +#define LINUX_AT_SYSINFO 32 +#define LINUX_AT_SYSINFO_EHDR 33 +#define LINUX_AT_COUNT 16 /* Count of used aux entry types. + * Keep this synchronized with + * elf_linux_fixup() code. + */ struct l___sysctl_args { l_int *name; diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c index 42365fb..b44fb00 100644 --- a/sys/i386/linux/linux_sysvec.c +++ b/sys/i386/linux/linux_sysvec.c @@ -58,11 +58,13 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_param.h> #include <machine/cpu.h> +#include <machine/cputypes.h> #include <machine/md_var.h> #include <machine/pcb.h> #include <i386/linux/linux.h> #include <i386/linux/linux_proto.h> +#include <compat/linux/linux_elf.h> #include <compat/linux/linux_emul.h> #include <compat/linux/linux_mib.h> #include <compat/linux/linux_signal.h> @@ -107,6 +109,10 @@ static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); static void exec_linux_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings); +static register_t *linux_copyout_strings(struct image_params *imgp); + +static int linux_szplatform; +const char *linux_platform; extern LIST_HEAD(futex_list, futex) futex_list; extern struct sx futex_sx; @@ -231,22 +237,30 @@ linux_fixup(register_t **stack_base, struct image_params *imgp) **stack_base = (intptr_t)(void *)argv; (*stack_base)--; **stack_base = imgp->args->argc; - return 0; + return (0); } static int elf_linux_fixup(register_t **stack_base, struct image_params *imgp) { + struct proc *p; Elf32_Auxargs *args; + Elf32_Addr *uplatform; + struct ps_strings *arginfo; register_t *pos; KASSERT(curthread->td_proc == imgp->proc, ("unsafe elf_linux_fixup(), should be curproc")); + + p = imgp->proc; + arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; + uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szsigcode - + linux_szplatform); args = (Elf32_Auxargs *)imgp->auxargs; pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2); - if (args->execfd != -1) - AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); + AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature); + AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, hz); AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); AUXARGS_ENTRY(pos, AT_PHENT, args->phent); AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); @@ -254,10 +268,14 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); AUXARGS_ENTRY(pos, AT_BASE, args->base); - AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); - AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); - AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); - AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); + AUXARGS_ENTRY(pos, LINUX_AT_SECURE, 0); + AUXARGS_ENTRY(pos, LINUX_AT_UID, imgp->proc->p_ucred->cr_ruid); + AUXARGS_ENTRY(pos, LINUX_AT_EUID, imgp->proc->p_ucred->cr_svuid); + AUXARGS_ENTRY(pos, LINUX_AT_GID, imgp->proc->p_ucred->cr_rgid); + AUXARGS_ENTRY(pos, LINUX_AT_EGID, imgp->proc->p_ucred->cr_svgid); + AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(uplatform)); + if (args->execfd != -1) + AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); AUXARGS_ENTRY(pos, AT_NULL, 0); free(imgp->auxargs, M_TEMP); @@ -265,9 +283,125 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp) (*stack_base)--; **stack_base = (register_t)imgp->args->argc; - return 0; + return (0); +} + +/* + * Copied from kern/kern_exec.c + */ +static register_t * +linux_copyout_strings(struct image_params *imgp) +{ + int argc, envc; + char **vectp; + char *stringp, *destp; + register_t *stack_base; + struct ps_strings *arginfo; + struct proc *p; + + /* + * Calculate string base and vector table pointers. + * Also deal with signal trampoline code for this exec type. + */ + p = imgp->proc; + arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings; + destp = (caddr_t)arginfo - linux_szsigcode - SPARE_USRSPACE - + linux_szplatform - roundup((ARG_MAX - imgp->args->stringspace), + sizeof(char *)); + + /* + * install sigcode + */ + copyout(p->p_sysent->sv_sigcode, ((caddr_t)arginfo - + linux_szsigcode), linux_szsigcode); + + /* + * install LINUX_PLATFORM + */ + copyout(linux_platform, ((caddr_t)arginfo - linux_szsigcode - + linux_szplatform), linux_szplatform); + + /* + * If we have a valid auxargs ptr, prepare some room + * on the stack. + */ + if (imgp->auxargs) { + /* + * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for + * lower compatibility. + */ + imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size : + (LINUX_AT_COUNT * 2); + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets,and imgp->auxarg_size is room + * for argument of Runtime loader. + */ + vectp = (char **)(destp - (imgp->args->argc + + imgp->args->envc + 2 + imgp->auxarg_size) * sizeof(char *)); + } else { + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets + */ + vectp = (char **)(destp - (imgp->args->argc + imgp->args->envc + 2) * + sizeof(char *)); + } + + /* + * vectp also becomes our initial stack base + */ + stack_base = (register_t *)vectp; + + stringp = imgp->args->begin_argv; + argc = imgp->args->argc; + envc = imgp->args->envc; + + /* + * Copy out strings - arguments and environment. + */ + copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); + + /* + * Fill in "ps_strings" struct for ps, w, etc. + */ + suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp); + suword(&arginfo->ps_nargvstr, argc); + + /* + * Fill in argument portion of vector table. + */ + for (; argc > 0; --argc) { + suword(vectp++, (long)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* a null vector table pointer separates the argp's from the envp's */ + suword(vectp++, 0); + + suword(&arginfo->ps_envstr, (long)(intptr_t)vectp); + suword(&arginfo->ps_nenvstr, envc); + + /* + * Fill in environment portion of vector table. + */ + for (; envc > 0; --envc) { + suword(vectp++, (long)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* end of vector table is a null pointer */ + suword(vectp, 0); + + return (stack_base); } + + extern int _ucodesel, _udatasel; extern unsigned long linux_sznonrtsigcode; @@ -808,6 +942,29 @@ exec_linux_setregs(struct thread *td, u_long entry, fldcw(&control); } +static int +linux_get_machine(const char **dst) +{ + const char *class; + + switch (cpu_class) { + case CPUCLASS_686: + class = "i686"; + break; + case CPUCLASS_586: + class = "i586"; + break; + case CPUCLASS_486: + class = "i486"; + break; + default: + class = "i386"; + } + *dst = class; + return (0); +} + + struct sysentvec linux_sysvec = { .sv_size = LINUX_SYS_MAXSYSCALL, .sv_table = linux_sysent, @@ -863,7 +1020,7 @@ struct sysentvec elf_linux_sysvec = { .sv_usrstack = USRSTACK, .sv_psstrings = PS_STRINGS, .sv_stackprot = VM_PROT_ALL, - .sv_copyout_strings = exec_copyout_strings, + .sv_copyout_strings = linux_copyout_strings, .sv_setregs = exec_linux_setregs, .sv_fixlimit = NULL, .sv_maxssiz = NULL, @@ -929,6 +1086,9 @@ linux_elf_modevent(module_t mod, int type, void *data) NULL, 1000); linux_exec_tag = EVENTHANDLER_REGISTER(process_exec, linux_proc_exec, NULL, 1000); + linux_get_machine(&linux_platform); + linux_szplatform = roundup(strlen(linux_platform) + 1, + sizeof(char *)); if (bootverbose) printf("Linux ELF exec handler installed\n"); } else diff --git a/sys/ia64/include/elf.h b/sys/ia64/include/elf.h index faab8d1..982629c 100644 --- a/sys/ia64/include/elf.h +++ b/sys/ia64/include/elf.h @@ -82,16 +82,8 @@ __ElfType(Auxinfo); #define AT_BASE 7 /* Interpreter's base address. */ #define AT_FLAGS 8 /* Flags (unused for i386). */ #define AT_ENTRY 9 /* Where interpreter should transfer control. */ -/* - * The following non-standard values are used in Linux ELF binaries. - */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ -#define AT_COUNT 15 /* Count of defined aux entry types. */ +#define AT_COUNT 10 /* Count of defined aux entry types. */ /* * Values for e_flags. diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h index 422a86a..d2b8e12 100644 --- a/sys/powerpc/include/elf.h +++ b/sys/powerpc/include/elf.h @@ -80,6 +80,9 @@ __ElfType(Auxinfo); #define AT_COUNT 13 /* Count of defined aux entry types. */ +/* Used in John Polstra's testbed stuff. */ +#define AT_DEBUG 14 /* Debugging level. */ + /* * Relocation types. */ diff --git a/sys/sparc64/include/elf.h b/sys/sparc64/include/elf.h index 108ade1..c826197 100644 --- a/sys/sparc64/include/elf.h +++ b/sys/sparc64/include/elf.h @@ -78,16 +78,8 @@ __ElfType(Auxinfo); #define AT_BASE 7 /* Interpreter's base address. */ #define AT_FLAGS 8 /* Flags (unused). */ #define AT_ENTRY 9 /* Where interpreter should transfer control. */ -/* - * The following non-standard values are used in Linux ELF binaries. - */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ -#define AT_COUNT 15 /* Count of defined aux entry types. */ +#define AT_COUNT 10 /* Count of defined aux entry types. */ /* Define "machine" characteristics */ #if __ELF_WORD_SIZE == 32 diff --git a/sys/sun4v/include/elf.h b/sys/sun4v/include/elf.h index 108ade1..c826197 100644 --- a/sys/sun4v/include/elf.h +++ b/sys/sun4v/include/elf.h @@ -78,16 +78,8 @@ __ElfType(Auxinfo); #define AT_BASE 7 /* Interpreter's base address. */ #define AT_FLAGS 8 /* Flags (unused). */ #define AT_ENTRY 9 /* Where interpreter should transfer control. */ -/* - * The following non-standard values are used in Linux ELF binaries. - */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ -#define AT_COUNT 15 /* Count of defined aux entry types. */ +#define AT_COUNT 10 /* Count of defined aux entry types. */ /* Define "machine" characteristics */ #if __ELF_WORD_SIZE == 32 -- Have fun! chd
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20081217172047.GA2884>