Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 2c5153b

Browse files
committed
libc: add getauxval()
Add support for getauxval(). This method allows a program an easy way to retrieve information from the kernel auxiliary vector, and will hopefully replace other clumsy ways of accessing this same information. This particular function was also added to glibc in glibc 2.16. See the following URLs for more details. * http://lwn.net/Articles/519085/ * http://www.gnu.org/software/libc/manual/html_node/Auxiliary-Vector.html This change is a prerequisite for bug 7959813. Bug: http://code.google.com/p/android/issues/detail?id=38441 Change-Id: Iba19d899df334bddc6f4899077ece2fc87564ea8
1 parent 69c8994 commit 2c5153b

File tree

9 files changed

+214
-28
lines changed

9 files changed

+214
-28
lines changed

libc/Android.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ libc_bionic_src_files := \
275275
bionic/dirent.cpp \
276276
bionic/eventfd.cpp \
277277
bionic/__fgets_chk.cpp \
278+
bionic/getauxval.cpp \
278279
bionic/getcwd.cpp \
279280
bionic/libgen.cpp \
280281
bionic/__memcpy_chk.cpp \

libc/bionic/getauxval.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (C) 2013 The Android Open Source Project
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in
12+
* the documentation and/or other materials provided with the
13+
* distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22+
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25+
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26+
* SUCH DAMAGE.
27+
*/
28+
29+
#include <stddef.h>
30+
#include <sys/cdefs.h>
31+
#include <sys/auxv.h>
32+
#include <private/bionic_auxv.h>
33+
#include <elf.h>
34+
35+
__LIBC_HIDDEN__
36+
Elf32_auxv_t* __libc_auxv = NULL;
37+
38+
extern "C" unsigned long int getauxval(unsigned long int type) {
39+
Elf32_auxv_t* v;
40+
41+
for (v = __libc_auxv; v->a_type != AT_NULL; v++) {
42+
if (v->a_type == type) {
43+
return v->a_un.a_val;
44+
}
45+
}
46+
47+
return 0;
48+
}

libc/bionic/libc_init_common.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
#include <bionic_tls.h>
4040
#include <errno.h>
41+
#include <private/bionic_auxv.h>
4142

4243
extern unsigned __get_sp(void);
4344
extern pid_t gettid(void);
@@ -95,6 +96,15 @@ void __libc_init_common(uintptr_t* elf_data) {
9596
__progname = argv[0] ? argv[0] : "<unknown>";
9697
environ = envp;
9798

99+
// The auxiliary vector is at the end of the environment block
100+
while(*envp != NULL) {
101+
envp++;
102+
}
103+
/* The end of the environment block is marked by two NULL pointers */
104+
envp++;
105+
106+
__libc_auxv = (Elf32_auxv_t*) envp;
107+
98108
__system_properties_init(); // Requires 'environ'.
99109
}
100110

libc/bionic/libc_init_static.c

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include <bionic_tls.h>
5050
#include <errno.h>
5151
#include <sys/mman.h>
52+
#include <sys/auxv.h>
5253

5354
// Returns the address of the page containing address 'x'.
5455
#define PAGE_START(x) ((x) & PAGE_MASK)
@@ -65,27 +66,13 @@ static void call_array(void(**list)())
6566
}
6667
}
6768

