git: 10b49af72e5d - stable/13 - linux(4): Deduplicate linux_copyout_auxargs()

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Thu, 29 Jun 2023 08:20:03 UTC
The branch stable/13 has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=10b49af72e5d9f4ac0fdfa9f239f48022604cae5

commit 10b49af72e5d9f4ac0fdfa9f239f48022604cae5
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2023-04-22 19:16:02 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2023-06-29 08:15:26 +0000

    linux(4): Deduplicate linux_copyout_auxargs()
    
    Export default MINSIGSTKSZ value for the x86 until we do not preserve AVX
    registers in the signal context.
    
    Differential Revision:  https://reviews.freebsd.org/D39644
    MFC after:              1 month
    
    (cherry picked from commit 7d8c98398302b939b97310d31883ebdab8c0b938)
---
 sys/amd64/linux/linux.h            |  2 +-
 sys/amd64/linux/linux_sysvec.c     | 56 ++++++---------------------------
 sys/amd64/linux32/linux.h          |  2 +-
 sys/amd64/linux32/linux32_sysvec.c | 64 ++++++--------------------------------
 sys/arm64/linux/linux_sysvec.c     | 58 +++++-----------------------------
 sys/compat/linux/linux_elf.c       | 54 ++++++++++++++++++++++++++++++++
 sys/compat/linux/linux_elf.h       |  2 ++
 sys/i386/linux/linux.h             |  2 +-
 sys/i386/linux/linux_sysvec.c      | 64 +++++++-------------------------------
 9 files changed, 98 insertions(+), 206 deletions(-)

diff --git a/sys/amd64/linux/linux.h b/sys/amd64/linux/linux.h
index b31b520cb573..305c4c43a471 100644
--- a/sys/amd64/linux/linux.h
+++ b/sys/amd64/linux/linux.h
@@ -90,7 +90,7 @@ typedef struct {
 /*
  * Miscellaneous
  */
-#define LINUX_AT_COUNT		20	/* Count of used aux entry types. */
+#define LINUX_AT_COUNT		21	/* Count of used aux entry types. */
 
 struct l___sysctl_args
 {
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
index 2ad1868db8d4..5e7bc96d0148 100644
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -206,52 +206,14 @@ linux_set_fork_retval(struct thread *td)
 	frame->tf_rax = 0;
 }
 
-static int
-linux_copyout_auxargs(struct image_params *imgp, uintptr_t base)
+void
+linux64_arch_copyout_auxargs(struct image_params *imgp, Elf_Auxinfo **pos)
 {
-	Elf_Auxargs *args;
-	Elf_Auxinfo *argarray, *pos;
-	struct proc *p;
-	int error, issetugid;
-
-	p = imgp->proc;
-	args = (Elf64_Auxargs *)imgp->auxargs;
-	argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
-	    M_WAITOK | M_ZERO);
-
-	issetugid = p->p_flag & P_SUGID ? 1 : 0;
-	AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, linux_vdso_base);
-	AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature);
-	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
-	AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz);
-	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
-	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
-	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
-	AUXARGS_ENTRY(pos, AT_BASE, args->base);
-	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
-	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
-	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, issetugid);
-	AUXARGS_ENTRY_PTR(pos, LINUX_AT_RANDOM, imgp->canary);
-	AUXARGS_ENTRY(pos, LINUX_AT_HWCAP2, 0);
-	if (imgp->execpathp != 0)
-		AUXARGS_ENTRY_PTR(pos, LINUX_AT_EXECFN, imgp->execpathp);
-	if (args->execfd != -1)
-		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
-	AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform));
-	AUXARGS_ENTRY(pos, AT_NULL, 0);
-
-	free(imgp->auxargs, M_TEMP);
-	imgp->auxargs = NULL;
-	KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs"));
-
-	error = copyout(argarray, (void *)base,
-	    sizeof(*argarray) * LINUX_AT_COUNT);
-	free(argarray, M_TEMP);
-	return (error);
+
+	AUXARGS_ENTRY((*pos), LINUX_AT_SYSINFO_EHDR, linux_vdso_base);
+	AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP, cpu_feature);
+	AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP2, 0);
+	AUXARGS_ENTRY((*pos), LINUX_AT_PLATFORM, PTROUT(linux_platform));
 }
 
 /*
@@ -622,7 +584,7 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_psstrings	= LINUX_PS_STRINGS_LA48,
 	.sv_psstringssz	= sizeof(struct ps_strings),
 	.sv_stackprot	= VM_PROT_ALL,
-	.sv_copyout_auxargs = linux_copyout_auxargs,
+	.sv_copyout_auxargs = __linuxN(copyout_auxargs),
 	.sv_copyout_strings = __linuxN(copyout_strings),
 	.sv_setregs	= linux_exec_setregs,
 	.sv_fixlimit	= NULL,
@@ -637,6 +599,8 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_schedtail	= linux_schedtail,
 	.sv_thread_detach = linux_thread_detach,
 	.sv_trap	= linux_vsyscall,
+	.sv_hwcap	= NULL,
+	.sv_hwcap2	= NULL,
 	.sv_onexec	= linux_on_exec_vmspace,
 	.sv_onexit	= linux_on_exit,
 	.sv_ontdexit	= linux_thread_dtor,
diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h
index c77897344506..0449790bd981 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -103,7 +103,7 @@ typedef struct {
 /*
  * Miscellaneous
  */
