Hi, attached is a patch for an NMU to fix this. It is also archived on: http://people.debian.org/~nion/nmu-diff/git-core-1.5.6.3-1_1.5.6.3-1.1.patch
Cheers Nico -- Nico Golde - http://www.ngolde.de - [EMAIL PROTECTED] - GPG: 0x73647CFF For security reasons, all text in this mail is double-rot13 encrypted.
diff -u git-core-1.5.6.3/debian/changelog git-core-1.5.6.3/debian/changelog --- git-core-1.5.6.3/debian/changelog +++ git-core-1.5.6.3/debian/changelog @@ -1,3 +1,13 @@ +git-core (1:1.5.6.3-1.1) unstable; urgency=high + + * Non-maintainer upload by the Security Team. + * Fix various stack-based buffer overflows when processing overly long + repository pathnames which can be exploited to execute arbitrary code if + a victim is tricked into using git-grep or git-diff on a crafted + repository (CVE-2008-3546; Closes: #494097). + + -- Nico Golde <[EMAIL PROTECTED]> Sat, 09 Aug 2008 13:53:13 +0200 + git-core (1:1.5.6.3-1) unstable; urgency=low * new upstream point release. only in patch2: unchanged: --- git-core-1.5.6.3.orig/debian/diff/0005-bug-494097-CVE-2008-3546.diff +++ git-core-1.5.6.3/debian/diff/0005-bug-494097-CVE-2008-3546.diff @@ -0,0 +1,234 @@ +From: Dmitry Potapov <[EMAIL PROTECTED]> +Date: Wed, 16 Jul 2008 14:54:02 +0000 (+0400) +Subject: Fix buffer overflow in git diff +X-Git-Tag: v1.5.6.4~16 +X-Git-Url: http://git.kernel.org/?p=git%2Fgit.git;a=commitdiff_plain;h=fd55a19eb1d49ae54008d932a65f79cd6fda45c9 + +Fix buffer overflow in git diff + +If PATH_MAX on your system is smaller than a path stored, it may cause +buffer overflow and stack corruption in diff_addremove() and diff_change() +functions when running git-diff + +Signed-off-by: Dmitry Potapov <[EMAIL PROTECTED]> +Signed-off-by: Junio C Hamano <[EMAIL PROTECTED]> +--- + +diff --git a/diff-lib.c b/diff-lib.c +index b17722d..e7eaff9 100644 +--- a/diff-lib.c ++++ b/diff-lib.c +@@ -171,7 +171,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) + if (silent_on_removed) + continue; + diff_addremove(&revs->diffopt, '-', ce->ce_mode, +- ce->sha1, ce->name, NULL); ++ ce->sha1, ce->name); + continue; + } + changed = ce_match_stat(ce, &st, ce_option); +@@ -184,7 +184,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option) + newmode = ce_mode_from_stat(ce, st.st_mode); + diff_change(&revs->diffopt, oldmode, newmode, + ce->sha1, (changed ? null_sha1 : ce->sha1), +- ce->name, NULL); ++ ce->name); + + } + diffcore_std(&revs->diffopt); +@@ -208,7 +208,7 @@ static void diff_index_show_file(struct rev_info *revs, + const unsigned char *sha1, unsigned int mode) + { + diff_addremove(&revs->diffopt, prefix[0], mode, +- sha1, ce->name, NULL); ++ sha1, ce->name); + } + + static int get_stat_data(struct cache_entry *ce, +@@ -312,7 +312,7 @@ static int show_modified(struct oneway_unpack_data *cbdata, + return 0; + + diff_change(&revs->diffopt, oldmode, mode, +- old->sha1, sha1, old->name, NULL); ++ old->sha1, sha1, old->name); + return 0; + } + +diff --git a/diff.c b/diff.c +index 78c4d3a..386de82 100644 +--- a/diff.c ++++ b/diff.c +@@ -3356,9 +3356,8 @@ int diff_result_code(struct diff_options *opt, int status) + void diff_addremove(struct diff_options *options, + int addremove, unsigned mode, + const unsigned char *sha1, +- const char *base, const char *path) ++ const char *concatpath) + { +- char concatpath[PATH_MAX]; + struct diff_filespec *one, *two; + + if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode)) +@@ -3380,9 +3379,6 @@ void diff_addremove(struct diff_options *options, + addremove = (addremove == '+' ? '-' : + addremove == '-' ? '+' : addremove); + +- if (!path) path = ""; +- sprintf(concatpath, "%s%s", base, path); +- + if (options->prefix && + strncmp(concatpath, options->prefix, options->prefix_length)) + return; +@@ -3403,9 +3399,8 @@ void diff_change(struct diff_options *options, + unsigned old_mode, unsigned new_mode, + const unsigned char *old_sha1, + const unsigned char *new_sha1, +- const char *base, const char *path) ++ const char *concatpath) + { +- char concatpath[PATH_MAX]; + struct diff_filespec *one, *two; + + if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode) +@@ -3418,8 +3413,6 @@ void diff_change(struct diff_options *options, + tmp = old_mode; old_mode = new_mode; new_mode = tmp; + tmp_c = old_sha1; old_sha1 = new_sha1; new_sha1 = tmp_c; + } +- if (!path) path = ""; +- sprintf(concatpath, "%s%s", base, path); + + if (options->prefix && + strncmp(concatpath, options->prefix, options->prefix_length)) +diff --git a/diff.h b/diff.h +index 5dc0cb5..50fb5dd 100644 +--- a/diff.h ++++ b/diff.h +@@ -14,12 +14,12 @@ typedef void (*change_fn_t)(struct diff_options *options, + unsigned old_mode, unsigned new_mode, + const unsigned char *old_sha1, + const unsigned char *new_sha1, +- const char *base, const char *path); ++ const char *fullpath); + + typedef void (*add_remove_fn_t)(struct diff_options *options, + int addremove, unsigned mode, + const unsigned char *sha1, +- const char *base, const char *path); ++ const char *fullpath); + + typedef void (*diff_format_fn_t)(struct diff_queue_struct *q, + struct diff_options *options, void *data); +@@ -164,14 +164,13 @@ extern void diff_addremove(struct diff_options *, + int addremove, + unsigned mode, + const unsigned char *sha1, +- const char *base, +- const char *path); ++ const char *fullpath); + + extern void diff_change(struct diff_options *, + unsigned mode1, unsigned mode2, + const unsigned char *sha1, + const unsigned char *sha2, +- const char *base, const char *path); ++ const char *fullpath); + + extern void diff_unmerge(struct diff_options *, + const char *path, +diff --git a/revision.c b/revision.c +index fc66755..8dc3ca7 100644 +--- a/revision.c ++++ b/revision.c +@@ -259,7 +259,7 @@ static int tree_difference = REV_TREE_SAME; + static void file_add_remove(struct diff_options *options, + int addremove, unsigned mode, + const unsigned char *sha1, +- const char *base, const char *path) ++ const char *fullpath) + { + int diff = REV_TREE_DIFFERENT; + +@@ -285,7 +285,7 @@ static void file_change(struct diff_options *options, + unsigned old_mode, unsigned new_mode, + const unsigned char *old_sha1, + const unsigned char *new_sha1, +- const char *base, const char *path) ++ const char *fullpath) + { + tree_difference = REV_TREE_DIFFERENT; + DIFF_OPT_SET(options, HAS_CHANGES); +diff --git a/tree-diff.c b/tree-diff.c +index e1e2e6c..bbb126f 100644 +--- a/tree-diff.c ++++ b/tree-diff.c +@@ -15,6 +15,15 @@ static char *malloc_base(const char *base, int baselen, const char *path, int pa + return newbase; + } + ++static char *malloc_fullname(const char *base, int baselen, const char *path, int pathlen) ++{ ++ char *fullname = xmalloc(baselen + pathlen + 1); ++ memcpy(fullname, base, baselen); ++ memcpy(fullname + baselen, path, pathlen); ++ fullname[baselen + pathlen] = 0; ++ return fullname; ++} ++ + static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, + const char *base, int baselen); + +@@ -24,6 +33,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const + const char *path1, *path2; + const unsigned char *sha1, *sha2; + int cmp, pathlen1, pathlen2; ++ char *fullname; + + sha1 = tree_entry_extract(t1, &path1, &mode1); + sha2 = tree_entry_extract(t2, &path2, &mode2); +@@ -55,15 +65,20 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const + if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) { + int retval; + char *newbase = malloc_base(base, baselen, path1, pathlen1); +- if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) ++ if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) { ++ newbase[baselen + pathlen1] = 0; + opt->change(opt, mode1, mode2, +- sha1, sha2, base, path1); ++ sha1, sha2, newbase); ++ newbase[baselen + pathlen1] = '/'; ++ } + retval = diff_tree_sha1(sha1, sha2, newbase, opt); + free(newbase); + return retval; + } + +- opt->change(opt, mode1, mode2, sha1, sha2, base, path1); ++ fullname = malloc_fullname(base, baselen, path1, pathlen1); ++ opt->change(opt, mode1, mode2, sha1, sha2, fullname); ++ free(fullname); + return 0; + } + +@@ -205,10 +220,10 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree + unsigned mode; + const char *path; + const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode); ++ int pathlen = tree_entry_len(path, sha1); + + if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) { + enum object_type type; +- int pathlen = tree_entry_len(path, sha1); + char *newbase = malloc_base(base, baselen, path, pathlen); + struct tree_desc inner; + void *tree; +@@ -224,7 +239,9 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree + free(tree); + free(newbase); + } else { +- opt->add_remove(opt, prefix[0], mode, sha1, base, path); ++ char *fullname = malloc_fullname(base, baselen, path, pathlen); ++ opt->add_remove(opt, prefix[0], mode, sha1, fullname); ++ free(fullname); + } + } +
pgpkTu2eDTtWE.pgp
Description: PGP signature