Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nix
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: e232bf2b6993
Choose a base ref
...
head repository: NixOS/nix
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0fb4744467b0
Choose a head ref
  • 10 commits
  • 17 files changed
  • 1 contributor

Commits on Oct 9, 2019

  1. Filter ANSI escape sequences in -L output

    Otherwise, builds like NixOS VM tests may leave the terminal in a
    weird state and do resets.
    
    (cherry picked from commit 4331eeb)
    edolstra committed Oct 9, 2019

    Unverified

    The email in this signature doesn’t match the committer email.
    Copy the full SHA
    910b0fc View commit details
  2. Remove world-writability from per-user directories

    'nix-daemon' now creates subdirectories for users when they first
    connect.
    
    Fixes #509 (CVE-2019-17365).
    Should also fix #3127.
    
    (cherry picked from commit 5a30309)
    edolstra committed Oct 9, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6595378 View commit details
  3. Remove some redundant initialization

    (cherry picked from commit c43d9f6)
    edolstra committed Oct 9, 2019
    Copy the full SHA
    923b6bd View commit details
  4. nix-profile.sh: Don't create .nix-channels

    This is already done by the installer, so no need to do it again.
    
    (cherry picked from commit 26762ce)
    edolstra committed Oct 9, 2019
    Copy the full SHA
    2522757 View commit details
  5. nix-profile.sh: Remove coreutils dependency

    (cherry picked from commit 61a6176)
    edolstra committed Oct 9, 2019
    Copy the full SHA
    1c10f73 View commit details
  6. Go back to 755 permission on per-user directories

    700 is pointless since the store is world-readable anyway. And
    per-user/root/channels must be world-readable.
    
    (cherry picked from commit d7bae56)
    edolstra committed Oct 9, 2019
    Copy the full SHA
    7c45898 View commit details
  7. Typo

    (cherry picked from commit 9277e72)
    edolstra committed Oct 9, 2019
    Copy the full SHA
    fe51fba View commit details
  8. Force per-user group to a known value

    (cherry picked from commit 20eec80)
    edolstra committed Oct 9, 2019
    Copy the full SHA
    2070d55 View commit details
  9. nix-env: Create ~/.nix-profile automatically

    (cherry picked from commit 9348f92)
    edolstra committed Oct 9, 2019
    Copy the full SHA
    f66108f View commit details
  10. nix-env: Create ~/.nix-defexpr automatically

    (cherry picked from commit c9159f8)
    edolstra committed Oct 9, 2019
    Copy the full SHA
    0fb4744 View commit details
2 changes: 1 addition & 1 deletion nix.spec.in
Original file line number Diff line number Diff line change
@@ -106,7 +106,7 @@ chmod 1775 $RPM_BUILD_ROOT/nix/store
for d in profiles gcroots;
do
mkdir -p $RPM_BUILD_ROOT/nix/var/nix/$d/per-user
chmod 1777 $RPM_BUILD_ROOT/nix/var/nix/$d/per-user
chmod 755 $RPM_BUILD_ROOT/nix/var/nix/$d/per-user
done

# fix permission of nix profile
17 changes: 5 additions & 12 deletions scripts/install-multi-user.sh
Original file line number Diff line number Diff line change
@@ -529,24 +529,17 @@ create_build_users() {
}

create_directories() {
# FIXME: remove all of this because it duplicates LocalStore::LocalStore().

_sudo "to make the basic directory structure of Nix (part 1)" \
mkdir -pv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool}
mkdir -pv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool} /nix/var/nix/{gcroots,profiles}/per-user

_sudo "to make the basic directory structure of Nix (part 2)" \
mkdir -pv -m 1777 /nix/var/nix/{gcroots,profiles}/per-user

_sudo "to make the basic directory structure of Nix (part 3)" \
mkdir -pv -m 1775 /nix/store

