Skip to content

Commit 4c8c162

Browse files
committed
initrd-put: Fix hang if soname is not found
The dlopen special helper must send the size so that the parent process does not have to wait for other data. Signed-off-by: Alexey Gladkov <[email protected]>
1 parent c217a58 commit 4c8c162

File tree

2 files changed

+22
-11
lines changed

2 files changed

+22
-11
lines changed

aclocal.m4

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
1+
# generated automatically by aclocal 1.17 -*- Autoconf -*-
22

3-
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
3+
# Copyright (C) 1996-2024 Free Software Foundation, Inc.
44

55
# This file is free software; the Free Software Foundation
66
# gives unlimited permission to copy and/or distribute it,

utils/initrd-put/elf_dlopen.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: GPL-3.0-only
22
#define _GNU_SOURCE
33

4+
#include <sys/wait.h>
45
#include <unistd.h>
56
#include <stdio.h>
67
#include <stdint.h>
@@ -59,6 +60,11 @@ static int in_envvar(const char *envname, const char *value)
5960
return in_list(getenv(envname), ',', value);
6061
}
6162

63+
static pid_t waitpid_retry(pid_t pid, int *wstatus, int options)
64+
{
65+
return (pid_t) TEMP_FAILURE_RETRY(waitpid(pid, wstatus, options));
66+
}
67+
6268
static int resolve_soname(const char **soname, size_t len, char *outbuf)
6369
{
6470
int pipefd[2];
@@ -108,6 +114,10 @@ static int resolve_soname(const char **soname, size_t len, char *outbuf)
108114
}
109115
ret = 0;
110116
out_parent:
117+
int status;
118+
if (waitpid_retry(pid, &status, 0) < 0)
119+
warn("waitpid");
120+
111121
close(pipefd[0]); // read
112122
close(pipefd[1]); // write
113123

@@ -123,17 +133,17 @@ static int resolve_soname(const char **soname, size_t len, char *outbuf)
123133
if (handle)
124134
dlclose(handle);
125135

126-
if (!(handle = dlopen(soname[i], RTLD_LAZY)))
127-
continue;
136+
offset = 0;
137+
siz = 0;
128138

129-
if (dlinfo(handle, RTLD_DI_LINKMAP, &map) < 0) {
130-
warnx("dladdr(%s) failed: %s", soname[i], dlerror());
131-
continue;
139+
if ((handle = dlopen(soname[i], RTLD_LAZY)) != NULL) {
140+
if (dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0) {
141+
siz = strlen(map->l_name) + 1;
142+
} else {
143+
warnx("dladdr(%s) failed: %s", soname[i], dlerror());
144+
}
132145
}
133146

134-
offset = 0;
135-
siz = strlen(map->l_name) + 1;
136-
137147
errno = 0;
138148
n = TEMP_FAILURE_RETRY(write(pipefd[1], &siz, sizeof(siz)));
139149
if (n < 0) {
@@ -154,7 +164,8 @@ static int resolve_soname(const char **soname, size_t len, char *outbuf)
154164
offset += (size_t) n;
155165
}
156166

157-
break;
167+
if (map)
168+
break;
158169
}
159170
ret = EXIT_SUCCESS;
160171
out_child:

0 commit comments

Comments
 (0)