68-
/*
69-
* Find the value of the AT_* variable passed to us by the kernel.
70-
*/
71-
static unsigned find_aux(unsigned *vecs, unsigned type) {
72-
while (vecs[0]) {
73-
if (vecs[0] == type) {
74-
return vecs[1];
75-
}
76-
vecs += 2;
77-
}
78-
79-
return 0; // should never happen
80-
}
81-
82-
static void apply_gnu_relro(unsigned *vecs) {
69+
static void apply_gnu_relro() {
8370
Elf32_Phdr *phdr_start;
84-
unsigned phdr_ct;
71+
unsigned long int phdr_ct;
8572
Elf32_Phdr *phdr;
8673

87-
phdr_start = (Elf32_Phdr *) find_aux(vecs, AT_PHDR);
88-
phdr_ct = find_aux(vecs, AT_PHNUM);
74+
phdr_start = (Elf32_Phdr *) getauxval(AT_PHDR);
75+
phdr_ct = getauxval(AT_PHNUM);
8976

9077
for (phdr = phdr_start; phdr < (phdr_start + phdr_ct); phdr++) {
9178
if (phdr->p_type != PT_GNU_RELRO)
@@ -108,7 +95,6 @@ __noreturn void __libc_init(uintptr_t *elfdata,
10895
{
10996
int argc;
11097
char **argv, **envp;
111-
unsigned *vecs;
11298

11399
__libc_init_tls(NULL);
114100

@@ -129,21 +115,13 @@ __noreturn void __libc_init(uintptr_t *elfdata,
129115
argv = (char**)(elfdata + 1);
130116
envp = argv + argc + 1;
131117

132-
// The auxiliary vector is at the end of the environment block
133-
vecs = (unsigned *) envp;
134-
while (vecs[0] != 0) {
135-
vecs++;
136-
}
137-
/* The end of the environment block is marked by two NULL pointers */
138-
vecs++;
139-
140118
/* The executable may have its own destructors listed in its .fini_array
141119
* so we need to ensure that these are called when the program exits
142120
* normally.
143121
*/
144122
if (structors->fini_array)
145123
__cxa_atexit(__libc_fini,structors->fini_array,NULL);
146124

147-
apply_gnu_relro(vecs);
125+
apply_gnu_relro();
148126
exit(slingshot(argc, argv, envp));
149127
}

libc/include/elf.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,23 @@
2828
#ifndef _ELF_H
2929
#define _ELF_H
3030

31+
#include <stdint.h>
3132
#include <linux/auxvec.h>
3233
#include <sys/exec_elf.h>
3334

35+
typedef struct {
36+
uint32_t a_type;
37+
union {
38+
uint32_t a_val;
39+
} a_un;
40+
} Elf32_auxv_t;
41+
42+
typedef struct {
43+
uint64_t a_type;
44+
union {
45+
uint64_t a_val;
46+
} a_un;
47+
} Elf64_auxv_t;
48+
3449
#endif /* _ELF_H */
3550

libc/include/sys/auxv.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (C) 2013 The Android Open Source Project
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in
12+
* the documentation and/or other materials provided with the
13+
* distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22+
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25+
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26+
* SUCH DAMAGE.
27+
*/
28+
#ifndef _SYS_AUXV_H_
29+
#define _SYS_AUXV_H_
30+
31+
#include <linux/auxvec.h>
32+
33+
__BEGIN_DECLS
34+
35+
unsigned long int getauxval(unsigned long int type);
36+
37+
__END_DECLS
38+
39+
#endif /* _SYS_AUXV_H_ */

libc/private/bionic_auxv.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (C) 2013 The Android Open Source Project
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions
7+
* are met:
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above copyright
11+
* notice, this list of conditions and the following disclaimer in
12+
* the documentation and/or other materials provided with the
13+
* distribution.
14+
*
15+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22+
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25+
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26+
* SUCH DAMAGE.
27+
*/
28+
#ifndef _SYS_AUXV_H_
29+
#define _SYS_AUXV_H_
30+
31+
#include <elf.h>
32+
33+
__BEGIN_DECLS
34+
35+
extern Elf32_auxv_t* __libc_auxv;
36+
37+
__END_DECLS
38+
39+
#endif /* _SYS_AUXV_H_ */

tests/Android.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ test_c_flags = \
5555
test_src_files = \
5656
dirent_test.cpp \
5757
fenv_test.cpp \
58+
getauxval_test.cpp \
5859
getcwd_test.cpp \
5960
libgen_test.cpp \
6061
pthread_test.cpp \

tests/getauxval_test.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (C) 2013 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <sys/cdefs.h>
18+
#include <features.h>
19+
#include <gtest/gtest.h>
20+
21+
// getauxval() was only added as of glibc version 2.16.
22+
// See: http://lwn.net/Articles/519085/
23+
// Don't try to compile this code on older glibc versions.
24+
25+
#if defined(__BIONIC__)
26+
#define GETAUXVAL_CAN_COMPILE 1
27+
#elif defined(__GLIBC_PREREQ)
28+
#if __GLIBC_PREREQ(2, 16)
29+
#define GETAUXVAL_CAN_COMPILE 1
30+
#endif
31+
#endif
32+
33+
#if defined(GETAUXVAL_CAN_COMPILE)
34+
35+
#include <sys/auxv.h>
36+
37+
TEST(getauxval, expected_values) {
38+
ASSERT_EQ((unsigned long int) 0, getauxval(AT_SECURE));
39+
ASSERT_EQ(getuid(), getauxval(AT_UID));
40+
ASSERT_EQ(geteuid(), getauxval(AT_EUID));
41+
ASSERT_EQ(getgid(), getauxval(AT_GID));
42+
ASSERT_EQ(getegid(), getauxval(AT_EGID));
43+
ASSERT_EQ((unsigned long int) getpagesize(), getauxval(AT_PAGESZ));
44+
45+
ASSERT_NE((unsigned long int) 0, getauxval(AT_PHDR));
46+
ASSERT_NE((unsigned long int) 0, getauxval(AT_PHNUM));
47+
ASSERT_NE((unsigned long int) 0, getauxval(AT_ENTRY));
48+
ASSERT_NE((unsigned long int) 0, getauxval(AT_PAGESZ));
49+
}
50+
51+
TEST(getauxval, unexpected_values) {
52+
ASSERT_EQ((unsigned long int) 0, getauxval(0xdeadbeef));
53+
}
54+
55+
#endif /* GETAUXVAL_CAN_COMPILE */

0 commit comments

Comments
 (0)