-#define	LINUX_AT_COUNT		21	/* Count of used aux entry types.
+#define	LINUX_AT_COUNT		22	/* Count of used aux entry types.
 					 * Keep this synchronized with
 					 * linux_fixup_elf() code.
 					 */
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index a67f2166deb0..2a7860cc3381 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -139,61 +139,15 @@ LINUX_VDSO_SYM_INTPTR(kern_tsc_selector);
 LINUX_VDSO_SYM_INTPTR(kern_cpu_selector);
 LINUX_VDSO_SYM_CHAR(linux_platform);
 
-static int
-linux_copyout_auxargs(struct image_params *imgp, uintptr_t base)
+void
+linux32_arch_copyout_auxargs(struct image_params *imgp, Elf_Auxinfo **pos)
 {
-	Elf32_Auxargs *args;
-	Elf32_Auxinfo *argarray, *pos;
-	int error, issetugid;
-
-	args = (Elf32_Auxargs *)imgp->auxargs;
-	argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
-	    M_WAITOK | M_ZERO);
-
-	issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0;
-	AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO, __kernel_vsyscall);
-	AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, linux_vdso_base);
-	AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature);
-	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
 
-	/*
-	 * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0,
-	 * as it has appeared in the 2.4.0-rc7 first time.
-	 * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK),
-	 * glibc falls back to the hard-coded CLK_TCK value when aux entry
-	 * is not present.
-	 * Also see linux_times() implementation.
-	 */
-	if (linux_kernver(curthread) >= LINUX_KERNVER_2004000)
-		AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz);
-	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
-	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
-	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
-	AUXARGS_ENTRY(pos, AT_BASE, args->base);
-	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
-	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
-	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, issetugid);
-	AUXARGS_ENTRY(pos, LINUX_AT_RANDOM, PTROUT(imgp->canary));
-	AUXARGS_ENTRY(pos, LINUX_AT_HWCAP2, 0);
-	if (imgp->execpathp != 0)
-		AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, PTROUT(imgp->execpathp));
-	if (args->execfd != -1)
-		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
-	AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform));
-	AUXARGS_ENTRY(pos, AT_NULL, 0);
-
-	free(imgp->auxargs, M_TEMP);
-	imgp->auxargs = NULL;
-	KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs"));
-
-	error = copyout(argarray, (void *)base,
-	    sizeof(*argarray) * LINUX_AT_COUNT);
-	free(argarray, M_TEMP);
-	return (error);
+	AUXARGS_ENTRY((*pos), LINUX_AT_SYSINFO, __kernel_vsyscall);
+	AUXARGS_ENTRY((*pos), LINUX_AT_SYSINFO_EHDR, linux_vdso_base);
+	AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP, cpu_feature);
+	AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP2, 0);
+	AUXARGS_ENTRY((*pos), LINUX_AT_PLATFORM, PTROUT(linux_platform));
 }
 
 static void
@@ -847,7 +801,7 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_psstrings	= LINUX32_PS_STRINGS,
 	.sv_psstringssz	= sizeof(struct linux32_ps_strings),
 	.sv_stackprot	= VM_PROT_ALL,
-	.sv_copyout_auxargs = linux_copyout_auxargs,
+	.sv_copyout_auxargs = __linuxN(copyout_auxargs),
 	.sv_copyout_strings = linux_copyout_strings,
 	.sv_setregs	= linux_exec_setregs,
 	.sv_fixlimit	= linux32_fixlimit,
@@ -862,6 +816,8 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_schedtail	= linux_schedtail,
 	.sv_thread_detach = linux_thread_detach,
 	.sv_trap	= NULL,
+	.sv_hwcap	= NULL,
+	.sv_hwcap2	= NULL,
 	.sv_onexec	= linux_on_exec_vmspace,
 	.sv_onexit	= linux_on_exit,
 	.sv_ontdexit	= linux_thread_dtor,
diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
index 7e1e35e6bae3..709566ee15bc 100644
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -115,7 +115,6 @@ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
 
 /* DTrace probes */
 LIN_SDT_PROBE_DEFINE0(sysvec, linux_exec_setregs, todo);
-LIN_SDT_PROBE_DEFINE0(sysvec, linux_copyout_auxargs, todo);
 
 LINUX_VDSO_SYM_CHAR(linux_platform);
 LINUX_VDSO_SYM_INTPTR(kern_timekeep_base);
@@ -160,55 +159,14 @@ linux_set_syscall_retval(struct thread *td, int error)
 	}
 }
 
