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

glibc: add NIX_LD_LIBRARY_PATH #31263

Closed
wants to merge 1 commit into from

Conversation

lukateras
Copy link
Member

@lukateras lukateras commented Nov 4, 2017

Motivation for this change

Will eventually lead to fix of #21109. Related: #31182 (comment).

To test this, replace glibc with path to glibc built with this patch and paste this into terminal (provided that you have nix-shell and patchelf on path):

glibc=/nix/store/...-glibc/
cd /tmp
curl -LO https://github.com/NixOS/nixpkgs/files/1443636/gtk3-progress-bar.tar.gz
tar zxf gtk3-progress-bar.tar.gz 
cd gtk3-progress-bar
nix-shell --run make
export NIX_LD_LIBRARY_PATH=$(patchelf --print-rpath gtk3-progress-bar)
patchelf --remove-rpath gtk3-progress-bar
patchelf --set-interpreter $glibc/lib/ld-linux-x86-64.so.2 gtk3-progress-bar
./gtk3-progress-bar

If you see a progress bar, then it works. It should also correctly handle case where some libraries are on LD_LIBRARY_PATH and others are on NIX_LD_LIBRARY_PATH, and case when LD_LIBRARY_PATH is empty but NIX_LD_LIBRARY_PATH is not.

/cc @abbradar

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option build-use-sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Fits CONTRIBUTING.md.

@7c6f434c
Copy link
Member

7c6f434c commented Nov 4, 2017

I think this should target the staging branch.

@lukateras
Copy link
Member Author

@7c6f434c Yeah, it will result in a total rebuild of everything. This PR should have no conflicts with staging branch, should I leave it as is or close this and open a new one?

@7c6f434c
Copy link
Member

7c6f434c commented Nov 4, 2017 via email

@lukateras lukateras changed the base branch from master to staging November 4, 2017 23:23
@lukateras
Copy link
Member Author

@ghost
Copy link

ghost commented Nov 5, 2017

@yegortimoshenko Perhaps #29064 can be dealt in similar way?

DL_SYSDEP_OSCHECK (_dl_fatal_printf);
#endif

+ char *nix_library_path = getenv ("NIX_LD_LIBRARY_PATH");
Copy link
Contributor

@dezgeg dezgeg Nov 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt that you can call getenv() here without causing a security vulnerability in setuid programs but rather secure_getenv or something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dezgeg Fixed, see unsecvars.h patch.

@lukateras
Copy link
Member Author

@gnidorah Yeah, we can definitely do the same thing with LD_PRELOAD_PATH and NIX_LD_PRELOAD_PATH. Just need to append NIX_LD_PRELOAD_PATH to preloadlist around line 1470 of elf/rtld.c.

Copy link
Member

@abbradar abbradar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, I thought of doing it in this way (concat strings) when I looked at this myself but decided that it would look too hacky. It seems not so when I look at it now ;)

+ strcpy (combined_library_path, library_path);
+
+ if (strlen (library_path) > 0)
+ strcat (combined_library_path, ":");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe better to just set a character here to avoid O(n)? Save strlen(library_path) and do combined_library_path[len] = ':'.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

combined_library_path should end with NUL.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course but you could do [len + 1] = '\0'. My point is that we want to avoid as much overhead as possible because this code executes with /any/ new process in the entire OS. However I'm not adamant on those -- if others think it's negligible let's merge, I see no other problems with that.

