Git Product home page Git Product logo

nix-ld-rs's Introduction

nix-ld-rs

Run unpatched dynamic binaries on NixOS. This is a rewrite of nix-ld in Rust, with extra functionalities. It's intended to be upstreamed at some point.

Usage

nix-ld-rs is a drop-in replacement for nix-ld.

It honors the following environment variables:

  • NIX_LD
  • NIX_LD_{system}
  • NIX_LD_LIBRARY_PATH
  • NIX_LD_LIBRARY_PATH_{system}
  • NIX_LD_LOG (error, warn, info, debug, trace)

Here {system} is the value of the Nix system with dashes replaced with underscores, like x86_64_linux. You can also run nix-ld-rs directly for a list.

Use in NixOS

{ pkgs, ... }: {
  programs.nix-ld.enable = true;
  programs.nix-ld.package = pkgs.nix-ld-rs;
}

Extra functionalities

  • NIX_LD_LIBRARY_PATH doesn't affect child processes (on x86_64-linux and aarch64-linux)
    • For example, shell environments spawned by the binary VSCode Server no longer get polluted

Development

The included devShell provides all dependencies required to build the project. It's recommended to set up transparent emulation using binfmt-misc so you can run tests on all supported platforms:

{
  # x86_64-linux, i686-linux, aarch64-linux
  boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
}

Run cargo test or cargo nextest run to run the integration tests, and just test to run them on all supported platforms (binfmt required).

Current behavior

Launch Seen by ld.so Seen by getenv() and children (a)
NIX_LD_LIBRARY_PATH LD_LIBRARY_PATH NIX_LD_LIBRARY_PATH LD_LIBRARY_PATH NIX_LD_LIBRARY_PATH LD_LIBRARY_PATH
1 (unset) (unset) (unset) "/run/current-system/sw/share/nix-ld/lib" (unset) "" (b)
2 (unset) "/some/lib" (unset) "/some/lib:/run/current-system/sw/share/nix-ld/lib" (unset) "/some/lib"
3 "/some/nix/ld/lib" (unset) (unset) "/some/nix/ld/lib" "/some/nix/ld/lib" (unset)
4 "/some/nix/ld/lib" "/some/lib" "/some/nix/ld/lib" "/some/lib:/some/nix/ld/lib" "/some/nix/ld/lib" "/some/lib"

(a) On X86-64 and AArch64 only (see src/arch.rs). On other platforms, the "Seen by ld.so" state will persist.
(b) The variable will be present but set to an empty string.

nix-ld-rs's People

Contributors

mergify[bot] avatar mic92 avatar renovate[bot] avatar zhaofengli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

nix-ld-rs's Issues

32-bit nix ld

Hi,