-static int
-linux_copyout_auxargs(struct image_params *imgp, uintptr_t base)
+void
+linux64_arch_copyout_auxargs(struct image_params *imgp, Elf_Auxinfo **pos)
 {
-	Elf_Auxargs *args;
-	Elf_Auxinfo *argarray, *pos;
-	struct proc *p;
-	int error, issetugid;
-
-	LIN_SDT_PROBE0(sysvec, linux_copyout_auxargs, todo);
-	p = imgp->proc;
-
-	args = (Elf64_Auxargs *)imgp->auxargs;
-	argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
-	    M_WAITOK | M_ZERO);
-
-	issetugid = p->p_flag & P_SUGID ? 1 : 0;
-	AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, linux_vdso_base);
-	AUXARGS_ENTRY(pos, LINUX_AT_MINSIGSTKSZ, LINUX_MINSIGSTKSZ);
-	AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, *imgp->sysent->sv_hwcap);
-	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
-	AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz);
-	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
-	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
-	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
-	AUXARGS_ENTRY(pos, AT_BASE, args->base);
-	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
-	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
-	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, issetugid);
-	AUXARGS_ENTRY_PTR(pos, LINUX_AT_RANDOM, imgp->canary);
-	AUXARGS_ENTRY(pos, LINUX_AT_HWCAP2, *imgp->sysent->sv_hwcap2);
-	if (imgp->execpathp != 0)
-		AUXARGS_ENTRY_PTR(pos, LINUX_AT_EXECFN, imgp->execpathp);
-	if (args->execfd != -1)
-		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
-	AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(linux_platform));
-	AUXARGS_ENTRY(pos, AT_NULL, 0);
-
-	free(imgp->auxargs, M_TEMP);
-	imgp->auxargs = NULL;
-	KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs"));
-
-	error = copyout(argarray, (void *)base,
-	    sizeof(*argarray) * LINUX_AT_COUNT);
-	free(argarray, M_TEMP);
-	return (error);
+
+	AUXARGS_ENTRY((*pos), LINUX_AT_SYSINFO_EHDR, linux_vdso_base);
+	AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP, *imgp->sysent->sv_hwcap);
+	AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP2, *imgp->sysent->sv_hwcap2);
+	AUXARGS_ENTRY((*pos), LINUX_AT_PLATFORM, PTROUT(linux_platform));
 }
 
 /*
@@ -423,7 +381,7 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_psstrings	= LINUX_PS_STRINGS,
 	.sv_psstringssz	= sizeof(struct ps_strings),
 	.sv_stackprot	= VM_PROT_READ | VM_PROT_WRITE,
-	.sv_copyout_auxargs = linux_copyout_auxargs,
+	.sv_copyout_auxargs = __linuxN(copyout_auxargs),
 	.sv_copyout_strings = __linuxN(copyout_strings),
 	.sv_setregs	= linux_exec_setregs,
 	.sv_fixlimit	= NULL,
diff --git a/sys/compat/linux/linux_elf.c b/sys/compat/linux/linux_elf.c
index 43df9508d470..9b2c38aba444 100644
--- a/sys/compat/linux/linux_elf.c
+++ b/sys/compat/linux/linux_elf.c
@@ -488,3 +488,57 @@ linux_trans_osrel(const Elf_Note *note, int32_t *osrel)
 
 	return (true);
 }
+
+int
+__linuxN(copyout_auxargs)(struct image_params *imgp, uintptr_t base)
+{
+	Elf_Auxargs *args;
+	Elf_Auxinfo *aarray, *pos;
+	struct proc *p;
+	int error, issetugid;
+
+	p = imgp->proc;
+	issetugid = p->p_flag & P_SUGID ? 1 : 0;
+	args = imgp->auxargs;
+	aarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
+	    M_WAITOK | M_ZERO);
+
+	__linuxN(arch_copyout_auxargs)(imgp, &pos);
+	/*
+	 * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0,
+	 * as it has appeared in the 2.4.0-rc7 first time.
+	 * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK),
+	 * glibc falls back to the hard-coded CLK_TCK value when aux entry
+	 * is not present.
+	 * Also see linux_times() implementation.
+	 */
+	if (linux_kernver(curthread) >= LINUX_KERNVER_2004000)
+		AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz);
+	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
+	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
+	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
+	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
+	AUXARGS_ENTRY(pos, AT_BASE, args->base);
+	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
+	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
+	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, issetugid);
+	AUXARGS_ENTRY_PTR(pos, LINUX_AT_RANDOM, imgp->canary);
+	if (imgp->execpathp != 0)
+		AUXARGS_ENTRY(pos, LINUX_AT_EXECFN, PTROUT(imgp->execpathp));
+	if (args->execfd != -1)
+		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
+	AUXARGS_ENTRY(pos, LINUX_AT_MINSIGSTKSZ, LINUX_MINSIGSTKSZ);
+	AUXARGS_ENTRY(pos, AT_NULL, 0);
+
+	free(imgp->auxargs, M_TEMP);
+	imgp->auxargs = NULL;
+	KASSERT(pos - aarray <= LINUX_AT_COUNT, ("Too many auxargs"));
+
+	error = copyout(aarray, PTRIN(base), sizeof(*aarray) * LINUX_AT_COUNT);
+	free(aarray, M_TEMP);
+	return (error);
+}
diff --git a/sys/compat/linux/linux_elf.h b/sys/compat/linux/linux_elf.h
index 87b21c4a14b2..8f134cd4e233 100644
--- a/sys/compat/linux/linux_elf.h
+++ b/sys/compat/linux/linux_elf.h
@@ -42,6 +42,8 @@ struct note_info_list;
 
 void 	__linuxN(prepare_notes)(struct thread *, struct note_info_list *,
 	    size_t *);
+void	__linuxN(arch_copyout_auxargs)(struct image_params *, Elf_Auxinfo **);
+int	__linuxN(copyout_auxargs)(struct image_params *, uintptr_t);
 int	__linuxN(copyout_strings)(struct image_params *, uintptr_t *);
 bool	linux_trans_osrel(const Elf_Note *note, int32_t *osrel);
 
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h
index 43bf3ca126b6..61ab5e40fe1d 100644
--- a/sys/i386/linux/linux.h
+++ b/sys/i386/linux/linux.h
@@ -95,7 +95,7 @@ typedef struct {
 /*
  * Miscellaneous
  */
-#define LINUX_AT_COUNT		20	/* Count of used aux entry types.
+#define LINUX_AT_COUNT		21	/* Count of used aux entry types.
 					 * Keep this synchronized with
 					 * linux_fixup_elf() code.
 					 */
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index ce61cfdec205..fb6f01adf66d 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -138,60 +138,14 @@ linux_fixup(uintptr_t *stack_base, struct image_params *imgp)
 	return (0);
 }
 
