1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <elf.h>
21: #include <errno.h>
22: #include <fcntl.h>
23: #include <libintl.h>
24: #include <stdbool.h>
25: #include <stdlib.h>
26: #include <string.h>
27: #include <unistd.h>
28: #include <ldsodefs.h>
29: #include <bits/wordsize.h>
30: #include <sys/mman.h>
31: #include <sys/param.h>
32: #include <sys/stat.h>
33: #include <sys/types.h>
34: #include "dynamic-link.h"
35: #include <abi-tag.h>
36: #include <stackinfo.h>
37: #include <caller.h>
38: #include <sysdep.h>
39:
40: #include <dl-dst.h>
41:
42:
43: #ifndef MAP_FILE
44: # define MAP_FILE 0
45: #endif
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58: #ifndef MAP_COPY
59: # ifdef MAP_DENYWRITE
60: # define MAP_COPY (MAP_PRIVATE | MAP_DENYWRITE)
61: # else
62: # define MAP_COPY MAP_PRIVATE
63: # endif
64: #endif
65:
66:
67:
68:
69:
70:
71: #ifndef MAP_BASE_ADDR
72: # define MAP_BASE_ADDR(l) 0
73: #endif
74:
75:
76: #include <endian.h>
77: #if BYTE_ORDER == BIG_ENDIAN
78: # define byteorder ELFDATA2MSB
79: #elif BYTE_ORDER == LITTLE_ENDIAN
80: # define byteorder ELFDATA2LSB
81: #else
82: # error "Unknown BYTE_ORDER " BYTE_ORDER
83: # define byteorder ELFDATANONE
84: #endif
85:
86: #define STRING(x) __STRING (x)
87:
88: #ifdef MAP_ANON
89:
90: # define ANONFD -1
91: #else
92: int _dl_zerofd = -1;
93: # define ANONFD _dl_zerofd
94: #endif
95:
96:
97:
98: #ifdef ELF_PREFERRED_ADDRESS_DATA
99: ELF_PREFERRED_ADDRESS_DATA;
100: #endif
101: #ifndef ELF_PREFERRED_ADDRESS
102: # define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
103: #endif
104: #ifndef ELF_FIXED_ADDRESS
105: # define ELF_FIXED_ADDRESS(loader, mapstart) ((void) 0)
106: #endif
107:
108:
109: int __stack_prot attribute_hidden attribute_relro
110: #if _STACK_GROWS_DOWN && defined PROT_GROWSDOWN
111: = PROT_GROWSDOWN;
112: #elif _STACK_GROWS_UP && defined PROT_GROWSUP
113: = PROT_GROWSUP;
114: #else
115: = 0;
116: #endif
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133: struct filebuf
134: {
135: ssize_t len;
136: #if __WORDSIZE == 32
137: # define FILEBUF_SIZE 512
138: #else
139: # define FILEBUF_SIZE 832
140: #endif
141: char buf[FILEBUF_SIZE] __attribute__ ((aligned (__alignof (ElfW(Ehdr)))));
142: };
143:
144:
145: static struct r_search_path_struct env_path_list attribute_relro;
146:
147:
148: static const struct r_strlenpair *capstr attribute_relro;
149: static size_t ncapstr attribute_relro;
150: static size_t max_capstrlen attribute_relro;
151:
152:
153:
154: #include "trusted-dirs.h"
155:
156: static const char system_dirs[] = SYSTEM_DIRS;
157: static const size_t system_dirs_len[] =
158: {
159: SYSTEM_DIRS_LEN
160: };
161: #define nsystem_dirs_len \
162: (sizeof (system_dirs_len) / sizeof (system_dirs_len[0]))
163:
164:
165:
166: static inline char *
167: local_strdup (const char *s)
168: {
169: size_t len = strlen (s) + 1;
170: void *new = malloc (len);
171:
172: if (new == NULL)
173: return NULL;
174:
175: return (char *) memcpy (new, s, len);
176: }
177:
178:
179: static size_t
180: is_dst (const char *start, const char *name, const char *str,
181: int is_path, int secure)
182: {
183: size_t len;
184: bool is_curly = false;
185:
186: if (name[0] == '{')
187: {
188: is_curly = true;
189: ++name;
190: }
191:
192: len = 0;
193: while (name[len] == str[len] && name[len] != '\0')
194: ++len;
195:
196: if (is_curly)
197: {
198: if (name[len] != '}')
199: return 0;
200:
201:
202: --name;
203:
204: len += 2;
205: }
206: else if (name[len] != '\0' && name[len] != '/'
207: && (!is_path || name[len] != ':'))
208: return 0;
209:
210: if (__builtin_expect (secure, 0)
211: && ((name[len] != '\0' && (!is_path || name[len] != ':'))
212: || (name != start + 1 && (!is_path || name[-2] != ':'))))
213: return 0;
214:
215: return len;
216: }
217:
218:
219: size_t
220: _dl_dst_count (const char *name, int is_path)
221: {
222: const char *const start = name;
223: size_t cnt = 0;
224:
225: do
226: {
227: size_t len;
228:
229:
230:
231: ++name;
232: if ((len = is_dst (start, name, "ORIGIN", is_path,
233: INTUSE(__libc_enable_secure))) != 0
234: || (len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0
235: || (len = is_dst (start, name, "LIB", is_path, 0)) != 0)
236: ++cnt;
237:
238: name = strchr (name + len, '$');
239: }
240: while (name != NULL);
241:
242: return cnt;
243: }
244:
245:
246: char *
247: _dl_dst_substitute (struct link_map *l, const char *name, char *result,
248: int is_path)
249: {
250: const char *const start = name;
251: char *last_elem, *wp;
252:
253:
254:
255:
256:
257: last_elem = wp = result;
258:
259: do
260: {
261: if (__builtin_expect (*name == '$', 0))
262: {
263: const char *repl = NULL;
264: size_t len;
265:
266: ++name;
267: if ((len = is_dst (start, name, "ORIGIN", is_path,
268: INTUSE(__libc_enable_secure))) != 0)
269: {
270: #ifndef SHARED
271: if (l == NULL)
272: repl = _dl_get_origin ();
273: else
274: #endif
275: repl = l->l_origin;
276: }
277: else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0)
278: repl = GLRO(dl_platform);
279: else if ((len = is_dst (start, name, "LIB", is_path, 0)) != 0)
280: repl = DL_DST_LIB;
281:
282: if (repl != NULL && repl != (const char *) -1)
283: {
284: wp = __stpcpy (wp, repl);
285: name += len;
286: }
287: else if (len > 1)
288: {
289:
290:
291: wp = last_elem;
292: name += len;
293: while (*name != '\0' && (!is_path || *name != ':'))
294: ++name;
295: }
296: else
297:
298: *wp++ = '$';
299: }
300: else
301: {
302: *wp++ = *name++;
303: if (is_path && *name == ':')
304: last_elem = wp;
305: }
306: }
307: while (*name != '\0');
308:
309: *wp = '\0';
310:
311: return result;
312: }
313:
314:
315:
316:
317:
318:
319:
320: static char *
321: expand_dynamic_string_token (struct link_map *l, const char *s)
322: {
323:
324:
325:
326:
327: size_t cnt;
328: size_t total;
329: char *result;
330:
331:
332: cnt = DL_DST_COUNT (s, 1);
333:
334:
335: if (__builtin_expect (cnt, 0) == 0)
336: return local_strdup (s);
337:
338:
339: total = DL_DST_REQUIRED (l, s, strlen (s), cnt);
340:
341:
342: result = (char *) malloc (total + 1);
343: if (result == NULL)
344: return NULL;
345:
346: return _dl_dst_substitute (l, s, result, 1);
347: }
348:
349:
350:
351:
352:
353:
354: static void
355: internal_function
356: add_name_to_object (struct link_map *l, const char *name)
357: {
358: struct libname_list *lnp, *lastp;
359: struct libname_list *newname;
360: size_t name_len;
361:
362: lastp = NULL;
363: for (lnp = l->l_libname; lnp != NULL; lastp = lnp, lnp = lnp->next)
364: if (strcmp (name, lnp->name) == 0)
365: return;
366:
367: name_len = strlen (name) + 1;
368: newname = (struct libname_list *) malloc (sizeof *newname + name_len);
369: if (newname == NULL)
370: {
371:
372: _dl_signal_error (ENOMEM, name, NULL, N_("cannot allocate name record"));
373: return;
374: }
375:
376: assert (lastp != NULL);
377:
378: newname->name = memcpy (newname + 1, name, name_len);
379: newname->next = NULL;
380: newname->dont_free = 0;
381: lastp->next = newname;
382: }
383:
384:
385: static struct r_search_path_struct rtld_search_dirs attribute_relro;
386:
387: static size_t max_dirnamelen;
388:
389: static struct r_search_path_elem **
390: fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
391: int check_trusted, const char *what, const char *where)
392: {
393: char *cp;
394: size_t nelems = 0;
395:
396: while ((cp = __strsep (&rpath, sep)) != NULL)
397: {
398: struct r_search_path_elem *dirp;
399: size_t len = strlen (cp);
400:
401:
402:
403: if (len == 0)
404: {
405: static const char curwd[] = "./";
406: cp = (char *) curwd;
407: }
408:
409:
410: while (len > 1 && cp[len - 1] == '/')
411: --len;
412:
413:
414: if (len > 0 && cp[len - 1] != '/')
415: cp[len++] = '/';
416:
417:
418: if (__builtin_expect (check_trusted, 0))
419: {
420: const char *trun = system_dirs;
421: size_t idx;
422: int unsecure = 1;
423:
424:
425: if (cp[0] == '/')
426: {
427: for (idx = 0; idx < nsystem_dirs_len; ++idx)
428: {
429: if (len == system_dirs_len[idx]
430: && memcmp (trun, cp, len) == 0)
431: {
432:
433: unsecure = 0;
434: break;
435: }
436:
437: trun += system_dirs_len[idx] + 1;
438: }
439: }
440:
441: if (unsecure)
442:
443: continue;
444: }
445:
446:
447: for (dirp = GL(dl_all_dirs); dirp != NULL; dirp = dirp->next)
448: if (dirp->dirnamelen == len && memcmp (cp, dirp->dirname, len) == 0)
449: break;
450:
451: if (dirp != NULL)
452: {
453:
454: size_t cnt;
455: for (cnt = 0; cnt < nelems; ++cnt)
456: if (result[cnt] == dirp)
457: break;
458:
459: if (cnt == nelems)
460: result[nelems++] = dirp;
461: }
462: else
463: {
464: size_t cnt;
465: enum r_dir_status init_val;
466: size_t where_len = where ? strlen (where) + 1 : 0;
467:
468:
469: dirp = (struct r_search_path_elem *)
470: malloc (sizeof (*dirp) + ncapstr * sizeof (enum r_dir_status)
471: + where_len + len + 1);
472: if (dirp == NULL)
473: _dl_signal_error (ENOMEM, NULL, NULL,
474: N_("cannot create cache for search path"));
475:
476: dirp->dirname = ((char *) dirp + sizeof (*dirp)
477: + ncapstr * sizeof (enum r_dir_status));
478: *((char *) __mempcpy ((char *) dirp->dirname, cp, len)) = '\0';
479: dirp->dirnamelen = len;
480:
481: if (len > max_dirnamelen)
482: max_dirnamelen = len;
483:
484:
485:
486:
487: init_val = cp[0] != '/' ? existing : unknown;
488: for (cnt = 0; cnt < ncapstr; ++cnt)
489: dirp->status[cnt] = init_val;
490:
491: dirp->what = what;
492: if (__builtin_expect (where != NULL, 1))
493: dirp->where = memcpy ((char *) dirp + sizeof (*dirp) + len + 1
494: + (ncapstr * sizeof (enum r_dir_status)),
495: where, where_len);
496: else
497: dirp->where = NULL;
498:
499: dirp->next = GL(dl_all_dirs);
500: GL(dl_all_dirs) = dirp;
501:
502:
503: result[nelems++] = dirp;
504: }
505: }
506:
507:
508: result[nelems] = NULL;
509:
510: return result;
511: }
512:
513:
514: static bool
515: internal_function
516: decompose_rpath (struct r_search_path_struct *sps,
517: const char *rpath, struct link_map *l, const char *what)
518: {
519:
520: const char *where = l->l_name;
521: char *copy;
522: char *cp;
523: struct r_search_path_elem **result;
524: size_t nelems;
525:
526: const char *errstring = NULL;
527:
528:
529:
530: if (__builtin_expect (GLRO(dl_inhibit_rpath) != NULL, 0)
531: && !INTUSE(__libc_enable_secure))
532: {
533: const char *inhp = GLRO(dl_inhibit_rpath);
534:
535: do
536: {
537: const char *wp = where;
538:
539: while (*inhp == *wp && *wp != '\0')
540: {
541: ++inhp;
542: ++wp;
543: }
544:
545: if (*wp == '\0' && (*inhp == '\0' || *inhp == ':'))
546: {
547:
548:
549: sps->dirs = (void *) -1;
550: return false;
551: }
552:
553: while (*inhp != '\0')
554: if (*inhp++ == ':')
555: break;
556: }
557: while (*inhp != '\0');
558: }
559:
560:
561:
562: copy = expand_dynamic_string_token (l, rpath);
563: if (copy == NULL)
564: {
565: errstring = N_("cannot create RUNPATH/RPATH copy");
566: goto signal_error;
567: }
568:
569:
570: nelems = 0;
571: for (cp = copy; *cp != '\0'; ++cp)
572: if (*cp == ':')
573: ++nelems;
574:
575:
576:
577: result = (struct r_search_path_elem **) malloc ((nelems + 1 + 1)
578: * sizeof (*result));
579: if (result == NULL)
580: {
581: free (