Merge branch 'dubiously-nested-submodules'
Recursive clones are currently affected by a vulnerability that is caused by too-lax validation of submodule names. This topic branch fixes that. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
commit
76a681ce9c
@ -678,6 +678,10 @@ static int module_clone(int argc, const char **argv, const char *prefix)
|
|||||||
} else
|
} else
|
||||||
path = xstrdup(path);
|
path = xstrdup(path);
|
||||||
|
|
||||||
|
if (validate_submodule_git_dir(sm_gitdir, name) < 0)
|
||||||
|
die(_("refusing to create/use '%s' in another submodule's "
|
||||||
|
"git dir"), sm_gitdir);
|
||||||
|
|
||||||
if (!file_exists(sm_gitdir)) {
|
if (!file_exists(sm_gitdir)) {
|
||||||
if (safe_create_leading_directories_const(sm_gitdir) < 0)
|
if (safe_create_leading_directories_const(sm_gitdir) < 0)
|
||||||
die(_("could not create directory '%s'"), sm_gitdir);
|
die(_("could not create directory '%s'"), sm_gitdir);
|
||||||
|
49
submodule.c
49
submodule.c
@ -1842,6 +1842,47 @@ int parallel_submodules(void)
|
|||||||
return parallel_jobs;
|
return parallel_jobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int validate_submodule_git_dir(char *git_dir, const char *submodule_name)
|
||||||
|
{
|
||||||
|
size_t len = strlen(git_dir), suffix_len = strlen(submodule_name);
|
||||||
|
char *p;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (len <= suffix_len || (p = git_dir + len - suffix_len)[-1] != '/' ||
|
||||||
|
strcmp(p, submodule_name))
|
||||||
|
BUG("submodule name '%s' not a suffix of git dir '%s'",
|
||||||
|
submodule_name, git_dir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We prevent the contents of sibling submodules' git directories to
|
||||||
|
* clash.
|
||||||
|
*
|
||||||
|
* Example: having a submodule named `hippo` and another one named
|
||||||
|
* `hippo/hooks` would result in the git directories
|
||||||
|
* `.git/modules/hippo/` and `.git/modules/hippo/hooks/`, respectively,
|
||||||
|
* but the latter directory is already designated to contain the hooks
|
||||||
|
* of the former.
|
||||||
|
*/
|
||||||
|
for (; *p; p++) {
|
||||||
|
if (is_dir_sep(*p)) {
|
||||||
|
char c = *p;
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
if (is_git_directory(git_dir))
|
||||||
|
ret = -1;
|
||||||
|
*p = c;
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
return error(_("submodule git dir '%s' is "
|
||||||
|
"inside git dir '%.*s'"),
|
||||||
|
git_dir,
|
||||||
|
(int)(p - git_dir), git_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Embeds a single submodules git directory into the superprojects git dir,
|
* Embeds a single submodules git directory into the superprojects git dir,
|
||||||
* non recursively.
|
* non recursively.
|
||||||
@ -1850,7 +1891,7 @@ static void relocate_single_git_dir_into_superproject(const char *prefix,
|
|||||||
const char *path)
|
const char *path)
|
||||||
{
|
{
|
||||||
char *old_git_dir = NULL, *real_old_git_dir = NULL, *real_new_git_dir = NULL;
|
char *old_git_dir = NULL, *real_old_git_dir = NULL, *real_new_git_dir = NULL;
|
||||||
const char *new_git_dir;
|
char *new_git_dir;
|
||||||
const struct submodule *sub;
|
const struct submodule *sub;
|
||||||
|
|
||||||
if (submodule_uses_worktrees(path))
|
if (submodule_uses_worktrees(path))
|
||||||
@ -1868,10 +1909,14 @@ static void relocate_single_git_dir_into_superproject(const char *prefix,
|
|||||||
if (!sub)
|
if (!sub)
|
||||||
die(_("could not lookup name for submodule '%s'"), path);
|
die(_("could not lookup name for submodule '%s'"), path);
|
||||||
|
|
||||||
new_git_dir = git_path("modules/%s", sub->name);
|
new_git_dir = git_pathdup("modules/%s", sub->name);
|
||||||
|
if (validate_submodule_git_dir(new_git_dir, sub->name) < 0)
|
||||||
|
die(_("refusing to move '%s' into an existing git dir"),
|
||||||
|
real_old_git_dir);
|
||||||
if (safe_create_leading_directories_const(new_git_dir) < 0)
|
if (safe_create_leading_directories_const(new_git_dir) < 0)
|
||||||
die(_("could not create directory '%s'"), new_git_dir);
|
die(_("could not create directory '%s'"), new_git_dir);
|
||||||
real_new_git_dir = real_pathdup(new_git_dir, 1);
|
real_new_git_dir = real_pathdup(new_git_dir, 1);
|
||||||
|
free(new_git_dir);
|
||||||
|
|
||||||
fprintf(stderr, _("Migrating git directory of '%s%s' from\n'%s' to\n'%s'\n"),
|
fprintf(stderr, _("Migrating git directory of '%s%s' from\n'%s' to\n'%s'\n"),
|
||||||
get_super_prefix_or_empty(), path,
|
get_super_prefix_or_empty(), path,
|
||||||
|
@ -120,6 +120,11 @@ extern int parallel_submodules(void);
|
|||||||
*/
|
*/
|
||||||
int submodule_to_gitdir(struct strbuf *buf, const char *submodule);
|
int submodule_to_gitdir(struct strbuf *buf, const char *submodule);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure that no submodule's git dir is nested in a sibling submodule's.
|
||||||
|
*/
|
||||||
|
int validate_submodule_git_dir(char *git_dir, const char *submodule_name);
|
||||||
|
|
||||||
#define SUBMODULE_MOVE_HEAD_DRY_RUN (1<<0)
|
#define SUBMODULE_MOVE_HEAD_DRY_RUN (1<<0)
|
||||||
#define SUBMODULE_MOVE_HEAD_FORCE (1<<1)
|
#define SUBMODULE_MOVE_HEAD_FORCE (1<<1)
|
||||||
extern int submodule_move_head(const char *path,
|
extern int submodule_move_head(const char *path,
|
||||||
|
@ -106,4 +106,27 @@ test_expect_success MINGW 'prevent git~1 squatting on Windows' '
|
|||||||
! grep gitdir squatting-clone/d/a/git~2
|
! grep gitdir squatting-clone/d/a/git~2
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git dirs of sibling submodules must not be nested' '
|
||||||
|
git init nested &&
|
||||||
|
test_commit -C nested nested &&
|
||||||
|
(
|
||||||
|
cd nested &&
|
||||||
|
cat >.gitmodules <<-EOF &&
|
||||||
|
[submodule "hippo"]
|
||||||
|
url = .
|
||||||
|
path = thing1
|
||||||
|
[submodule "hippo/hooks"]
|
||||||
|
url = .
|
||||||
|
path = thing2
|
||||||
|
EOF
|
||||||
|
git clone . thing1 &&
|
||||||
|
git clone . thing2 &&
|
||||||
|
git add .gitmodules thing1 thing2 &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -m nested
|
||||||
|
) &&
|
||||||
|
test_must_fail git clone --recurse-submodules nested clone 2>err &&
|
||||||
|
test_i18ngrep "is inside git dir" err
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
x
Reference in New Issue
Block a user