Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS does not pass DYLD_LIBRARY_PATH to subprocesses #7973

Closed
3 tasks done
JC3 opened this issue Oct 2, 2023 · 2 comments · Fixed by #7983
Closed
3 tasks done

macOS does not pass DYLD_LIBRARY_PATH to subprocesses #7973

JC3 opened this issue Oct 2, 2023 · 2 comments · Fixed by #7983
Labels
triage Please triage and relabel this issue

Comments

@JC3
Copy link

JC3 commented Oct 2, 2023

Description of the issue

macOS does not pass the DYLD_LIBRARY_PATH env var (or other dyld-related env vars) to subprocesses: https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/RuntimeProtections/RuntimeProtections.html#//apple_ref/doc/uid/TP40016462-CH3-SW1

Therefore, on systems with a DYLD_LIBRARY_PATH set, the Python scripts in the binaries generated by pyinstaller do not have access to it, and so pyinstaller can not be used if the target system is expected to have a meaningful DYLD_LIBRARY_PATH set.

It would be nice if pyinstaller found some way to explicitly pass these environment variables through.

Thought: Unfortunately, passing them through the env parameter to e.g. Popen doesn't work; the only way I've found to pass them through is to spawn subprocesses in shell mode and embed the env vars on the command line, which also requires sanitizing the env vars to prevent arbitrary command execution. I don't know if there's another way.

Context information (for bug reports)

  • Output of pyinstaller --version: 6.0.0

  • Version of Python: 3.9.6

  • Platform: macOS

  • How you installed Python: default macOS install

  • Did you also try this on another platform? Does it work there? Yes it works on Linux and Windows

  • try the latest development version, using the following command:

pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip

Make sure everything is packaged correctly

  • start with clean installation
  • use the latest development version
  • Run your frozen program from a command window (shell) — instead of double-clicking on it
  • N/A Package your program in --onedir mode
  • N/A Package without UPX, say: use the option --noupx or set upx=False in your .spec-file
  • N/A Repackage you application in verbose/debug mode. For this, pass the option --debug to pyi-makespec or pyinstaller or use EXE(..., debug=1, ...) in your .spec file.

A minimal example program which shows the error

import os

print(os.getenv("DYLD_LIBRARY_PATH"))

Stacktrace / full error message

N/A

Please also see https://github.com/pyinstaller/pyinstaller/wiki/How-to-Report-Bugs
for more about what would use to solve the issue.

@JC3 JC3 added the triage Please triage and relabel this issue label Oct 2, 2023
@rokm
Copy link
Member

rokm commented Oct 2, 2023

Hmm...

$ cat << EOF > program.py
> import os
> print(os.getenv("DYLD_LIBRARY_PATH"))
> EOF
$ pyinstaller --clean --noconfirm program.py --onedir --distpath dist-onedir
[...]
$ pyinstaller --clean --noconfirm program.py --onefile --distpath dist-onefile
[...]
$ export DYLD_LIBRARY_PATH=/some/invalid/path
$ ./dist-onedir/program/program 
/some/invalid/path
$ ./dist-onefile/program        
None

So I assume you are talking about onefile builds?

I suspect this block of code in the bootloader

#ifdef __APPLE__
/* On Mac OS X we do not use environment variables DYLD_LIBRARY_PATH
* or others to tell OS where to look for dynamic libraries.
* There were some issues with this approach. In some cases some
* system libraries were trying to load incompatible libraries from
* the dist directory. For instance this was experienced with macprots
* and PyQt applications.
*
* To tell the OS where to look for dynamic libraries we modify
* .so/.dylib files to use relative paths to other dependent
* libraries starting with @executable_path.
*
* For more information see:
* http://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac
* http://developer.apple.com/library/mac/#documentation/DeveloperTools/ \
* Conceptual/DynamicLibraries/100-Articles/DynamicLibraryUsageGuidelines.html
*/
/* For environment variable details see 'man dyld'. */
pyi_unsetenv("DYLD_FRAMEWORK_PATH");
pyi_unsetenv("DYLD_FALLBACK_FRAMEWORK_PATH");
pyi_unsetenv("DYLD_VERSIONED_FRAMEWORK_PATH");
pyi_unsetenv("DYLD_LIBRARY_PATH");
pyi_unsetenv("DYLD_FALLBACK_LIBRARY_PATH");
pyi_unsetenv("DYLD_VERSIONED_LIBRARY_PATH");
pyi_unsetenv("DYLD_ROOT_PATH");
#else

is to blame, rather than macOS.

I need to look a bit deeper, but my first impression is that we should get rid of those unsetenv's. As the comment above them states, we explicitly go to the trouble of rewriting library search paths on collected binaries to be independent of dyld environment variables, and by extension, we should be able to not care if they are set or not (i.e., should not touch them at all)...

@JC3
Copy link
Author

JC3 commented Oct 7, 2023

Awesome. I thought it was the macos security thing. This is great news thank you!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
triage Please triage and relabel this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants