-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path__libc_start_main.c
183 lines (149 loc) · 4.2 KB
/
__libc_start_main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
* Copyright 2022-2024 Gaël PORTAY
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <link.h>
extern int next_dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *),
void *);
#include "iamroot.h"
static int __is_in_path_callback(const char *path, void *user)
{
const char *p = (const char *)user;
return strneq(path, p, PATH_MAX);
}
static int __is_in_iamrootlib(const char *pathname)
{
char *lib;
lib = _getenv("IAMROOT_LIB");
if (!lib)
return 0;
return __path_iterate(lib, __is_in_path_callback, (void *)pathname);
}
#if defined __powerpc__ && defined __GLIBC__
#define __ELF_TARGET_CLASS __WORDSIZE
#undef ElfW
/*
* Stolen and hacked from glibc (elf/link.h)
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#define ElfW(type) _ElfW (Elf, __ELF_TARGET_CLASS, type)
/*
* Stolen from glibc (sysdeps/unix/sysv/linux/powerpc/libc-start.c)
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
struct startup_info
{
void *sda_base;
int (*main) (int, char **, char **, void *);
int (*init) (int, char **, char **, void *);
void (*fini) (void);
};
static int (*sym)(int, char **, char **, ElfW(auxv_t) *, void (*)(),
struct startup_info *, char **);
hidden int next___libc_start_main(int argc,
char **argv,
char **ev,
ElfW(auxv_t) *auxvec,
void (*rtld_fini)(void),
struct startup_info *stinfo,
char **stack_on_entry)
{
if (!sym)
sym = dlsym(RTLD_NEXT, "__libc_start_main");
if (!sym)
return __dl_set_errno_and_perror(ENOSYS, -1);
return sym(argc, argv, ev, auxvec, rtld_fini, stinfo, stack_on_entry);
}
#else
static int (*sym)(int (*)(), int, char **, int (*)(int, char **, char **),
void (*)(), void(*)(), void(*)());
hidden int next___libc_start_main(int (*main)(int, char **, char **),
int argc,
char **argv,
int (*init)(int, char **, char **),
void (*fini)(void),
void (*rtld_fini)(void),
void *stack_end)
{
if (!sym)
sym = dlsym(RTLD_NEXT, "__libc_start_main");
if (!sym)
return __dl_set_errno_and_perror(ENOSYS, -1);
return sym(main, argc, argv, init, fini, rtld_fini, stack_end);
}
#endif
static int __dl_iterate_phdr_callback(struct dl_phdr_info *info, size_t size,
void *data)
{
const char *root = (void *)data;
const char *path = info->dlpi_name;
(void)size;
__debug("%s(info: %p { .info->dlpi_name: '%s' }, ...)\n", __func__,
info, info->dlpi_name);
/* in chroot? */
if ((*path != '/') || __strleq(path, root))
return 0;
/* is an host interpreter? */
if (__strneq(path, "/lib/ld") || __strneq(path, "/lib64/ld"))
return 0;
/* is an iamroot library? */
if (__strneq(__basename(path), "libiamroot"))
return 0;
/* is an IAMROOT_LIB? */
if (__is_in_iamrootlib(path))
return 0;
__warning("%s: is not in root directory '%s'\n", path, root);
return 0;
}
#if defined __powerpc__ && defined __GLIBC__
int __libc_start_main(int argc,
char **argv,
char **ev,
ElfW(auxv_t) *auxvec,
void (*rtld_fini)(void),
struct startup_info *stinfo,
char **stack_on_entry)
{
const char *root;
char *argv0;
__debug("%s(argc: %i, argv: { '%s', '%s', ... }, ...)\n", __func__,
argc, argv[0], argv[1]);
argv0 = _getenv("argv0");
if (argv0)
argv[0] = argv0;
root = __getrootdir();
if (!streq(root, "/"))
next_dl_iterate_phdr(__dl_iterate_phdr_callback, (void *)root);
return next___libc_start_main(argc, argv, ev, auxvec, rtld_fini,
stinfo, stack_on_entry);
}
#else
int __libc_start_main(int (*main)(int, char **, char **), int argc,
char **argv, int (*init)(int, char **, char **),
void (*fini)(void), void (*rtld_fini)(void),
void *stack_end)
{
const char *root;
char *argv0;
__debug("%s(main: %p, argc: %i, argv: { '%s', '%s', ... }, ...)\n",
__func__, main, argc, argv[0], argv[1]);
argv0 = _getenv("argv0");
if (argv0)
argv[0] = argv0;
root = __getrootdir();
if (!streq(root, "/"))
next_dl_iterate_phdr(__dl_iterate_phdr_callback, (void *)root);
return next___libc_start_main(main, argc, argv, init, fini, rtld_fini,
stack_end);
}
#endif