]>
Commit | Line | Data |
---|---|---|
1718c60c | 1 | /* Operating system specific code for generic dynamic loader functions. Linux. |
05f399e6 | 2 | Copyright (C) 2000-2002,2004-2009,2011 Free Software Foundation, Inc. |
32b4fe6a UD |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
32b4fe6a UD |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
32b4fe6a | 14 | |
41bdb6e2 AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
32b4fe6a | 19 | |
6ddd37a4 | 20 | #include <kernel-features.h> |
1718c60c | 21 | #include <dl-sysdep.h> |
15a856b1 | 22 | #include <endian.h> |
39546e34 | 23 | #include <fcntl.h> |
35f1e827 | 24 | #include <stdint.h> |
05f399e6 | 25 | #include <not-cancel.h> |
b4246fd6 UD |
26 | |
27 | #ifndef MIN | |
28 | # define MIN(a,b) (((a)<(b))?(a):(b)) | |
29 | #endif | |
32b4fe6a UD |
30 | |
31 | #ifdef SHARED | |
32 | /* This is the function used in the dynamic linker to print the fatal error | |
33 | message. */ | |
6cc8844f | 34 | static void |
32b4fe6a UD |
35 | __attribute__ ((__noreturn__)) |
36 | dl_fatal (const char *str) | |
37 | { | |
35fc382a | 38 | _dl_dprintf (2, str); |
32b4fe6a UD |
39 | _exit (1); |
40 | } | |
41 | #endif | |
42 | ||
1718c60c | 43 | #define DL_SYSDEP_OSCHECK(FATAL) \ |
32b4fe6a | 44 | do { \ |
1718c60c RM |
45 | /* Test whether the kernel is new enough. This test is only performed \ |
46 | if the library is not compiled to run on all kernels. */ \ | |
a334319f | 47 | \ |
1718c60c RM |
48 | int version = _dl_discover_osversion (); \ |
49 | if (__builtin_expect (version >= 0, 1)) \ | |
50 | { \ | |
609b254a UD |
51 | if (__builtin_expect (GLRO(dl_osversion) == 0, 1) \ |
52 | || GLRO(dl_osversion) > version) \ | |
53 | GLRO(dl_osversion) = version; \ | |
32b4fe6a UD |
54 | \ |
55 | /* Now we can test with the required version. */ \ | |
1718c60c | 56 | if (__LINUX_KERNEL_VERSION > 0 && version < __LINUX_KERNEL_VERSION) \ |
32b4fe6a UD |
57 | /* Not sufficent. */ \ |
58 | FATAL ("FATAL: kernel too old\n"); \ | |
59 | } \ | |
1718c60c RM |
60 | else if (__LINUX_KERNEL_VERSION > 0) \ |
61 | FATAL ("FATAL: cannot determine kernel version\n"); \ | |
32b4fe6a | 62 | } while (0) |
35f1e827 UD |
63 | |
64 | static inline uintptr_t __attribute__ ((always_inline)) | |
965cb60a | 65 | _dl_setup_stack_chk_guard (void *dl_random) |
35f1e827 | 66 | { |
15a856b1 UD |
67 | union |
68 | { | |
69 | uintptr_t num; | |
70 | unsigned char bytes[sizeof (uintptr_t)]; | |
71 | } ret; | |
72 | ||
965cb60a UD |
73 | #ifndef __ASSUME_AT_RANDOM |
74 | if (__builtin_expect (dl_random == NULL, 0)) | |
35f1e827 | 75 | { |
15a856b1 UD |
76 | const size_t filllen = sizeof (ret.bytes) - 1; |
77 | ret.num = 0; | |
965cb60a | 78 | # ifdef ENABLE_STACKGUARD_RANDOMIZE |
05f399e6 | 79 | int fd = open_not_cancel_2 ("/dev/urandom", O_RDONLY); |
965cb60a UD |
80 | if (fd >= 0) |
81 | { | |
15a856b1 | 82 | ssize_t reslen = read_not_cancel (fd, ret.bytes + 1, filllen); |
05f399e6 | 83 | close_not_cancel_no_status (fd); |
15a856b1 UD |
84 | if (reslen == (ssize_) filllen) |
85 | return ret.num; | |
965cb60a UD |
86 | } |
87 | # endif | |
15a856b1 UD |
88 | ret.bytes[filllen - 2] = 255; |
89 | ret.bytes[filllen - 3] = '\n'; | |
35f1e827 | 90 | } |
965cb60a | 91 | else |
35f1e827 | 92 | #endif |
15a856b1 UD |
93 | { |
94 | /* We need in the moment only 8 bytes on 32-bit platforms and 16 | |
95 | bytes on 64-bit platforms. Therefore we can use the data | |
96 | directly and not use the kernel-provided data to seed a PRNG. */ | |
97 | memcpy (ret.bytes, dl_random, sizeof (ret)); | |
98 | #if BYTE_ORDER == LITTLE_ENDIAN | |
99 | ret.num &= ~0xff; | |
100 | #elif BYTE_ORDER == BIG_ENDIAN | |
101 | ret.num &= ~(0xff << (8 * (sizeof (ret) - 1))); | |
102 | #else | |
103 | # error "BYTE_ORDER unknown" | |
104 | #endif | |
105 | } | |
106 | return ret.num; | |
965cb60a UD |
107 | } |
108 | ||
109 | static inline uintptr_t __attribute__ ((always_inline)) | |
110 | _dl_setup_pointer_guard (void *dl_random, uintptr_t stack_chk_guard) | |
111 | { | |
112 | uintptr_t ret; | |
113 | #ifndef __ASSUME_AT_RANDOM | |
114 | if (dl_random == NULL) | |
115 | { | |
116 | ret = stack_chk_guard; | |
117 | # ifndef HP_TIMING_NONAVAIL | |
118 | hp_timing_t now; | |
119 | HP_TIMING_NOW (now); | |
120 | ret ^= now; | |
121 | # endif | |
122 | } | |
123 | else | |
124 | #endif | |
125 | memcpy (&ret, (char *) dl_random + sizeof (ret), sizeof (ret)); | |
35f1e827 UD |
126 | return ret; |
127 | } |