I think nix-ld is very useful, and wanted to run some 32-bit programs recently. What I have done is patch nix-ld-rs (and probably nix-ld but I haven't tried that) to rename NIX_LD* to NIX_LD32* which has changed from /run/current-system/sw/share/nix-ld to /run/current-system/sw/share/nix-ld32 and contains the pkgsi686Linux versions of the packages. Then made a NixOS module to use this, copied from the original one with relevant bits made 32-bit.

KoviRobi/nixos-config@4c0826f

It works for me, I suppose I'm asking/proposing it might be worth making this less of a hack? Perhaps add a feature flag for 32-bit (and I imagine to the C++ nix-ld), then update the package in NixOS and modify the module to support both?

Any suggestions are appreciated, if it looks fine then I'll try to get around to implementing it (though these days I am terrible with finishing things, sorry)

Support for `/lib/ld-musl-x86_64.so.1`

I'm using nix-ld-rs for VSCode Server and it seems to be working fine, except that the current version of the ms-dotnettools.vscode-dotnet-runtime extension is using a dotnet binary that uses /lib/ld-musl-x86_64.so.1 and I can't make it work. I assume that I could use nix-ld-rs to run it if I set NIX_LD to musl's interpreter and set NIX_LD_LIBRARY_PATH to a folder of libraries built using musl, but I don't have any way to set the environment just for invoking this binary and I need the defaults for VSCode Server itself.

What I'd really like is some solution that allows me to symlink /lib/ld-musl-x86_64.so.1 and have everything work. Something like providing vars NIX_LD_musl/NIX_LD_x86_64_linux_musl and NIX_LD_LIBRARY_PATH_musl/NIX_LD_LIBRARY_PATH_x86_64_linux_musl and then either having nix-ld-rs look at what interpreter the binary wanted to determine musl support, or possibly just having a separate libexec/nix-ld-musl binary that does it.

Configuration fragment for using?

nix-ld-rs looks interesting! Glad to see it in nix-community. Is it ready for use or at least experimentation?

I'm sure it's obvious in hindsight, but is there a configuration fragment I can paste into my configuration.nix to make use of nix-ld-rs? This is something I can likely solve myself but I'm interested in seeing it documented at the top of the readme for other people as well.

Right now I imagine I might need to import nix-ld-rs as a flake, but is there also a plan to get this integrated into nixpkgs and nixos?

Solves bazel issues on NixOS

I just started testing this but it so far resolves issues using deterministic Python/Go toolchains that nix-ld would break on.

Thanks for the effort and keep it up! This has solved loads of problems for me.

RUNPATH is ignored when nix-ld-rs is enabled

Hi! It seems like nix-ld-rs is ignoring RPATH and binaries are linked to whatever libraries nix-ld exposes instead.

❯ /nix/store/q8qq40xg2grfh9ry1d9x4g7lq4ra7n81-bash-5.2-p21/bin/bash
/nix/store/q8qq40xg2grfh9ry1d9x4g7lq4ra7n81-bash-5.2-p21/bin/bash: symbol lookup error: /run/current-system/sw/share/nix-ld/lib/libc.so.6: undefined symbol: __tunable_is_initialized, version GLIBC_PRIVATE
❯ patchelf --print-rpath /nix/store/q8qq40xg2grfh9ry1d9x4g7lq4ra7n81-bash-5.2-p21/bin/bash
/nix/store/9y8pmvk8gdwwznmkzxa6pwyah52xy3nk-glibc-2.38-27/lib
❯ strace -e openat /nix/store/q8qq40xg2grfh9ry1d9x4g7lq4ra7n81-bash-5.2-p21/bin/bash
openat(AT_FDCWD, "/run/current-system/sw/share/nix-ld/lib/glibc-hwcaps/x86-64-v3/libdl.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/current-system/sw/share/nix-ld/lib/glibc-hwcaps/x86-64-v2/libdl.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/run/current-system/sw/share/nix-ld/lib/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/run/current-system/sw/share/nix-ld/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
/nix/store/q8qq40xg2grfh9ry1d9x4g7lq4ra7n81-bash-5.2-p21/bin/bash: symbol lookup error: /run/current-system/sw/share/nix-ld/lib/libc.so.6: undefined symbol: __tunable_is_initialized, version GLIBC_PRIVATE
+++ exited with 127 +++

using `nix-ld-rs` to load openssl makes ping response time from LAN address spiky

I have had this weird issue that if I add pkgs.openssl (or pkgs.openssl_3_3) to the enabled libraries for nix-ld module, and after a reboot, response time from pinging my LAN router becomes spiky, ranging from the normal sub 1ms to sometimes 10+ ms even hundreds of ms. This issue affects other IP protocol communication, e.g. browsing the web become sluggish.

I tried straceing the ping command, and the only difference between the normal ping and a problematic ping is that the recvmsg syscall returns EAGAIN error, e.g.

sendto(3, "\10\0\2717\377\377\0\3\220\203zf\0\0\0\0l\10\t\0\0\0\0\0\20\21\22\23\24\25\26\27"..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.199.1")}, 16) = 64
recvmsg(3, {msg_namelen=128}, 0)        = -1 EAGAIN (Resource temporarily unavailable)

whereas a ping with normal response looks like:

sendto(3, "\10\0q\201\377\377\0\4\221\203zf\0\0\0\0\262\275\t\0\0\0\0\0\20\21\22\23\24\25\26\27"..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.199.1")}, 16) = 64
recvmsg(3, {msg_name={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.199.1")}, msg_namelen=128 => 16, msg_iov=[{iov_base="\0\0\3012\0\5\0\3\220\203zf\0\0\0\0l\10\t\0\0\0\0\0\20\21\22\23\24\25\26\27"..., iov_len=192}], msg_iovlen=1, msg_control=[{cmsg_len=32, cmsg_level=SOL_SOCKET, cmsg_type=SO_TIMESTAMP_OLD, cmsg_data={tv_sec=1719305105, tv_usec=638725}}, {cmsg_len=20, cmsg_level=SOL_IP, cmsg_type=IP_TTL, cmsg_data=[64]}], msg_controllen=56, msg_flags=0}, 0) = 64

While the error explains the slow response time, it didn't give hints to the root cause.

Any help/guidance on debugging this issue is appreciated!

Some context:

  • OS: NixOS 24.05
  • tried both nix-ld and nix-ld-rs, but no difference

X11 lib not found

Hello,

I'm trying to run a program that uses x11-dl to interact with X11 but it cannot find it.

I have enabled nix-ld with the appropriate libs:

programs.nix-ld.enable = true;                                                                                                                                                                                                      
programs.nix-ld.libraries = with pkgs; [                                                                                                                                                                                            
    openssl                                                                                                                                                                                                                           
    xorg.libX11                                                                                                                                                                                                                       
    xorg.libXcursor                                                                                                                                                                                                                   
    xorg.libxcb                                                                                                                                                                                                                       
    xorg.libXi                                                                                                                                                                                                                        
    libxkbcommon                                                                                                                                                                                                                      
    libz                                                                                                                                                                                                                              
];

I also managed to isolate the problem using a dummy program written in Rust:

use x11_dl::xlib;

fn main() {
    let _xlib = xlib::Xlib::open().unwrap();
}

And I get the output:

[kamereon@nixos:~/test_xlib]$ cargo run
   Compiling test_xlib v0.1.0 (/home/kamereon/test_xlib)
    Finished dev [unoptimized + debuginfo] target(s) in 0.19s
     Running `target/debug/test_xlib`
thread 'main' panicked at src/main.rs:4:36:
called `Result::unwrap()` on an `Err` value: OpenError { kind: Library, detail: "opening library failed (libX11.so.6: cannot open shared object file: No such file or directory); opening library failed (libX11.so: cannot open shared object file: No such file or directory)" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I have read documentation about dlopen and I believe it should act the same way as having an ELF linked binary but I may be mistaken that's why I open this ticket.

I this behaviour expected ? If yes could you tell me how to run a binary with dynamically loaded libraries on Nixos ?

The only way I got it to work but it's quite dirty is by setting the LD_LIBRARY_PATH to the content of NIX_LD_LIBRARY_PATH manually before running cargo run.

Python `find_library`

I have been testing out nix-ld-rs with the pixi package manager, which is similar to conda. I've been having success so far by just adding the libraries as needed on the spot as I find them, but what I've come across now is a package that uses find_library() from the builtin ctypes.util Python module. This method tries a few options starting by using a hardcoded /sbin/ldconfig, then trying to use gcc -t, and finally by using LD_LIBRARY_PATH. LD_LIBRARY_PATH would in theory be compatiple with nix-ld-rs but it finds the library by spawning a new shell process that uses ld to try to find the library. Because a standard nix install does not contain ld, though, this fails. If I make ld available via nix, then it warns about not being able to find ld-linux-x86-64.so.2 which to my understanding is because nix-ld-rs doesn't "activate" for nix programs.

What's the best way to get this function working in a nix-ld setup? Is there a proper ld that is "included" with nix-ld?

Config File Support

I'm trying to see if I can get bazelisk working in a Nix (container) environment for bazelbuild/continuous-integration#1799 and I'm running into an issue where Bazel (and many executables it launches) run fine with nix-ld-rs (it gets past the child process issue that nix-ld has) but in some cases Bazel insists on running a child process with a clean environment and hard-coded PATH.

I think the nixpkgs version of Bazel patches out this behavior, if I'm interpreting this correctly (https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/tools/build-managers/bazel/nix-hacks.patch). If nix-ld-rs could fall back to reading /etc/nix-ld.conf (for example) to get the values for NIX_LD and NIX_LD_LIBRARY_PATH, that would work around this particular case.

I'm assuming not having config file support is a pretty deliberate choice for a reason I'm not considering. If not and this functionality would be a good addition, I'd be happy to take a stab at a PR.

newb question

Hello,

Sorry, I am relatively new to Nix & NixOS, and would like to install this package, but don't know how. Is it possible to provide some information? My configuration is currently flake-based.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Awaiting Schedule

These updates are awaiting their schedule. Click on a checkbox to get an update now.

  • chore(deps): lock file maintenance

Detected dependencies

cargo
Cargo.toml
  • cfg-match 0.2.1
  • constcat 0.5.0
  • default-env 0.1.1
  • embedded-io 0.6.1
  • goblin 0.8.1
  • heapless 0.8.0
  • linux-raw-sys 0.6.4
  • log 0.4.21
  • cc 1.0.95
  • lazy_static 1.4.0
  • rstest 0.22.0
  • tempfile 3.10.1
  • cc 1.0.95

  • Check this box to trigger a request for Renovate to run again on this repository

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.