From 9e67c58735d42020dad4af97b25119b68e26570c Mon Sep 17 00:00:00 2001
From: ramin <lordrasmus@gmail.com>
Date: Wed, 7 Dec 2022 11:59:57 +0100
Subject: [PATCH] add getauxval() implementation

---
 include/sys/auxv.h          | 30 +++++++++++++++++++++++++
 ldso/include/ldso.h         |  5 ++++-
 ldso/ldso/dl-startup.c      | 32 +++++++++++++++++---------
 ldso/ldso/ldso.c            | 45 ++++++++++++++++++-------------------
 libc/misc/Makefile.in       |  2 ++
 libc/misc/auxvt/Makefile.in | 23 +++++++++++++++++++
 libc/misc/auxvt/getauxval.c | 39 ++++++++++++++++++++++++++++++++
 7 files changed, 141 insertions(+), 35 deletions(-)
 create mode 100644 include/sys/auxv.h
 create mode 100644 libc/misc/auxvt/Makefile.in
 create mode 100644 libc/misc/auxvt/getauxval.c

diff --git a/include/sys/auxv.h b/include/sys/auxv.h
new file mode 100644
index 000000000..71860b794
--- /dev/null
+++ b/include/sys/auxv.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 2022 uClibc-ng
+   This file is part of the uClibc-ng Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_AUXV_H
+#define _SYS_AUXV_H 1
+
+__BEGIN_DECLS
+
+/* Return the value associated with an Elf*_auxv_t type from the auxv list
+   passed to the program on startup.  If TYPE was not present in the auxv
+   list, returns zero and sets errno to ENOENT.  */
+extern unsigned long int getauxval (unsigned long int __type) __THROW;
+
+__END_DECLS
+
+#endif /* sys/auxv.h */
diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h
index f19957d1d..c88d6c5e6 100644
--- a/ldso/include/ldso.h
+++ b/ldso/include/ldso.h
@@ -148,6 +148,9 @@ extern int   _dl_debug_file;
 #define NULL ((void *) 0)
 #endif
 
+#define AUX_MAX_AT_ID 40
+extern ElfW(auxv_t) _dl_auxvt[AUX_MAX_AT_ID];
+
 extern void *_dl_malloc(size_t size);
 extern void *_dl_calloc(size_t __nmemb, size_t __size);
 extern void *_dl_realloc(void *__ptr, size_t __size);
@@ -176,7 +179,7 @@ extern void _dl_dprintf(int, const char *, ...);
 #endif
 
 extern void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
-		ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
+		char **envp, char **argv
 		DL_GET_READY_TO_RUN_EXTRA_PARMS);
 
 #ifdef HAVE_DL_INLINES_H
diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c
index a1b3d49fd..e36d688b4 100644
--- a/ldso/ldso/dl-startup.c
+++ b/ldso/ldso/dl-startup.c
@@ -98,6 +98,9 @@
 extern ElfW(Addr) _begin[] attribute_hidden;
 #endif
 
+
+ElfW(auxv_t) _dl_auxvt[AUX_MAX_AT_ID];
+
 #ifdef LDSO_NEED_DPNT
 ElfW(Dyn) *_dl_saved_dpnt = 0;
 #endif
@@ -127,7 +130,7 @@ DL_START(unsigned long args)
 	ElfW(Ehdr) *header;
 	struct elf_resolve tpnt_tmp;
 	struct elf_resolve *tpnt = &tpnt_tmp;
-	ElfW(auxv_t) auxvt[AT_EGID + 1];
+	ElfW(auxv_t) _dl_auxvt_tmp[AUX_MAX_AT_ID];
 	ElfW(Dyn) *dpnt;
 	uint32_t  *p32;
 
@@ -158,7 +161,7 @@ DL_START(unsigned long args)
 
 	/* Place -1 here as a checkpoint.  We later check if it was changed
 	 * when we read in the auxvt */
-	auxvt[AT_UID].a_type = -1;
+	_dl_auxvt_tmp[AT_UID].a_type = -1;
 
 	/* The junk on the stack immediately following the environment is
 	 * the Auxiliary Vector Table.  Read out the elements of the auxvt,
@@ -166,9 +169,11 @@ DL_START(unsigned long args)
 	while (*aux_dat) {
 		ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat;
 
-		if (auxv_entry->a_type <= AT_EGID) {
-			_dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t)));
+		if (auxv_entry->a_type < AUX_MAX_AT_ID) {
+			_dl_memcpy(&(_dl_auxvt_tmp[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t)));
 		}
+		
+		
 		aux_dat += 2;
 	}
 
@@ -183,16 +188,16 @@ DL_START(unsigned long args)
 	 * We use it if the kernel is not passing a valid address through the auxvt.
 	 */
 
-	if (!auxvt[AT_BASE].a_un.a_val)
-		auxvt[AT_BASE].a_un.a_val =  (ElfW(Addr)) &_begin;
+	if (!_dl_auxvt_tmp[AT_BASE].a_un.a_val)
+		_dl_auxvt_tmp[AT_BASE].a_un.a_val =  (ElfW(Addr)) &_begin;
 	/* Note: if the dynamic linker itself is prelinked, the load_addr is 0 */
 	DL_INIT_LOADADDR_BOOT(load_addr, elf_machine_load_address());
 #else
-	if (!auxvt[AT_BASE].a_un.a_val)
-		auxvt[AT_BASE].a_un.a_val = elf_machine_load_address();
-	DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val);
+	if (!_dl_auxvt_tmp[AT_BASE].a_un.a_val)
+		_dl_auxvt_tmp[AT_BASE].a_un.a_val = elf_machine_load_address();
+	DL_INIT_LOADADDR_BOOT(load_addr, _dl_auxvt_tmp[AT_BASE].a_un.a_val);
 #endif
-	header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
+	header = (ElfW(Ehdr) *) _dl_auxvt_tmp[AT_BASE].a_un.a_val;
 
 	/* Check the ELF header to make sure everything looks ok.  */
 	if (!header || header->e_ident[EI_CLASS] != ELF_CLASS ||
@@ -353,8 +358,13 @@ DL_START(unsigned long args)
 #endif
 	__rtld_stack_end = (void *)(argv - 1);
 
+	/*
+	*  now the globals work. so copy the aux vector
+	*/
+	_dl_memcpy( _dl_auxvt, _dl_auxvt_tmp, sizeof( ElfW(auxv_t) ) * AUX_MAX_AT_ID );
+
 	_dl_elf_main = (int (*)(int, char **, char **))
-			_dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv
+			_dl_get_ready_to_run(tpnt, load_addr, envp, argv
 					     DL_GET_READY_TO_RUN_EXTRA_ARGS);
 
 	/* Transfer control to the application.  */
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index b33547670..501676da6 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -350,10 +350,9 @@ static void trace_objects(struct elf_resolve *tpnt, char *str_name)
 static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
 									 DL_LOADADDR_TYPE load_addr,
 									 ElfW(Addr) ldso_mapaddr,
-									 ElfW(auxv_t) auxvt[AT_EGID + 1],
 									 struct dyn_elf *rpnt)
 {
-		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
+		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) _dl_auxvt[AT_BASE].a_un.a_val;
 		ElfW(Phdr) *myppnt = (ElfW(Phdr) *)
 				DL_RELOC_ADDR(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr),
 							  epnt->e_phoff);
@@ -422,7 +421,7 @@ static void _dl_setup_progname(const char *argv0)
 }
 
 void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
-			  ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
+			  char **envp, char **argv
 			  DL_GET_READY_TO_RUN_EXTRA_PARMS)
 {
 	ElfW(Addr) app_mapaddr = 0, ldso_mapaddr = 0;
@@ -461,7 +460,7 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 	_dl_memset(app_tpnt, 0, sizeof(*app_tpnt));
 
 	/* Store the page size for later use */
-	_dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
+	_dl_pagesize = (_dl_auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) _dl_auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE;
 	/* Make it so _dl_malloc can use the page of memory we have already
 	 * allocated.  We shouldn't need to grab any more memory.  This must
 	 * be first since things like _dl_dprintf() use _dl_malloc()...
@@ -504,10 +503,10 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 	 * Note that for SUID programs we ignore the settings in
 	 * LD_LIBRARY_PATH.
 	 */
-	if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) ||
-	    (auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
-	     auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val &&
-	     auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) {
+	if ((_dl_auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) ||
+	    (_dl_auxvt[AT_UID].a_un.a_val != (size_t)-1 &&
+	     _dl_auxvt[AT_UID].a_un.a_val == _dl_auxvt[AT_EUID].a_un.a_val &&
+	     _dl_auxvt[AT_GID].a_un.a_val == _dl_auxvt[AT_EGID].a_un.a_val)) {
 		_dl_secure = 0;
 #ifdef __LDSO_PRELOAD_ENV_SUPPORT__
 		_dl_preload = _dl_getenv("LD_PRELOAD", envp);
@@ -546,7 +545,7 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
 #endif
 
 #ifdef __LDSO_STANDALONE_SUPPORT__
-	if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
+	if (_start == (void *) _dl_auxvt[AT_ENTRY].a_un.a_val) {
 		ElfW(Addr) *aux_dat = (ElfW(Addr) *) argv;
 		int argc = (int) aux_dat[-1];
 
@@ -643,11 +642,11 @@ of this helper program; chances are you did not intend to run this program.\n\
 	 */
 	{
 		unsigned int idx;
-		ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
+		ElfW(Phdr) *phdr = (ElfW(Phdr) *) _dl_auxvt[AT_PHDR].a_un.a_val;
 
-		for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
+		for (idx = 0; idx < _dl_auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
 			if (phdr->p_type == PT_PHDR) {
-				DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
+				DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, _dl_auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
 				break;
 			}
 
@@ -662,8 +661,8 @@ of this helper program; chances are you did not intend to run this program.\n\
 	 */
 	debug_addr = _dl_zalloc(sizeof(struct r_debug));
 
-	ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
-	for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
+	ppnt = (ElfW(Phdr) *) _dl_auxvt[AT_PHDR].a_un.a_val;
+	for (i = 0; i < _dl_auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
 		if (ppnt->p_type == PT_GNU_RELRO) {
 			relro_addr = ppnt->p_vaddr;
 			relro_size = ppnt->p_memsz;
@@ -685,8 +684,8 @@ of this helper program; chances are you did not intend to run this program.\n\
 				int j;
 				ElfW(Phdr) *ppnt_outer = ppnt;
 				_dl_debug_early("calling mprotect on the application program\n");
-				ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
-				for (j = 0; j < auxvt[AT_PHNUM].a_un.a_val; j++, ppnt++) {
+				ppnt = (ElfW(Phdr) *) _dl_auxvt[AT_PHDR].a_un.a_val;
+				for (j = 0; j < _dl_auxvt[AT_PHNUM].a_un.a_val; j++, ppnt++) {
 					if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
 						_dl_mprotect((void *) (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & PAGE_ALIGN),
 							     (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & ADDR_ALIGN) +
@@ -713,8 +712,8 @@ of this helper program; chances are you did not intend to run this program.\n\
 					(unsigned long) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr),
 					ppnt->p_filesz);
 			_dl_loaded_modules->libtype = elf_executable;
-			_dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
-			_dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
+			_dl_loaded_modules->ppnt = (ElfW(Phdr) *) _dl_auxvt[AT_PHDR].a_un.a_val;
+			_dl_loaded_modules->n_phent = _dl_auxvt[AT_PHNUM].a_un.a_val;
 			_dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf));
 			rpnt->dyn = _dl_loaded_modules;
 			app_tpnt->mapaddr = app_mapaddr;
@@ -856,7 +855,7 @@ of this helper program; chances are you did not intend to run this program.\n\
 	}
 #endif
 
-	ldso_mapaddr = (ElfW(Addr)) auxvt[AT_BASE].a_un.a_val;
+	ldso_mapaddr = (ElfW(Addr)) _dl_auxvt[AT_BASE].a_un.a_val;
 	/*
 	 * OK, fix one more thing - set up debug_addr so it will point
 	 * to our chain.  Later we may need to fill in more fields, but this
@@ -1046,7 +1045,7 @@ of this helper program; chances are you did not intend to run this program.\n\
 						if (!ldso_tpnt) {
 							/* Insert the ld.so only once */
 							ldso_tpnt = add_ldso(tpnt, load_addr,
-												 ldso_mapaddr, auxvt, rpnt);
+												 ldso_mapaddr, rpnt);
 						} else {
 							ldso_tpnt->init_flag |= DL_OPENED2;
 						}
@@ -1148,7 +1147,7 @@ of this helper program; chances are you did not intend to run this program.\n\
 	 * again once all libs are loaded.
 	 */
 	if (!ldso_tpnt) {
-		tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, auxvt, rpnt);
+		tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, rpnt);
 		tpnt->usage_count++;
 		nscope_elem++;
 	} else
@@ -1450,11 +1449,11 @@ of this helper program; chances are you did not intend to run this program.\n\
 	_dl_debug_state();
 
 #ifdef __LDSO_STANDALONE_SUPPORT__
-	if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val)
+	if (_start == (void *) _dl_auxvt[AT_ENTRY].a_un.a_val)
 		return (void *) app_tpnt->l_entry;
 	else
 #endif
-		return (void *) auxvt[AT_ENTRY].a_un.a_val;
+		return (void *) _dl_auxvt[AT_ENTRY].a_un.a_val;
 }
 
 #include "dl-hash.c"
diff --git a/libc/misc/Makefile.in b/libc/misc/Makefile.in
index 53bb6d6c8..caf7f1391 100644
--- a/libc/misc/Makefile.in
+++ b/libc/misc/Makefile.in
@@ -5,7 +5,9 @@
 # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
 #
 
+
 include $(top_srcdir)libc/misc/assert/Makefile.in
+include $(top_srcdir)libc/misc/auxvt/Makefile.in
 include $(top_srcdir)libc/misc/ctype/Makefile.in
 include $(top_srcdir)libc/misc/dirent/Makefile.in
 include $(top_srcdir)libc/misc/error/Makefile.in
diff --git a/libc/misc/auxvt/Makefile.in b/libc/misc/auxvt/Makefile.in
new file mode 100644
index 000000000..142ade10c
--- /dev/null
+++ b/libc/misc/auxvt/Makefile.in
@@ -0,0 +1,23 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2008 Erik Andersen <andersen@uclibc.org>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+subdirs += libc/misc/auxvt
+
+CSRC-y := getauxval.c
+
+MISC_AUXVT_DIR := $(top_srcdir)libc/misc/auxvt
+MISC_AUXVT_OUT := $(top_builddir)libc/misc/auxvt
+
+MISC_AUXVT_SRC := $(patsubst %.c,$(MISC_AUXVT_DIR)/%.c,$(CSRC-y))
+MISC_AUXVT_OBJ := $(patsubst %.c,$(MISC_AUXVT_OUT)/%.o,$(CSRC-y))
+
+libc-y += $(MISC_AUXVT_OBJ)
+
+objclean-y += CLEAN_libc/misc/auxvt
+
+CLEAN_libc/misc/auxvt:
+	$(do_rm) $(addprefix $(MISC_AUXVT_OUT)/*., o os)
diff --git a/libc/misc/auxvt/getauxval.c b/libc/misc/auxvt/getauxval.c
new file mode 100644
index 000000000..94ea75384
--- /dev/null
+++ b/libc/misc/auxvt/getauxval.c
@@ -0,0 +1,39 @@
+/*  Copyright (C) 2022     Ramin Seyed Moussavi
+ *  An getauxval() function compatible with the glibc auxv.h
+ *  that is used by uClibc-ng.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, see
+ *  <http://www.gnu.org/licenses/>.
+ */
+
+#include "ldso.h"
+#include "sys/auxv.h"
+
+
+unsigned long int getauxval (unsigned long int __type)
+{
+	if ( __type >= AUX_MAX_AT_ID ){
+		__set_errno (ENOENT);
+		return 0;
+	}
+	
+	if ( _dl_auxvt[__type].a_type == __type){
+		return _dl_auxvt[__type].a_un.a_val;
+	}
+
+	__set_errno (ENOENT);
+	return 0;
+}
+
+
-- 
2.37.2

