aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaximilian Bosch <maximilian@mbosch.me>2022-04-23 23:04:35 +0200
committerMaximilian Bosch <maximilian@mbosch.me>2022-04-23 23:20:17 +0200
commit0256e5578e97a11db66207e1f8e231db115c91f8 (patch)
tree52db58bb7e3be5308a2750ba14ffed2aa7b3c243
parent7f814d6d9af9d78f922d59115a94078f807676a8 (diff)
libfetchers/git: hardcode `--git-dir`
To demonstrate the problem: * You need a `git` at 2.33.3 in your $PATH * An expression like this in a git repository: ``` nix { outputs = { self, nixpkgs }: { packages.foo.x86_64-linux = with nixpkgs.legacyPackages.x86_64-linux; runCommand "snens" { } '' echo ${(builtins.fetchGit ./.).lastModifiedDate} > $out ''; }; } ``` Now, when instantiating the package via `builtins.getFlake`, it fails on Nix 2.7 like this: $ nix-instantiate -E '(builtins.getFlake "'"$(pwd)"'").packages.foo.x86_64-linux' fatal: unsafe repository ('/nix/store/a7j3125km4h8l0p71q6ssfkxamfh5d61-source' is owned by someone else) To add an exception for this directory, call: git config --global --add safe.directory /nix/store/a7j3125km4h8l0p71q6ssfkxamfh5d61-source error: program 'git' failed with exit code 128 (use '--show-trace' to show detailed location information) This breaks e.g. `nixops`-deployments using flakes with similar expressions as shown above. The cause for this is that `git(1)` tries to find the highest `.git`-directory in the directory tree and if it finds a such a directory, but with another owning user (root vs. the user who evaluates the expression), it fails as above. This was changed recently to fix CVE-2022-24765[1]. By explicitly specifying `--git-dir`, Git assumes to be in the top-level directory and doesn't attempt to look for a `.git`-directory in the parent directories and thus the code-path leading to said error is never reached. [1] https://lore.kernel.org/git/xmqqv8veb5i6.fsf@gitster.g/
-rw-r--r--src/libfetchers/git.cc14
1 files changed, 7 insertions, 7 deletions
diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc
index 34b1342a0..219a5ca7a 100644
--- a/src/libfetchers/git.cc
+++ b/src/libfetchers/git.cc
@@ -23,7 +23,7 @@ const std::string gitInitialBranch = "__nix_dummy_branch";
static std::string readHead(const Path & path)
{
- return chomp(runProgram("git", true, { "-C", path, "rev-parse", "--abbrev-ref", "HEAD" }));
+ return chomp(runProgram("git", true, { "-C", path, "--git-dir", ".git", "rev-parse", "--abbrev-ref", "HEAD" }));
}
static bool isNotDotGitDirectory(const Path & path)
@@ -152,11 +152,11 @@ struct GitInputScheme : InputScheme
assert(sourcePath);
runProgram("git", true,
- { "-C", *sourcePath, "add", "--force", "--intent-to-add", "--", std::string(file) });
+ { "-C", *sourcePath, "--git-dir", ".git", "add", "--force", "--intent-to-add", "--", std::string(file) });
if (commitMsg)
runProgram("git", true,
- { "-C", *sourcePath, "commit", std::string(file), "-m", *commitMsg });
+ { "-C", *sourcePath, "--git-dir", ".git", "commit", std::string(file), "-m", *commitMsg });
}
std::pair<bool, std::string> getActualUrl(const Input & input) const
@@ -259,7 +259,7 @@ struct GitInputScheme : InputScheme
if (hasHead) {
// Using git diff is preferrable over lower-level operations here,
// because its conceptually simpler and we only need the exit code anyways.
- auto gitDiffOpts = Strings({ "-C", actualUrl, "diff", "HEAD", "--quiet"});
+ auto gitDiffOpts = Strings({ "-C", actualUrl, "--git-dir", ".git", "diff", "HEAD", "--quiet"});
if (!submodules) {
// Changes in submodules should only make the tree dirty
// when those submodules will be copied as well.
@@ -284,7 +284,7 @@ struct GitInputScheme : InputScheme
if (fetchSettings.warnDirty)
warn("Git tree '%s' is dirty", actualUrl);
- auto gitOpts = Strings({ "-C", actualUrl, "ls-files", "-z" });
+ auto gitOpts = Strings({ "-C", actualUrl, "--git-dir", ".git", "ls-files", "-z" });
if (submodules)
gitOpts.emplace_back("--recurse-submodules");
@@ -314,7 +314,7 @@ struct GitInputScheme : InputScheme
// modified dirty file?
input.attrs.insert_or_assign(
"lastModified",
- hasHead ? std::stoull(runProgram("git", true, { "-C", actualPath, "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0);
+ hasHead ? std::stoull(runProgram("git", true, { "-C", actualPath, "--git-dir", ".git", "log", "-1", "--format=%ct", "--no-show-signature", "HEAD" })) : 0);
return {std::move(storePath), input};
}
@@ -335,7 +335,7 @@ struct GitInputScheme : InputScheme
if (!input.getRev())
input.attrs.insert_or_assign("rev",
- Hash::parseAny(chomp(runProgram("git", true, { "-C", actualUrl, "rev-parse", *input.getRef() })), htSHA1).gitRev());
+ Hash::parseAny(chomp(runProgram("git", true, { "-C", actualUrl, "--git-dir", ".git", "rev-parse", *input.getRef() })), htSHA1).gitRev());
repoDir = actualUrl;