_sudo "to make the basic directory structure of Nix (part 4)" \
_sudo "to make the basic directory structure of Nix (part 3)" \
chgrp "$NIX_BUILD_GROUP_NAME" /nix/store

_sudo "to set up the root user's profile (part 1)" \
mkdir -pv -m 0755 /nix/var/nix/profiles/per-user/root

_sudo "to set up the root user's profile (part 2)" \
mkdir -pv -m 0700 "$ROOT_HOME/.nix-defexpr"

_sudo "to place the default nix daemon configuration (part 1)" \
mkdir -pv -m 0555 /etc/nix
}
@@ -589,7 +582,7 @@ EOF
We will:
- make sure your computer doesn't already have Nix files
(if it does, I will tell you how to clean them up.)
(if it does, I will tell you how to clean them up.)
- create local users (see the list above for the users we'll make)
- create a local group ($NIX_BUILD_GROUP_NAME)
- install Nix in to $NIX_ROOT
39 changes: 0 additions & 39 deletions scripts/nix-profile-daemon.sh.in
Original file line number Diff line number Diff line change
@@ -5,45 +5,6 @@ __ETC_PROFILE_NIX_SOURCED=1
export NIX_USER_PROFILE_DIR="@localstatedir@/nix/profiles/per-user/$USER"
export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile"

# Set up the per-user profile.
mkdir -m 0755 -p $NIX_USER_PROFILE_DIR
if ! test -O "$NIX_USER_PROFILE_DIR"; then
echo "WARNING: bad ownership on $NIX_USER_PROFILE_DIR" >&2
fi

if test -w $HOME; then
if ! test -L $HOME/.nix-profile; then
if test "$USER" != root; then
ln -s $NIX_USER_PROFILE_DIR/profile $HOME/.nix-profile
else
# Root installs in the system-wide profile by default.
ln -s @localstatedir@/nix/profiles/default $HOME/.nix-profile
fi
fi

# Subscribe the root user to the NixOS channel by default.
if [ "$USER" = root -a ! -e $HOME/.nix-channels ]; then
echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > $HOME/.nix-channels
fi

# Create the per-user garbage collector roots directory.
NIX_USER_GCROOTS_DIR=@localstatedir@/nix/gcroots/per-user/$USER
mkdir -m 0755 -p $NIX_USER_GCROOTS_DIR
if ! test -O "$NIX_USER_GCROOTS_DIR"; then
echo "WARNING: bad ownership on $NIX_USER_GCROOTS_DIR" >&2
fi

# Set up a default Nix expression from which to install stuff.
if [ ! -e $HOME/.nix-defexpr -o -L $HOME/.nix-defexpr ]; then
rm -f $HOME/.nix-defexpr
mkdir -p $HOME/.nix-defexpr
if [ "$USER" != root ]; then
ln -s @localstatedir@/nix/profiles/per-user/root/channels $HOME/.nix-defexpr/channels_root
fi
fi
fi


# Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work.
if [ ! -z "${NIX_SSL_CERT_FILE:-}" ]; then
: # Allow users to override the NIX_SSL_CERT_FILE
48 changes: 2 additions & 46 deletions scripts/nix-profile.sh.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
if [ -n "$HOME" ] && [ -n "$USER" ]; then
__savedpath="$PATH"
export PATH=@coreutils@

# Set up the per-user profile.
# This part should be kept in sync with nixpkgs:nixos/modules/programs/shell.nix
@@ -9,48 +7,6 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then

NIX_USER_PROFILE_DIR=@localstatedir@/nix/profiles/per-user/$USER

mkdir -m 0755 -p "$NIX_USER_PROFILE_DIR"

if [ "$(stat --printf '%u' "$NIX_USER_PROFILE_DIR")" != "$(id -u)" ]; then
echo "Nix: WARNING: bad ownership on "$NIX_USER_PROFILE_DIR", should be $(id -u)" >&2
fi

if [ -w "$HOME" ]; then
if ! [ -L "$NIX_LINK" ]; then
echo "Nix: creating $NIX_LINK" >&2
if [ "$USER" != root ]; then
if ! ln -s "$NIX_USER_PROFILE_DIR"/profile "$NIX_LINK"; then
echo "Nix: WARNING: could not create $NIX_LINK -> $NIX_USER_PROFILE_DIR/profile" >&2
fi
else
# Root installs in the system-wide profile by default.
ln -s @localstatedir@/nix/profiles/default "$NIX_LINK"
fi
fi

# Subscribe the user to the unstable Nixpkgs channel by default.
if [ ! -e "$HOME/.nix-channels" ]; then
echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$HOME/.nix-channels"
fi

# Create the per-user garbage collector roots directory.
__user_gcroots=@localstatedir@/nix/gcroots/per-user/"$USER"
mkdir -m 0755 -p "$__user_gcroots"
if [ "$(stat --printf '%u' "$__user_gcroots")" != "$(id -u)" ]; then
echo "Nix: WARNING: bad ownership on $__user_gcroots, should be $(id -u)" >&2
fi
unset __user_gcroots

# Set up a default Nix expression from which to install stuff.
__nix_defexpr="$HOME"/.nix-defexpr
[ -L "$__nix_defexpr" ] && rm -f "$__nix_defexpr"
mkdir -m 0755 -p "$__nix_defexpr"
if [ "$USER" != root ] && [ ! -L "$__nix_defexpr"/channels_root ]; then
ln -s @localstatedir@/nix/profiles/per-user/root/channels "$__nix_defexpr"/channels_root
fi
unset __nix_defexpr
fi

# Append ~/.nix-defexpr/channels to $NIX_PATH so that <nixpkgs>
# paths work when the user has fetched the Nixpkgs channel.
export NIX_PATH=${NIX_PATH:+$NIX_PATH:}$HOME/.nix-defexpr/channels
@@ -78,6 +34,6 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
export MANPATH="$NIX_LINK/share/man:$MANPATH"
fi

export PATH="$NIX_LINK/bin:$__savedpath"
unset __savedpath NIX_LINK NIX_USER_PROFILE_DIR
export PATH="$NIX_LINK/bin:$PATH"
unset NIX_LINK NIX_USER_PROFILE_DIR
fi
29 changes: 23 additions & 6 deletions src/libstore/local-store.cc
Original file line number Diff line number Diff line change
@@ -70,15 +70,17 @@ LocalStore::LocalStore(const Params & params)
createSymlink(profilesDir, gcRootsDir + "/profiles");
}

