Sync with 2.40.2

* maint-2.40: (39 commits)
  Git 2.40.2
  Git 2.39.4
  fsck: warn about symlink pointing inside a gitdir
  core.hooksPath: add some protection while cloning
  init.templateDir: consider this config setting protected
  clone: prevent hooks from running during a clone
  Add a helper function to compare file contents
  init: refactor the template directory discovery into its own function
  find_hook(): refactor the `STRIP_EXTENSION` logic
  clone: when symbolic links collide with directories, keep the latter
  entry: report more colliding paths
  t5510: verify that D/F confusion cannot lead to an RCE
  submodule: require the submodule path to contain directories only
  clone_submodule: avoid using `access()` on directories
  submodules: submodule paths must not contain symlinks
  clone: prevent clashing git dirs when cloning submodule in parallel
  t7423: add tests for symlinked submodule directories
  has_dir_name(): do not get confused by characters < '/'
  docs: document security issues around untrusted .git dirs
  upload-pack: disable lazy-fetching by default
  ...
This commit is contained in:
Johannes Schindelin
2024-04-17 11:38:18 +02:00
47 changed files with 1324 additions and 124 deletions

53
hook.c
View File

@ -6,25 +6,56 @@
#include "run-command.h"
#include "config.h"
#include "strbuf.h"
#include "environment.h"
#include "setup.h"
#include "copy.h"
static int identical_to_template_hook(const char *name, const char *path)
{
const char *env = getenv("GIT_CLONE_TEMPLATE_DIR");
const char *template_dir = get_template_dir(env && *env ? env : NULL);
struct strbuf template_path = STRBUF_INIT;
int found_template_hook, ret;
strbuf_addf(&template_path, "%s/hooks/%s", template_dir, name);
found_template_hook = access(template_path.buf, X_OK) >= 0;
#ifdef STRIP_EXTENSION
if (!found_template_hook) {
strbuf_addstr(&template_path, STRIP_EXTENSION);
found_template_hook = access(template_path.buf, X_OK) >= 0;
}
#endif
if (!found_template_hook)
return 0;
ret = do_files_match(template_path.buf, path);
strbuf_release(&template_path);
return ret;
}
const char *find_hook(const char *name)
{
static struct strbuf path = STRBUF_INIT;
int found_hook;
strbuf_reset(&path);
strbuf_git_path(&path, "hooks/%s", name);
if (access(path.buf, X_OK) < 0) {
found_hook = access(path.buf, X_OK) >= 0;
#ifdef STRIP_EXTENSION
if (!found_hook) {
int err = errno;
#ifdef STRIP_EXTENSION
strbuf_addstr(&path, STRIP_EXTENSION);
if (access(path.buf, X_OK) >= 0)
return path.buf;
if (errno == EACCES)
err = errno;
found_hook = access(path.buf, X_OK) >= 0;
if (!found_hook)
errno = err;
}
#endif
if (err == EACCES && advice_enabled(ADVICE_IGNORED_HOOK)) {
if (!found_hook) {
if (errno == EACCES && advice_enabled(ADVICE_IGNORED_HOOK)) {
static struct string_list advise_given = STRING_LIST_INIT_DUP;
if (!string_list_lookup(&advise_given, name)) {
@ -38,6 +69,14 @@ const char *find_hook(const char *name)
}
return NULL;
}
if (!git_hooks_path && git_env_bool("GIT_CLONE_PROTECTION_ACTIVE", 0) &&
!identical_to_template_hook(name, path.buf))
die(_("active `%s` hook found during `git clone`:\n\t%s\n"
"For security reasons, this is disallowed by default.\n"
"If this is intentional and the hook should actually "
"be run, please\nrun the command again with "
"`GIT_CLONE_PROTECTION_ACTIVE=false`"),
name, path.buf);
return path.buf;
}