-static int
-linux_copyout_auxargs(struct image_params *imgp, uintptr_t base)
+void
+linux32_arch_copyout_auxargs(struct image_params *imgp, Elf_Auxinfo **pos)
 {
-	Elf32_Auxargs *args;
-	Elf32_Auxinfo *argarray, *pos;
-	int error, issetugid;
-
-	issetugid = imgp->proc->p_flag & P_SUGID ? 1 : 0;
-	args = (Elf32_Auxargs *)imgp->auxargs;
-	argarray = pos = malloc(LINUX_AT_COUNT * sizeof(*pos), M_TEMP,
-	    M_WAITOK | M_ZERO);
-
-	AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO_EHDR, linux_vdso_base);
-	AUXARGS_ENTRY(pos, LINUX_AT_SYSINFO, __kernel_vsyscall);
-	AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature);
 
-	/*
-	 * Do not export AT_CLKTCK when emulating Linux kernel prior to 2.4.0,
-	 * as it has appeared in the 2.4.0-rc7 first time.
-	 * Being exported, AT_CLKTCK is returned by sysconf(_SC_CLK_TCK),
-	 * glibc falls back to the hard-coded CLK_TCK value when aux entry
-	 * is not present.
-	 * Also see linux_times() implementation.
-	 */
-	if (linux_kernver(curthread) >= LINUX_KERNVER_2004000)
-		AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, stclohz);
-	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
-	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
-	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
-	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
-	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
-	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
-	AUXARGS_ENTRY(pos, AT_BASE, args->base);
-	AUXARGS_ENTRY(pos, LINUX_AT_SECURE, issetugid);
-	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_PLATFORM, PTROUT(linux_platform));
-	AUXARGS_ENTRY_PTR(pos, LINUX_AT_RANDOM, imgp->canary);
-	if (imgp->execpathp != 0)
-		AUXARGS_ENTRY_PTR(pos, LINUX_AT_EXECFN, imgp->execpathp);
-	if (args->execfd != -1)
-		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
-	AUXARGS_ENTRY(pos, AT_NULL, 0);
-
-	free(imgp->auxargs, M_TEMP);
-	imgp->auxargs = NULL;
-	KASSERT(pos - argarray <= LINUX_AT_COUNT, ("Too many auxargs"));
-
-	error = copyout(argarray, (void *)base,
-	    sizeof(*argarray) * LINUX_AT_COUNT);
-	free(argarray, M_TEMP);
-	return (error);
+	AUXARGS_ENTRY((*pos), LINUX_AT_SYSINFO_EHDR, linux_vdso_base);
+	AUXARGS_ENTRY((*pos), LINUX_AT_SYSINFO, __kernel_vsyscall);
+	AUXARGS_ENTRY((*pos), LINUX_AT_HWCAP, cpu_feature);
+	AUXARGS_ENTRY((*pos), LINUX_AT_PLATFORM, PTROUT(linux_platform));
 }
 
 static void
@@ -649,6 +603,8 @@ struct sysentvec linux_sysvec = {
 	.sv_schedtail	= linux_schedtail,
 	.sv_thread_detach = linux_thread_detach,
 	.sv_trap	= NULL,
+	.sv_hwcap	= NULL,
+	.sv_hwcap2	= NULL,
 	.sv_onexec	= linux_on_exec_vmspace,
 	.sv_onexit	= linux_on_exit,
 	.sv_ontdexit	= linux_thread_dtor,
@@ -677,7 +633,7 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_psstrings	= LINUX_PS_STRINGS,
 	.sv_psstringssz	= sizeof(struct ps_strings),
 	.sv_stackprot	= VM_PROT_ALL,
-	.sv_copyout_auxargs = linux_copyout_auxargs,
+	.sv_copyout_auxargs = __linuxN(copyout_auxargs),
 	.sv_copyout_strings = __linuxN(copyout_strings),
 	.sv_setregs	= linux_exec_setregs,
 	.sv_fixlimit	= NULL,
@@ -692,6 +648,8 @@ struct sysentvec elf_linux_sysvec = {
 	.sv_schedtail	= linux_schedtail,
 	.sv_thread_detach = linux_thread_detach,
 	.sv_trap	= NULL,
+	.sv_hwcap	= NULL,
+	.sv_hwcap2	= NULL,
 	.sv_onexec	= linux_on_exec_vmspace,
 	.sv_onexit	= linux_on_exit,
 	.sv_ontdexit	= linux_thread_dtor,