for (auto & perUserDir : {profilesDir + "/per-user", gcRootsDir + "/per-user"}) {
createDirs(perUserDir);
if (chmod(perUserDir.c_str(), 0755) == -1)
throw SysError("could not set permissions on '%s' to 755", perUserDir);
}

createUser(getUserName(), getuid());

/* Optionally, create directories and set permissions for a
multi-user install. */
if (getuid() == 0 && settings.buildUsersGroup != "") {

Path perUserDir = profilesDir + "/per-user";
createDirs(perUserDir);
if (chmod(perUserDir.c_str(), 01777) == -1)
throw SysError(format("could not set permissions on '%1%' to 1777") % perUserDir);

mode_t perm = 01775;

struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
@@ -1433,4 +1435,19 @@ void LocalStore::signPathInfo(ValidPathInfo & info)
}


void LocalStore::createUser(const std::string & userName, uid_t userId)
{
for (auto & dir : {
fmt("%s/profiles/per-user/%s", stateDir, userName),
fmt("%s/gcroots/per-user/%s", stateDir, userName)
}) {
createDirs(dir);
if (chmod(dir.c_str(), 0755) == -1)
throw SysError("changing permissions of directory '%s'", dir);
if (chown(dir.c_str(), userId, 0) == -1)
throw SysError("changing owner of directory '%s'", dir);
}
}


}
2 changes: 2 additions & 0 deletions src/libstore/local-store.hh
Original file line number Diff line number Diff line change
@@ -293,6 +293,8 @@ private:

