Skip to content

Commit a3cfcf1

Browse files
committed
Add support for static runtimes
1 parent 75bb5cd commit a3cfcf1

File tree

3 files changed

+29
-21
lines changed

3 files changed

+29
-21
lines changed

src/binfmt-bypass/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,14 @@ target_link_libraries(${bypass_lib} PUBLIC dl)
120120
# we need to include the preload lib headers (see below) from the binary dir
121121
target_include_directories(${bypass_lib} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
122122
target_compile_options(${bypass_lib}
123-
PRIVATE -DPRELOAD_LIB_PATH="${CMAKE_INSTALL_PREFIX}/${_private_libdir}/$<TARGET_FILE_NAME:${preload_lib}>"
123+
PRIVATE -DPRELOAD_LIB_NAME="$<TARGET_FILE_NAME:${preload_lib}>"
124124
PUBLIC -D_GNU_SOURCE
125125
# obviously needs to be private, otherwise the value leaks into users of this lib
126126
PRIVATE -DCOMPONENT_NAME="lib"
127127
)
128128
if(build_32bit_preload_library)
129129
target_compile_options(${bypass_lib}
130-
PRIVATE -DPRELOAD_LIB_PATH_32BIT="${CMAKE_INSTALL_PREFIX}/${_private_libdir}/$<TARGET_FILE_NAME:${preload_lib_32bit}>"
130+
PRIVATE -DPRELOAD_LIB_NAME_32BIT="$<TARGET_FILE_NAME:${preload_lib_32bit}>"
131131
)
132132
target_sources(${bypass_lib} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/${preload_lib_32bit}.h)
133133
endif()

src/binfmt-bypass/lib.cpp

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
#include <memory>
1010
#include <stdexcept>
1111
#include <cassert>
12+
#include <filesystem>
1213

1314
// own headers
1415
#include "elf.h"
1516
#include "logging.h"
1617
#include "lib.h"
1718
#include "binfmt-bypass-preload.h"
1819

19-
#ifdef PRELOAD_LIB_PATH_32BIT
20+
#ifdef PRELOAD_LIB_NAME_32BIT
2021
#include "binfmt-bypass-preload_32bit.h"
2122
#endif
2223

@@ -122,23 +123,28 @@ int create_shm_fd_with_patched_runtime(const char* const appimage_filename, cons
122123

123124
#endif
124125

125-
std::string find_preload_library(bool is_32bit) {
126+
std::filesystem::path find_preload_library(bool is_32bit) {
127+
// packaging is now done using ld-p-native_packages which does not make guarantees about the install path
128+
// therefore, we need to look up the path of the preload library in relation to the current binary's path
126129
// since we use the F (fix binary) binfmt mode nowadays to enable the use of the interpreter in different cgroups,
127-
// namespaces or changeroots, we can no longer rely on the path to the interpreter to find the preload libs
128-
// also, we compile in the absolute path to AppImageLauncher anyway
129-
// therefore, we can just compile in the paths to the libs as well
130-
// since we also compile in the contents of the preload libraries, this is merely just an optimization so we do not
131-
// have to write and maintain the library files in the majority of all cases (that is, using AppImages regularly
132-
// on some desktop or generally a host system)
133-
// our workflow is: check whether the (right) preload lib exists on the system, otherwise return an empty string
134-
// the creation of a library file needs to be handled by the caller then
135-
#ifdef PRELOAD_LIB_PATH_32BIT
130+
// namespaces or changeroots, we may not find the library there, but we'll at least try
131+
132+
// we expect the library to be placed next to this binary
133+
const auto own_binary_path = std::filesystem::read_symlink("/proc/self/exe");
134+
log_error("proc self exe %s\n", own_binary_path.string().c_str());
135+
const auto dir_path = own_binary_path.parent_path();
136+
137+
std::filesystem::path rv = dir_path;
138+
139+
#ifdef PRELOAD_LIB_NAME_32BIT
136140
if (is_32bit) {
137-
return PRELOAD_LIB_PATH_32BIT;
141+
rv /= PRELOAD_LIB_NAME_32BIT;
142+
return rv;
138143
}
139144
#endif
140145

141-
return PRELOAD_LIB_PATH;
146+
rv /= PRELOAD_LIB_NAME;
147+
return rv;
142148
}
143149

144150
/**
@@ -174,7 +180,7 @@ class TemporaryPreloadLibFile {
174180

175181
private:
176182
int _fd;
177-
std::string _path;
183+
std::filesystem::path _path;
178184
};
179185

180186
// need to keep track of the subprocess pid in a global variable, as signal handlers in C(++) are simple interrupt
@@ -231,15 +237,15 @@ int bypassBinfmtAndRunAppImage(const std::string& appimage_path, const std::vect
231237
new_argv.push_back(nullptr);
232238

233239
// preload our library
234-
std::string preload_lib_path = find_preload_library(is_32bit_elf(appimage_path));
240+
auto preload_lib_path = find_preload_library(is_32bit_elf(appimage_path));
235241

236242
// may or may not be used, but must survive until this application terminates
237243
std::unique_ptr<TemporaryPreloadLibFile> temporaryPreloadLibFile;
238244

239-
if (access(preload_lib_path.c_str(), F_OK) != 0) {
245+
if (!std::filesystem::exists(preload_lib_path)) {
240246
log_warning("could not find preload library path, creating new temporary file for it\n");
241247

242-
#ifdef PRELOAD_LIB_PATH_32BIT
248+
#ifdef PRELOAD_LIB_NAME_32BIT
243249
if (is_32bit_elf(appimage_path)) {
244250
temporaryPreloadLibFile = std::make_unique<TemporaryPreloadLibFile>(
245251
libbinfmt_bypass_preload_32bit_so,
@@ -260,14 +266,16 @@ int bypassBinfmtAndRunAppImage(const std::string& appimage_path, const std::vect
260266
preload_lib_path = temporaryPreloadLibFile->path();
261267
}
262268

263-
log_debug("library to preload: %s\n", preload_lib_path.c_str());
269+
log_debug("library to preload: %s\n", preload_lib_path.string().c_str());
264270

265271
setenv("LD_PRELOAD", preload_lib_path.c_str(), true);
266272

267273
// calculate absolute path to AppImage, for use in the preloaded lib
268274
char* abs_appimage_path = realpath(appimage_path.c_str(), nullptr);
269275
log_debug("absolute AppImage path: %s\n", abs_appimage_path);
276+
// TARGET_APPIMAGE is further needed for static runtimes which do not make any use of LD_PRELOAD
270277
setenv("REDIRECT_APPIMAGE", abs_appimage_path, true);
278+
setenv("TARGET_APPIMAGE", abs_appimage_path, true);
271279

272280
// launch memfd directly, no path needed
273281
log_debug("fexecve(...)\n");

src/binfmt-bypass/preload.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ void __init() {
6161
char* __abs_appimage_path() {
6262
__init();
6363

64-
static const char env_var_name[] = "REDIRECT_APPIMAGE";
64+
static const char env_var_name[] = "TARGET_APPIMAGE";
6565

6666
char* appimage_var = getenv(env_var_name);
6767

0 commit comments

Comments
 (0)