Sync with 2.43.4
* maint-2.43: (40 commits) Git 2.43.4 Git 2.42.2 Git 2.41.1 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 ...
This commit is contained in:
@ -329,7 +329,20 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
|
||||
int src_len, dest_len;
|
||||
struct dir_iterator *iter;
|
||||
int iter_status;
|
||||
struct strbuf realpath = STRBUF_INIT;
|
||||
|
||||
/*
|
||||
* Refuse copying directories by default which aren't owned by us. The
|
||||
* code that performs either the copying or hardlinking is not prepared
|
||||
* to handle various edge cases where an adversary may for example
|
||||
* racily swap out files for symlinks. This can cause us to
|
||||
* inadvertently use the wrong source file.
|
||||
*
|
||||
* Furthermore, even if we were prepared to handle such races safely,
|
||||
* creating hardlinks across user boundaries is an inherently unsafe
|
||||
* operation as the hardlinked files can be rewritten at will by the
|
||||
* potentially-untrusted user. We thus refuse to do so by default.
|
||||
*/
|
||||
die_upon_dubious_ownership(NULL, NULL, src_repo);
|
||||
|
||||
mkdir_if_missing(dest->buf, 0777);
|
||||
|
||||
@ -377,9 +390,27 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
|
||||
if (unlink(dest->buf) && errno != ENOENT)
|
||||
die_errno(_("failed to unlink '%s'"), dest->buf);
|
||||
if (!option_no_hardlinks) {
|
||||
strbuf_realpath(&realpath, src->buf, 1);
|
||||
if (!link(realpath.buf, dest->buf))
|
||||
if (!link(src->buf, dest->buf)) {
|
||||
struct stat st;
|
||||
|
||||
/*
|
||||
* Sanity-check whether the created hardlink
|
||||
* actually links to the expected file now. This
|
||||
* catches time-of-check-time-of-use bugs in
|
||||
* case the source file was meanwhile swapped.
|
||||
*/
|
||||
if (lstat(dest->buf, &st))
|
||||
die(_("hardlink cannot be checked at '%s'"), dest->buf);
|
||||
if (st.st_mode != iter->st.st_mode ||
|
||||
st.st_ino != iter->st.st_ino ||
|
||||
st.st_dev != iter->st.st_dev ||
|
||||
st.st_size != iter->st.st_size ||
|
||||
st.st_uid != iter->st.st_uid ||
|
||||
st.st_gid != iter->st.st_gid)
|
||||
die(_("hardlink different from source at '%s'"), dest->buf);
|
||||
|
||||
continue;
|
||||
}
|
||||
if (option_local > 0)
|
||||
die_errno(_("failed to create link '%s'"), dest->buf);
|
||||
option_no_hardlinks = 1;
|
||||
@ -392,8 +423,6 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
|
||||
strbuf_setlen(src, src_len);
|
||||
die(_("failed to iterate over '%s'"), src->buf);
|
||||
}
|
||||
|
||||
strbuf_release(&realpath);
|
||||
}
|
||||
|
||||
static void clone_local(const char *src_repo, const char *dest_repo)
|
||||
@ -936,6 +965,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
int hash_algo;
|
||||
unsigned int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
|
||||
const int do_not_override_repo_unix_permissions = -1;
|
||||
const char *template_dir;
|
||||
char *template_dir_dup = NULL;
|
||||
|
||||
struct transport_ls_refs_options transport_ls_refs_options =
|
||||
TRANSPORT_LS_REFS_OPTIONS_INIT;
|
||||
@ -955,6 +986,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
usage_msg_opt(_("You must specify a repository to clone."),
|
||||
builtin_clone_usage, builtin_clone_options);
|
||||
|
||||
xsetenv("GIT_CLONE_PROTECTION_ACTIVE", "true", 0 /* allow user override */);
|
||||
template_dir = get_template_dir(option_template);
|
||||
if (*template_dir && !is_absolute_path(template_dir))
|
||||
template_dir = template_dir_dup =
|
||||
absolute_pathdup(template_dir);
|
||||
xsetenv("GIT_CLONE_TEMPLATE_DIR", template_dir, 1);
|
||||
|
||||
if (option_depth || option_since || option_not.nr)
|
||||
deepen = 1;
|
||||
if (option_single_branch == -1)
|
||||
@ -1116,7 +1154,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
* repository, and reference backends may persist that information into
|
||||
* their on-disk data structures.
|
||||
*/
|
||||
init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN,
|
||||
init_db(git_dir, real_git_dir, template_dir, GIT_HASH_UNKNOWN,
|
||||
ref_storage_format, NULL,
|
||||
do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
|
||||
|
||||
@ -1460,6 +1498,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
||||
free(dir);
|
||||
free(path);
|
||||
free(repo_to_free);
|
||||
free(template_dir_dup);
|
||||
junk_mode = JUNK_LEAVE_ALL;
|
||||
|
||||
transport_ls_refs_options_release(&transport_ls_refs_options);
|
||||
|
Reference in New Issue
Block a user