Path getRealStoreDir() override { return realStoreDir; }

void createUser(const std::string & userName, uid_t userId) override;

friend class DerivationGoal;
friend class SubstitutionGoal;
};
3 changes: 3 additions & 0 deletions src/libstore/store-api.hh
Original file line number Diff line number Diff line change
@@ -628,6 +628,9 @@ public:
return storePath;
}

virtual void createUser(const std::string & userName, uid_t userId)
{ }

protected:

Stats stats;
10 changes: 10 additions & 0 deletions src/libutil/util.cc
Original file line number Diff line number Diff line change
@@ -475,6 +475,16 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
}


std::string getUserName()
{
auto pw = getpwuid(geteuid());
std::string name = pw ? pw->pw_name : getEnv("USER", "");
if (name.empty())
throw Error("cannot figure out user name");
return name;
}


static Lazy<Path> getHome2([]() {
Path homeDir = getEnv("HOME");
if (homeDir.empty()) {
2 changes: 2 additions & 0 deletions src/libutil/util.hh
Original file line number Diff line number Diff line change
@@ -126,6 +126,8 @@ void deletePath(const Path & path, unsigned long long & bytesFreed);
Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);

std::string getUserName();

/* Return $HOME or the user's home directory from /etc/passwd. */
Path getHome();

8 changes: 1 addition & 7 deletions src/nix-channel/nix-channel.cc
Original file line number Diff line number Diff line change
@@ -159,13 +159,7 @@ static int _main(int argc, char ** argv)
nixDefExpr = home + "/.nix-defexpr";

// Figure out the name of the channels profile.
;
auto pw = getpwuid(geteuid());
std::string name = pw ? pw->pw_name : getEnv("USER", "");
if (name.empty())
throw Error("cannot figure out user name");
profile = settings.nixStateDir + "/profiles/per-user/" + name + "/channels";
createDirs(dirOf(profile));
profile = fmt("%s/profiles/per-user/%s/channels", settings.nixStateDir, getUserName());

enum {
cNone,
9 changes: 6 additions & 3 deletions src/nix-daemon/nix-daemon.cc
Original file line number Diff line number Diff line change
@@ -742,7 +742,8 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
}


static void processConnection(bool trusted)
static void processConnection(bool trusted,
const std::string & userName, uid_t userId)
{
MonitorFdHup monitor(from.fd);

@@ -793,6 +794,8 @@ static void processConnection(bool trusted)
params["path-info-cache-size"] = "0";
auto store = openStore(settings.storeUri, params);

store->createUser(userName, userId);

tunnelLogger->stopWork();
to.flush();

@@ -1053,7 +1056,7 @@ static void daemonLoop(char * * argv)
/* Handle the connection. */
from.fd = remote.get();
to.fd = remote.get();
processConnection(trusted);
processConnection(trusted, user, peer.uid);

exit(0);
}, options);
@@ -1133,7 +1136,7 @@ static int _main(int argc, char * * argv)
}
}
} else {
processConnection(true);
processConnection(true, "root", 0);
}
} else {
daemonLoop(argv);
30 changes: 20 additions & 10 deletions src/nix-env/nix-env.cc
Original file line number Diff line number Diff line change
@@ -193,12 +193,6 @@ static void loadDerivations(EvalState & state, Path nixExprPath,
}


static Path getDefNixExprPath()
{
return getHome() + "/.nix-defexpr";
}


static long getPriority(EvalState & state, DrvInfo & drv)
{
return drv.queryMetaInt("priority", 0);
@@ -1330,9 +1324,20 @@ static int _main(int argc, char * * argv)
Globals globals;

globals.instSource.type = srcUnknown;
globals.instSource.nixExprPath = getDefNixExprPath();
globals.instSource.nixExprPath = getHome() + "/.nix-defexpr";
globals.instSource.systemFilter = "*";

if (!pathExists(globals.instSource.nixExprPath)) {
createDirs(globals.instSource.nixExprPath);
replaceSymlink(
fmt("%s/profiles/per-user/%s/channels", settings.nixStateDir, getUserName()),
globals.instSource.nixExprPath + "/channels");
if (getuid() != 0)
replaceSymlink(
fmt("%s/profiles/per-user/root/channels", settings.nixStateDir),
globals.instSource.nixExprPath + "/channels_root");
}

globals.dryRun = false;
globals.preserveInstalled = false;
globals.removeAll = false;
@@ -1425,9 +1430,14 @@ static int _main(int argc, char * * argv)

if (globals.profile == "") {
Path profileLink = getHome() + "/.nix-profile";
globals.profile = pathExists(profileLink)
? absPath(readLink(profileLink), dirOf(profileLink))
: canonPath(settings.nixStateDir + "/profiles/default");
if (!pathExists(profileLink)) {
replaceSymlink(
getuid() == 0
? settings.nixStateDir + "/profiles/default"
: fmt("%s/profiles/per-user/%s/profile", settings.nixStateDir, getUserName()),
profileLink);
}
globals.profile = absPath(readLink(profileLink), dirOf(profileLink));
}

op(globals, opFlags, opArgs);
2 changes: 1 addition & 1 deletion src/nix/progress-bar.cc
Original file line number Diff line number Diff line change
@@ -120,7 +120,7 @@ class ProgressBar : public Logger
void log(State & state, Verbosity lvl, const std::string & s)
{
if (state.active) {
writeToStderr("\r\e[K" + s + ANSI_NORMAL "\n");
writeToStderr("\r\e[K" + filterANSIEscapes(s, !isTTY) + ANSI_NORMAL "\n");
draw(state);
} else {
auto s2 = s + ANSI_NORMAL "\n";
4 changes: 2 additions & 2 deletions tests/nix-channel.sh
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ grep -q 'item.*attrPath="foo".*name="dependencies"' $TEST_ROOT/meta.xml

# Do an install.
nix-env -i dependencies
[ -e $TEST_ROOT/var/nix/profiles/default/foobar ]
[ -e $TEST_HOME/.nix-profile/foobar ]

clearProfiles
rm -f $TEST_HOME/.nix-channels
@@ -55,5 +55,5 @@ grep -q 'item.*attrPath="foo".*name="dependencies"' $TEST_ROOT/meta.xml

# Do an install.
nix-env -i dependencies
[ -e $TEST_ROOT/var/nix/profiles/default/foobar ]
[ -e $TEST_HOME/.nix-profile/foobar ]

5 changes: 0 additions & 5 deletions tests/nix-profile.sh
Original file line number Diff line number Diff line change
@@ -7,8 +7,3 @@ rm -rf $TEST_HOME $TEST_ROOT/profile-var
mkdir -p $TEST_HOME
USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh; set"
USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh" # test idempotency

[ -L $TEST_HOME/.nix-profile ]
[ -e $TEST_HOME/.nix-channels ]
[ -e $TEST_ROOT/profile-var/nix/gcroots/per-user/$user ]
[ -e $TEST_ROOT/profile-var/nix/profiles/per-user/$user ]
4 changes: 4 additions & 0 deletions tests/remote-store.sh
Original file line number Diff line number Diff line change
@@ -13,3 +13,7 @@ cmp $TEST_ROOT/d1 $TEST_ROOT/d2
nix-store --gc --max-freed 1K

killDaemon

user=$(whoami)
[ -e $NIX_STATE_DIR/gcroots/per-user/$user ]
[ -e $NIX_STATE_DIR/profiles/per-user/$user ]
Loading