|
11 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12 | 12 | * GNU Lesser General Public License for more details.
|
13 | 13 | */
|
14 |
| -/* |
15 |
| - */ |
| 14 | + |
| 15 | +/* must be at the beginning, it affects defines in other headers that cannot be reenabled later */ |
| 16 | +#define _GNU_SOURCE |
16 | 17 |
|
17 | 18 | #include <unistd.h>
|
18 | 19 | #include <stdlib.h>
|
@@ -72,6 +73,30 @@ CAMLprim value stub_XA_mh_chpasswd(value username, value new_password){
|
72 | 73 | CAMLreturn(ret);
|
73 | 74 | }
|
74 | 75 |
|
| 76 | +#include <crypt.h> |
| 77 | +/* 'constructor' attribute will ensure this function gets call early during program startup. */ |
| 78 | +void __attribute__((constructor)) stub_XA_workaround(void) |
| 79 | +{ |
| 80 | + struct crypt_data data; |
| 81 | + memset(&data, 0, sizeof(data)); |
| 82 | + |
| 83 | + /* Initialize and load crypt library used for password hashing. |
| 84 | + This library is loaded and initialized at [pam_authenticate] time and not at [pam_start]. |
| 85 | + If it detects a race condition (multiple threads with their own PAM contexts trying to call 'crypt_r'), |
| 86 | + then it does [sleep 1] as can be seen in this call trace: |
| 87 | + [pam_authenticate -> crypt_r -> __sha512_crypt_r -> freebl_InitVector -> freebl_RunLoaderOnce -> sleep]. |
| 88 | +
|
| 89 | + As a workaround link with 'libcrypt' and call 'crypt_r' with a setting that will make it take tha sha512 route |
| 90 | + to ensure that the library gets initialized while we're still single-threaded and stays loaded and initialized. |
| 91 | +
|
| 92 | + '$6$' is the setting for sha512 according to crypt(5). |
| 93 | +
|
| 94 | + Upstream has switched to using libxcrypt instead which doesn't have these problems, when we switch then |
| 95 | + this workaround can be dropped. |
| 96 | + */ |
| 97 | + crypt_r("", "$6$", &data); |
| 98 | +} |
| 99 | + |
75 | 100 | /*
|
76 | 101 | * Local variables:
|
77 | 102 | * mode: C
|
|
0 commit comments