1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright (c) 1988 AT&T
29 * All Rights Reserved
30 */
31 /*
32 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
33 * Copyright 2022 Oxide Computer Company
34 */
35
36 /*
37 * i386 specific setup routine - relocate ld.so's symbols, setup its
38 * environment, map in loadable sections of the executable.
39 *
40 * Takes base address ld.so was loaded at, address of ld.so's dynamic
41 * structure, address of process environment pointers, address of auxiliary
42 * vector and * argv[0] (process name).
43 * If errors occur, send process signal - otherwise
44 * return executable's entry point to the bootstrap routine.
45 */
46
47 #include <signal.h>
48 #include <stdlib.h>
49 #include <sys/auxv.h>
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #include <link.h>
53 #include <dlfcn.h>
54 #include "_rtld.h"
55 #include "_audit.h"
56 #include "msg.h"
57
58 /* VARARGS */
59 unsigned long
_setup(Boot * ebp,Dyn * ld_dyn)60 _setup(Boot *ebp, Dyn *ld_dyn)
61 {
62 ulong_t reladdr, relcount, ld_base = 0;
63 ulong_t relent = 0;
64 ulong_t strtab, soname, interp_base = 0;
65 char *_rt_name, **_envp, **_argv;
66 int _syspagsz = 0, fd = -1;
67 uint_t _flags = 0;
68 uint_t hwcap[3] = { 0, 0, 0 };
69 Dyn *dyn_ptr;
70 Phdr *phdr = NULL;
71 Rt_map *lmp;
72 auxv_t *auxv, *_auxv;
73 uid_t uid = (uid_t)-1, euid = (uid_t)-1;
74 gid_t gid = (gid_t)-1, egid = (gid_t)-1;
75 char *_platform = NULL, *_execname = NULL, *_emulator = NULL;
76 int auxflags = -1;
77
78 /*
79 * Scan the bootstrap structure to pick up the basics.
80 */
81 for (; ebp->eb_tag != EB_NULL; ebp++)
82 switch (ebp->eb_tag) {
83 case EB_LDSO_BASE:
84 ld_base = (unsigned long)ebp->eb_un.eb_val;
85 break;
86 case EB_ARGV:
87 _argv = (char **)ebp->eb_un.eb_ptr;
88 break;
89 case EB_ENVP:
90 _envp = (char **)ebp->eb_un.eb_ptr;
91 break;
92 case EB_AUXV:
93 _auxv = (auxv_t *)ebp->eb_un.eb_ptr;
94 break;
95 case EB_PAGESIZE:
96 _syspagsz = (int)ebp->eb_un.eb_val;
97 break;
98 }
99
100 /*
101 * Search the aux. vector for the information passed by exec.
102 */
103 for (auxv = _auxv; auxv->a_type != AT_NULL; auxv++) {
104 switch (auxv->a_type) {
105 case AT_EXECFD:
106 /* this is the old exec that passes a file descriptor */
107 fd = (int)auxv->a_un.a_val;
108 break;
109 case AT_FLAGS:
110 /* processor flags (MAU available, etc) */
111 _flags = auxv->a_un.a_val;
112 break;
113 case AT_PAGESZ:
114 /* system page size */
115 _syspagsz = (int)auxv->a_un.a_val;
116 break;
117 case AT_PHDR:
118 /* address of the segment table */
119 phdr = (Phdr *)auxv->a_un.a_ptr;
120 break;
121 case AT_BASE:
122 /* interpreter base address */
123 if (ld_base == 0)
124 ld_base = auxv->a_un.a_val;
125 interp_base = auxv->a_un.a_val;
126 break;
127 case AT_SUN_UID:
128 /* effective user id for the executable */
129 euid = (uid_t)auxv->a_un.a_val;
130 break;
131 case AT_SUN_RUID:
132 /* real user id for the executable */
133 uid = (uid_t)auxv->a_un.a_val;
134 break;
135 case AT_SUN_GID:
136 /* effective group id for the executable */
137 egid = (gid_t)auxv->a_un.a_val;
138 break;
139 case AT_SUN_RGID:
140 /* real group id for the executable */
141 gid = (gid_t)auxv->a_un.a_val;
142 break;
143 case AT_SUN_PLATFORM:
144 /* platform name */
145 _platform = auxv->a_un.a_ptr;
146 break;
147 case AT_SUN_EXECNAME:
148 /* full pathname of execed object */
149 _execname = auxv->a_un.a_ptr;
150 break;
151 case AT_SUN_AUXFLAGS:
152 /* auxiliary flags */
153 auxflags = (int)auxv->a_un.a_val;
154 break;
155 case AT_SUN_HWCAP:
156 /* hardware capabilities */
157 hwcap[0] = (uint_t)auxv->a_un.a_val;
158 break;
159 case AT_SUN_HWCAP2:
160 /* hardware capabilities */
161 hwcap[1] = (uint_t)auxv->a_un.a_val;
162 break;
163 case AT_SUN_HWCAP3:
164 /* hardware capabilities */
165 hwcap[2] = (uint_t)auxv->a_un.a_val;
166 break;
167 case AT_SUN_EMULATOR:
168 /* name of emulation library, if any */
169 _emulator = auxv->a_un.a_ptr;
170 break;
171 }
172 }
173
174 /*
175 * Get needed info from ld.so's dynamic structure.
176 */
177 /* LINTED */
178 dyn_ptr = (Dyn *)((char *)ld_dyn + ld_base);
179 for (ld_dyn = dyn_ptr; ld_dyn->d_tag != DT_NULL; ld_dyn++) {
180 switch (ld_dyn->d_tag) {
181 case DT_REL:
182 reladdr = ld_dyn->d_un.d_ptr + ld_base;
183 break;
184 case DT_RELCOUNT:
185 relcount = ld_dyn->d_un.d_val;
186 break;
187 case DT_RELENT:
188 relent = ld_dyn->d_un.d_val;
189 break;
190 case DT_STRTAB:
191 strtab = ld_dyn->d_un.d_ptr + ld_base;
192 break;
193 case DT_SONAME:
194 soname = ld_dyn->d_un.d_val;
195 break;
196 }
197 }
198 _rt_name = (char *)strtab + soname;
199
200 /*
201 * If we don't have a RELENT, just assume the size.
202 */
203 if (relent == 0)
204 relent = sizeof (Rel);
205
206 /*
207 * As all global symbol references within ld.so.1 are protected
208 * (symbolic), only RELATIVE and JMPSLOT relocations should be left
209 * to process at runtime. Process all relative relocations now.
210 */
211 for (; relcount; relcount--) {
212 ulong_t roffset;
213
214 roffset = ((Rel *)reladdr)->r_offset + ld_base;
215 *((ulong_t *)roffset) += ld_base;
216 reladdr += relent;
217 }
218
219 /*
220 * If an emulation library is being used, use that as the linker's
221 * effective executable name. The real executable is not linked by this
222 * linker.
223 */
224 if (_emulator != NULL) {
225 _execname = _emulator;
226 rtld_flags2 |= RT_FL2_BRANDED;
227 }
228
229 /*
230 * Initialize the dyn_plt_ent_size field. It currently contains the
231 * size of the dyn_plt_template. It still needs to be aligned and have
232 * space for the 'dyn_data' area added.
233 */
234 dyn_plt_ent_size = ROUND(dyn_plt_ent_size, M_WORD_ALIGN) +
235 sizeof (uintptr_t) + sizeof (uintptr_t) + sizeof (ulong_t) +
236 sizeof (ulong_t) + sizeof (Sym);
237
238 /*
239 * Continue with generic startup processing.
240 */
241 if ((lmp = setup((char **)_envp, (auxv_t *)_auxv, _flags, _platform,
242 _syspagsz, _rt_name, ld_base, interp_base, fd, phdr,
243 _execname, _argv, uid, euid, gid, egid, auxflags,
244 hwcap)) == NULL) {
245 rtldexit(&lml_main, 1);
246 }
247
248 return (LM_ENTRY_PT(lmp)());
249 }
250