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
175181private:
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 " );
0 commit comments