fsck: warn about symlink pointing inside a gitdir

In the wake of fixing a vulnerability where `git clone` mistakenly
followed a symbolic link that it had just written while checking out
files, writing into a gitdir, let's add some defense-in-depth by
teaching `git fsck` to report symbolic links stored in its trees that
point inside `.git/`.

Even though the Git project never made any promises about the exact
shape of the `.git/` directory's contents, there are likely repositories
out there containing symbolic links that point inside the gitdir. For
that reason, let's only report these as warnings, not as errors.
Security-conscious users are encouraged to configure
`fsck.symlinkPointsToGitDir = error`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin
2024-04-10 18:01:13 +02:00
parent 20f3588efc
commit a33fea0886
4 changed files with 117 additions and 0 deletions

12
fsck.h
View File

@ -63,6 +63,8 @@ enum fsck_msg_type {
FUNC(GITATTRIBUTES_LARGE, ERROR) \
FUNC(GITATTRIBUTES_LINE_LENGTH, ERROR) \
FUNC(GITATTRIBUTES_BLOB, ERROR) \
FUNC(SYMLINK_TARGET_MISSING, ERROR) \
FUNC(SYMLINK_TARGET_BLOB, ERROR) \
/* warnings */ \
FUNC(EMPTY_NAME, WARN) \
FUNC(FULL_PATHNAME, WARN) \
@ -72,6 +74,8 @@ enum fsck_msg_type {
FUNC(NULL_SHA1, WARN) \
FUNC(ZERO_PADDED_FILEMODE, WARN) \
FUNC(NUL_IN_COMMIT, WARN) \
FUNC(SYMLINK_TARGET_LENGTH, WARN) \
FUNC(SYMLINK_POINTS_TO_GIT_DIR, WARN) \
/* infos (reported as warnings, but ignored by default) */ \
FUNC(BAD_FILEMODE, INFO) \
FUNC(GITMODULES_PARSE, INFO) \
@ -139,6 +143,8 @@ struct fsck_options {
struct oidset gitmodules_done;
struct oidset gitattributes_found;
struct oidset gitattributes_done;
struct oidset symlink_targets_found;
struct oidset symlink_targets_done;
kh_oid_map_t *object_names;
};
@ -148,6 +154,8 @@ struct fsck_options {
.gitmodules_done = OIDSET_INIT, \
.gitattributes_found = OIDSET_INIT, \
.gitattributes_done = OIDSET_INIT, \
.symlink_targets_found = OIDSET_INIT, \
.symlink_targets_done = OIDSET_INIT, \
.error_func = fsck_error_function \
}
#define FSCK_OPTIONS_STRICT { \
@ -156,6 +164,8 @@ struct fsck_options {
.gitmodules_done = OIDSET_INIT, \
.gitattributes_found = OIDSET_INIT, \
.gitattributes_done = OIDSET_INIT, \
.symlink_targets_found = OIDSET_INIT, \
.symlink_targets_done = OIDSET_INIT, \
.error_func = fsck_error_function, \
}
#define FSCK_OPTIONS_MISSING_GITMODULES { \
@ -164,6 +174,8 @@ struct fsck_options {
.gitmodules_done = OIDSET_INIT, \
.gitattributes_found = OIDSET_INIT, \
.gitattributes_done = OIDSET_INIT, \
.symlink_targets_found = OIDSET_INIT, \
.symlink_targets_done = OIDSET_INIT, \
.error_func = fsck_error_cb_print_missing_gitmodules, \
}