Skip to content

Commit ed8b10f

Browse files
committed
fsck: check .gitmodules content
This patch detects and blocks submodule names which do not match the policy set forth in submodule-config. These should already be caught by the submodule code itself, but putting the check here means that newer versions of Git can protect older ones from malicious entries (e.g., a server with receive.fsckObjects will block the objects, protecting clients which fetch from it). As a side effect, this means fsck will also complain about .gitmodules files that cannot be parsed (or were larger than core.bigFileThreshold). Signed-off-by: Jeff King <[email protected]>
1 parent 2738744 commit ed8b10f

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

fsck.c

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include "decorate.h"
1313
#include "oidset.h"
1414
#include "packfile.h"
15+
#include "submodule-config.h"
16+
#include "config.h"
1517

1618
static struct oidset gitmodules_found = OIDSET_INIT;
1719
static struct oidset gitmodules_done = OIDSET_INIT;
@@ -59,6 +61,8 @@ static struct oidset gitmodules_done = OIDSET_INIT;
5961
FUNC(ZERO_PADDED_DATE, ERROR) \
6062
FUNC(GITMODULES_MISSING, ERROR) \
6163
FUNC(GITMODULES_BLOB, ERROR) \
64+
FUNC(GITMODULES_PARSE, ERROR) \
65+
FUNC(GITMODULES_NAME, ERROR) \
6266
/* warnings */ \
6367
FUNC(BAD_FILEMODE, WARN) \
6468
FUNC(EMPTY_NAME, WARN) \
@@ -911,10 +915,64 @@ static int fsck_tag(struct tag *tag, const char *data,
911915
return fsck_tag_buffer(tag, data, size, options);
912916
}
913917

918+
struct fsck_gitmodules_data {
919+
struct object *obj;
920+
struct fsck_options *options;
921+
int ret;
922+
};
923+
924+
static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata)
925+
{
926+
struct fsck_gitmodules_data *data = vdata;
927+
const char *subsection, *key;
928+
int subsection_len;
929+
char *name;
930+
931+
if (parse_config_key(var, "submodule", &subsection, &subsection_len, &key) < 0 ||
932+
!subsection)
933+
return 0;
934+
935+
name = xmemdupz(subsection, subsection_len);
936+
if (check_submodule_name(name) < 0)
937+
data->ret |= report(data->options, data->obj,
938+
FSCK_MSG_GITMODULES_NAME,
939+
"disallowed submodule name: %s",
940+
name);
941+
free(name);
942+
943+
return 0;
944+
}
945+
914946
static int fsck_blob(struct blob *blob, const char *buf,
915947
unsigned long size, struct fsck_options *options)
916948
{
917-
return 0;
949+
struct fsck_gitmodules_data data;
950+
951+
if (!oidset_contains(&gitmodules_found, &blob->object.oid))
952+
return 0;
953+
oidset_insert(&gitmodules_done, &blob->object.oid);
954+
955+
if (!buf) {
956+
/*
957+
* A missing buffer here is a sign that the caller found the
958+
* blob too gigantic to load into memory. Let's just consider
959+
* that an error.
960+
*/
961+
return report(options, &blob->object,
962+
FSCK_MSG_GITMODULES_PARSE,
963+
".gitmodules too large to parse");
964+
}
965+
966+
data.obj = &blob->object;
967+
data.options = options;
968+
data.ret = 0;
969+
if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB,
970+
".gitmodules", buf, size, &data))
971+
data.ret |= report(options, &blob->object,
972+
FSCK_MSG_GITMODULES_PARSE,
973+
"could not parse gitmodules blob");
974+
975+
return data.ret;
918976
}
919977

920978
int fsck_object(struct object *obj, void *data, unsigned long size,

0 commit comments

Comments
 (0)