+ if (strlen (library_path) > 0)
+ strcat (combined_library_path, ":");
+
+ strcat (combined_library_path, nix_library_path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strcpy(combined_library_path + len + (conditional) 1, nix_library_path) would be more effective.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer this code to be as straightforward as possible :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

+ char *combined_library_path;
+
+ if (nix_library_path) {
+ combined_library_path = malloc (strlen (library_path) + strlen (nix_library_path) + 2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compute library_path length once.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely, good catch!

@globin
Copy link
Member

globin commented Nov 5, 2017

cc @edolstra @Ericson2314

@vcunat
Copy link
Member

vcunat commented Nov 5, 2017

I expect tomorrow I'll be combining staging with glibc updates (fixing vulnerabilities). We might catch those together, if this PR seems OK-ish by the time I do it.

@lukateras
Copy link
Member Author

lukateras commented Nov 5, 2017

@vcunat Thanks! I've just made and tested change proposed by @abbradar, now it doesn't compute strlen(library_path) twice and also handles separator better. This should be ready to merge.

Copy link
Member

@Ericson2314 Ericson2314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine to me. NIX_SSL_CERT_FILE is the precedent of course. I wish we could have the proper return status, but I'll take your word that it would take a big ugly patch to do so.

@vcunat vcunat self-assigned this Nov 6, 2017
@vcunat
Copy link
Member

vcunat commented Nov 6, 2017

If I understand glibc and the patch correctly, this applies for shared glibc but not for static one (_dl_non_dynamic_init also calling _dl_init_paths). To include that case, the new code could be moved to _dl_init_paths directly, but I can't see any use case for such a combination, so I'm inclined to keep the current approach.

@edolstra
Copy link
Member

edolstra commented Nov 6, 2017

I don't really understand the motivation for this. If the problem is to allow some proprietary games to find libGL, then can't you do that by mounting /usr/lib/libGL.so in the mount namespace?

Adding a lot of ad hoc NIX_* environment variables seems ugly to me (and I regret adding NIX_SSL_CERT_FILE for creating a precedent).

@vcunat
Copy link
Member

vcunat commented Nov 6, 2017

Such additions are a bit risky. I personally currently can't see a better way around the use cases when you have a mix of binaries from nix and others (e.g. running on a non-nixos host). There it's common to have interferences due to one of those two groups wanting to override libs (like nixpkgs for opengl) and negatively affecting the others.

Another thing is, that on 2.26 #28622 this gets us:

/build/glibc-2.26/stdlib/getenv.c:84: undefined reference to `strncmp'

(not counting a trivial merge conflict in sysdeps/generic/unsecvars.h)

I also tried to address some other nitpicks in https://github.com/vcunat/nixpkgs/commits/p/glibc-NIX_LD but not this linking error.

Well, let me leave this open for now.

@vcunat vcunat removed their assignment Nov 6, 2017
@lukateras
Copy link
Member Author

lukateras commented Nov 6, 2017

@vcunat Do you plan to apply this patch to glibc 2.26? If so, I can rebase it on glibc 2.26 and resolve this.

I also had patched _dl_non_dynamic_init but dropped because I didn't see it as necessary. However, come to think of it, if we are to switch to NIX_LD_LIBRARY_PATH for OpenGL system-wide, this indeed should be moved to _dl_init_paths so that we support statically linked OpenGL applications.

@edolstra This is not only for games, or proprietary software; see #31136 (comment): avrdude is GPL'd. Quite a few games on Steam are open-source, too. This is essentially to make Nix composable with other package managers (PlatformIO, Steam): some of the software they distribute presumes that LD_LIBRARY_PATH is empty (or at least non-essential) and rewrites it.

What is really ugly here is mutability of environment variables. If LD_LIBRARY_PATH was to be append-only, this would not be an issue. Perhaps we should patch setenv instead? (not joking)

@vcunat
Copy link
Member

vcunat commented Nov 6, 2017

@yegortimoshenko: glibc-2.26 is in staging now. There are some security fixes in there, so I don't want to delay it. You can utilize my branch (it used merge instead of rebase).

@lukateras
Copy link
Member Author

@vcunat By the way, can this resolve #9415?

@vcunat
Copy link
Member

vcunat commented Nov 6, 2017

@yegortimoshenko: no, there's a much more complex situation. Maybe the libcapsule approach at the end, if combined with libglvnd and maybe some extra hacks.

@abbradar
Copy link
Member

abbradar commented Mar 14, 2018

You can patch libglvnd to look into /run/opengl-driver first, but that wouldn't be that different from just setting LD_LIBRARY_PATH, really. Just a bit cleaner.

Yeah, we already do just that -- override libglvnd (and other similar libraries like vulkan-loader) to look there. I agree that's similar but avoids problems with LD_LIBRARY_PATH and friends.

  • non-Nix binaries loaded with their ld-linux on NixOS

Yeah, that's definitely a case which we don't want to support.

  • non-Nix binaries loaded with our ld-linux on NixOS: NIX_LD_LATE_RUNPATH and/or ld.so.cache provide paths to the common libs your app doesn't explicitly override,

Note: this is a non-existent case outside of FHS environments, otherwise agreed.

  • Nix binaries on non-NixOS: LD_LIBRARY_PATH-wrapper like nixGL and/or libglvnd for libGL emulate NixOS environment, nix binaries work as if they are run under NixOS completely ignoring the host environment (unless you override it explicitly yourself),

If by "environment" you mean installed stuff in /usr (sans explicit overrides) then yeah.

Overall that's pretty much what I believed we are going to do. I have half-finished branch moving us to libglvnd which I abandoned at that time because Mesa was still believed to be unstable with it.

@guibou
Copy link
Contributor

guibou commented Mar 14, 2018

@oxij Please steal everything you want from nixGL (most of its current state is anyway stolen from @deepfire's nix-install-vendor-gl. But please add me to the future discussions / pull requests ;)

@oxij
Copy link
Member

oxij commented Mar 15, 2018 via email

@abbradar
Copy link
Member

@oxij Cool! ldd should show them -- it's not supposed to have different behavior from actual ld.so search codepaths. Overall this may even be upstreamable -- before just adding it to NixOS it would be a good idea to post it to glibc's mailing list and see what they have to say.

@mmahut
Copy link
Member

mmahut commented Aug 19, 2019

Are there any updates on this pull request, please?

@drewboardman
Copy link

Is this still in progress? I'm seeing this error:

"can't load .so/.DLL for: /nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/libpthread.so (/nix/store/681354n3k44r8z90m35hm8945vsp95h1-glibc-2.27/lib/libpthread.so.0: undefined symbol: __libc_vfork, version GLIBC_PRIVATE)"

It's the same error mentioned here

#31846

and here

#29064

@lukateras
Copy link
Member Author

I'm going to take a stab at rebasing this patch against the latest glibc.

@oxij
Copy link
Member

oxij commented Feb 29, 2020 via email

@domenkozar
Copy link
Member

@oxij can you create a PR?

@danielfullmer
Copy link
Contributor

Just adding a note here that I'm fairly certain this would solve issues we're having with SteamVR+Proton: #71554

@DavHau
Copy link
Member

DavHau commented Jun 8, 2020

Why create an entirely new fallback mechanism if we can just use the one which is already built into ld-linux? I think this is what #59595 tries to do.

@7c6f434c
Copy link
Member

@DavHau I guess for every upstream mechanism there is some package making assumptions about it in a way that is inconvenient for Nixpkgs…

@stale
Copy link

stale bot commented Dec 9, 2020

I marked this as stale due to inactivity. → More info

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Dec 9, 2020
@Mic92
Copy link
Member

Mic92 commented Jan 7, 2021

Fun fact in https://github.com/Mic92/nix-ld I also introduced NIX_LD_LIBRARY_PATH.

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Jan 7, 2021
@stale
Copy link

stale bot commented Jul 8, 2021

I marked this as stale due to inactivity. → More info

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Jul 8, 2021
@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label May 4, 2022
@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Nov 2, 2022
@Artturin Artturin marked this pull request as draft February 2, 2023 18:49
@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Feb 2, 2023
@oxij
Copy link
Member

oxij commented Aug 11, 2023

I PRed my glibc patch at #248547.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet