NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
12.06k stars 1.47k forks source link

Crash with static nix if HOME is owned by a different user #10772

Open iwanb opened 3 months ago

iwanb commented 3 months ago

Describe the bug

Trying to run the static nix as root with HOME set to a folder owned by a different user results in a crash/segfault.

Stacktrace, on latest master.

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000000000086e4bb in nix::getHome[abi:cxx11]()::{lambda()#1}::operator()() const [clone .constprop.0] ()

EDIT: Leaving this wrong stacktrace, I made a mistake before and mixed up two versions of the binary:

(gdb) bt
#0  0x00000000007b9983 in toml::detail::repeat<toml::detail::either<toml::detail::either<toml::detail::character<(char)32>, toml::detail::character<(char)9> >, toml::detail::either<toml::detail::character<(char)10>, toml::detail::sequence<toml::detail::character<(char)13>, toml::detail::character<(char)10> > >, toml::detail::sequence<toml::detail::character<(char)35>, toml::detail::repeat<toml::detail::either<toml::detail::either<toml::detail::character<(char)9>, toml::detail::in_range<(char)32, (char)126> >, toml::detail::sequence<toml::detail::in_range<(char)-62, (char)-33>, toml::detail::in_range<(char)-128, (char)-65> >, toml::detail::sequence<toml::detail::either<toml::detail::sequence<toml::detail::character<(char)-32>, toml::detail::in_range<(char)-96, (char)-65> >, toml::detail::sequence<toml::detail::in_range<(char)-31, (char)-20>, toml::detail::in_range<(char)-128, (char)-65> >, toml::detail::sequence<toml::detail::character<(char)-19>, toml::detail::in_range<(char)-128, (char)-97> >, toml::detail::sequence<toml::detail::in_range<(char)-18, (char)-17>, toml::detail::in_range<(char)-128, (char)-65> > >, toml::detail::in_range<(char)-128, (char)-65> >, toml::detail::sequence<toml::detail::either<toml::detail::sequence<toml::detail::character<(char)-16>, toml::detail::in_range<(char)-112, (char)-65> >, toml::detail::sequence<toml::detail::in_range<(char)-15, (char)-13>, toml::detail::in_range<(char)-128, (char)-65> >, toml::detail::sequence<toml::detail::character<(char)-12>, toml::detail::in_range<(char)-128, (char)-113> > >, toml::detail::in_range<(char)-128, (char)-65>, toml::detail::in_range<(char)-128, (char)-65> > >, toml::detail::unlimited> > >, toml::detail::unlimited>::invoke(toml::detail::location&) ()
#1  0x0000000000000000 in ?? ()

Stacktrace, on version 2.18.1:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00000000007b9983 in nix::getHome[abi:cxx11]()::{lambda()#1}::operator()() const [clone .isra.0] ()
(gdb) bt
#0  0x00000000007b9983 in nix::getHome[abi:cxx11]()::{lambda()#1}::operator()() const [clone .isra.0] ()
#1  0x00000000007b9db7 in nix::getHome[abi:cxx11]() ()
#2  0x000000000065a70d in nix::getNixDefExpr[abi:cxx11]() ()
#3  0x000000000065bc18 in nix::EvalSettings::getDefaultNixPath[abi:cxx11]() ()
#4  0x000000000065c70e in nix::EvalSettings::EvalSettings() ()
#5  0x00000000004aa2d1 in _GLOBAL__sub_I_eval_settings.cc ()
#6  0x0000000001288bad in __libc_start_init ()
#7  0x0000000001288bd2 in libc_start_main_stage2 ()
#8  0x00000000004b76cb in _start ()

Steps To Reproduce

# As root
useradd someuser
mkdir /home/someuser
chown someuser /home/someuser
HOME=/home/someuser ./nix

Expected behavior

It should fallback to the user's home directory, and/or ignore the HOME folder, as if it didn't exist. That seems to work for the non-static build:

warning: $HOME ('/home/someuser') is not owned by you, falling back to the one defined in the 'passwd' file ('/root')

nix-env --version output

https://hydra.nixos.org/build/261167110 and also version 2.18.1 from nixpkgs.

Additional context

I encountered this when trying to make the static nix binary setuid. Seemed like a simple way to have a kind of static multi-user nix, if you don't care about users getting root access (in a container in my case).

Priorities

Add :+1: to issues you find important.

fricklerhandwerk commented 3 months ago

Triaged in Nix maintainers meeting:

nixos-discourse commented 3 months ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2024-05-29-nix-team-meeting-minutes-148/46195/1

Qyriad commented 3 months ago

Lix has the same bug — seems to be the nix::logger global that's nullptr:

Starting program: /home/qyriad/code/lix/build/src/nix/nix --version

Program received signal SIGSEGV, Segmentation fault.
0x0000000000a58aab in nix::warn<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > (fs=...) at src/libutil/logging.hh:231
231     inline void warn(const std::string & fs, const Args & ... args)
(gdb) p nix::logger
$1 = (nix::Logger *) 0x0
Qyriad commented 3 months ago

Linking nix against libutil with -Wl,--whole-archive when building statically seems to fix/workaround the issue