|
|
c5f736 |
From 73b65b02d5d1aa4612bb7015f80c8cd1b5e828cd Mon Sep 17 00:00:00 2001
|
|
|
c5f736 |
From: Petr Stodulka <pstodulk@redhat.com>
|
|
|
c5f736 |
Date: Fri, 18 Mar 2016 17:14:32 +0100
|
|
|
c5f736 |
Subject: [PATCH] Fix CVE-2016-2315 CVE-2016-2324
|
|
|
c5f736 |
|
|
|
c5f736 |
- added upstream macros for detecting size_t overflow (much more just
|
|
|
c5f736 |
for easier related changes in future, if we want to do some yet)
|
|
|
c5f736 |
- upstream solution removes function path_name() and modify all related
|
|
|
c5f736 |
part of code to replace this function. However, it's too hard for
|
|
|
c5f736 |
backport to such old version of git without unchanged behaviour,
|
|
|
c5f736 |
so application just die with error message instead.
|
|
|
c5f736 |
---
|
|
|
c5f736 |
diff.h | 4 ++--
|
|
|
c5f736 |
git-compat-util.h | 35 +++++++++++++++++++++++++++++++++++
|
|
|
c5f736 |
revision.c | 13 ++++++++++---
|
|
|
c5f736 |
3 files changed, 47 insertions(+), 5 deletions(-)
|
|
|
c5f736 |
|
|
|
c5f736 |
diff --git a/diff.h b/diff.h
|
|
|
c5f736 |
index ce123fa..88db230 100644
|
|
|
c5f736 |
--- a/diff.h
|
|
|
c5f736 |
+++ b/diff.h
|
|
|
c5f736 |
@@ -209,8 +209,8 @@ struct combine_diff_path {
|
|
|
c5f736 |
} parent[FLEX_ARRAY];
|
|
|
c5f736 |
};
|
|
|
c5f736 |
#define combine_diff_path_size(n, l) \
|
|
|
c5f736 |
- (sizeof(struct combine_diff_path) + \
|
|
|
c5f736 |
- sizeof(struct combine_diff_parent) * (n) + (l) + 1)
|
|
|
c5f736 |
+ st_add4(sizeof(struct combine_diff_path), (l), 1, \
|
|
|
c5f736 |
+ st_mult(sizeof(struct combine_diff_parent), (n)))
|
|
|
c5f736 |
|
|
|
c5f736 |
extern void show_combined_diff(struct combine_diff_path *elem, int num_parent,
|
|
|
c5f736 |
int dense, struct rev_info *);
|
|
|
c5f736 |
diff --git a/git-compat-util.h b/git-compat-util.h
|
|
|
c5f736 |
index d493a8c..d5a15fa 100644
|
|
|
c5f736 |
--- a/git-compat-util.h
|
|
|
c5f736 |
+++ b/git-compat-util.h
|
|
|
c5f736 |
@@ -46,6 +46,14 @@
|
|
|
c5f736 |
#define unsigned_add_overflows(a, b) \
|
|
|
c5f736 |
((b) > maximum_unsigned_value_of_type(a) - (a))
|
|
|
c5f736 |
|
|
|
c5f736 |
+/*
|
|
|
c5f736 |
+ * Returns true if the multiplication of "a" and "b" will
|
|
|
c5f736 |
+ * overflow. The types of "a" and "b" must match and must be unsigned.
|
|
|
c5f736 |
+ * Note that this macro evaluates "a" twice!
|
|
|
c5f736 |
+ */
|
|
|
c5f736 |
+#define unsigned_mult_overflows(a, b) \
|
|
|
c5f736 |
+ ((a) && (b) > maximum_unsigned_value_of_type(a) / (a))
|
|
|
c5f736 |
+
|
|
|
c5f736 |
#ifdef __GNUC__
|
|
|
c5f736 |
#define TYPEOF(x) (__typeof__(x))
|
|
|
c5f736 |
#else
|
|
|
c5f736 |
@@ -526,6 +534,33 @@ extern void release_pack_memory(size_t);
|
|
|
c5f736 |
typedef void (*try_to_free_t)(size_t);
|
|
|
c5f736 |
extern try_to_free_t set_try_to_free_routine(try_to_free_t);
|
|
|
c5f736 |
|
|
|
c5f736 |
+static inline size_t st_add(size_t a, size_t b)
|
|
|
c5f736 |
+{
|
|
|
c5f736 |
+ if (unsigned_add_overflows(a, b))
|
|
|
c5f736 |
+ die("size_t overflow: %"PRIuMAX" + %"PRIuMAX,
|
|
|
c5f736 |
+ (uintmax_t)a, (uintmax_t)b);
|
|
|
c5f736 |
+ return a + b;
|
|
|
c5f736 |
+}
|
|
|
c5f736 |
+#define st_add3(a,b,c) st_add((a),st_add((b),(c)))
|
|
|
c5f736 |
+#define st_add4(a,b,c,d) st_add((a),st_add3((b),(c),(d)))
|
|
|
c5f736 |
+
|
|
|
c5f736 |
+static inline size_t st_mult(size_t a, size_t b)
|
|
|
c5f736 |
+{
|
|
|
c5f736 |
+ if (unsigned_mult_overflows(a, b))
|
|
|
c5f736 |
+ die("size_t overflow: %"PRIuMAX" * %"PRIuMAX,
|
|
|
c5f736 |
+ (uintmax_t)a, (uintmax_t)b);
|
|
|
c5f736 |
+ return a * b;
|
|
|
c5f736 |
+}
|
|
|
c5f736 |
+
|
|
|
c5f736 |
+static inline size_t st_sub(size_t a, size_t b)
|
|
|
c5f736 |
+{
|
|
|
c5f736 |
+ if (a < b)
|
|
|
c5f736 |
+ die("size_t underflow: %"PRIuMAX" - %"PRIuMAX,
|
|
|
c5f736 |
+ (uintmax_t)a, (uintmax_t)b);
|
|
|
c5f736 |
+ return a - b;
|
|
|
c5f736 |
+}
|
|
|
c5f736 |
+
|
|
|
c5f736 |
+
|
|
|
c5f736 |
extern char *xstrdup(const char *str);
|
|
|
c5f736 |
extern void *xmalloc(size_t size);
|
|
|
c5f736 |
extern void *xmallocz(size_t size);
|
|
|
c5f736 |
diff --git a/revision.c b/revision.c
|
|
|
c5f736 |
index f40ccf1..b897ca6 100644
|
|
|
c5f736 |
--- a/revision.c
|
|
|
c5f736 |
+++ b/revision.c
|
|
|
c5f736 |
@@ -24,16 +24,21 @@ char *path_name(const struct name_path *path, const char *name)
|
|
|
c5f736 |
{
|
|
|
c5f736 |
const struct name_path *p;
|
|
|
c5f736 |
char *n, *m;
|
|
|
c5f736 |
- int nlen = strlen(name);
|
|
|
c5f736 |
- int len = nlen + 1;
|
|
|
c5f736 |
+ size_t nlen = strlen(name);
|
|
|
c5f736 |
+ size_t len = st_add(nlen, 1);
|
|
|
c5f736 |
+
|
|
|
c5f736 |
+ if(len >= INT_MAX)
|
|
|
c5f736 |
+ die("path_name(): path is too long.");
|
|
|
c5f736 |
|
|
|
c5f736 |
for (p = path; p; p = p->up) {
|
|
|
c5f736 |
if (p->elem_len)
|
|
|
c5f736 |
len += p->elem_len + 1;
|
|
|
c5f736 |
+ if(len >= INT_MAX)
|
|
|
c5f736 |
+ die("path_name(): path is too long.");
|
|
|
c5f736 |
}
|
|
|
c5f736 |
n = xmalloc(len);
|
|
|
c5f736 |
m = n + len - (nlen + 1);
|
|
|
c5f736 |
- strcpy(m, name);
|
|
|
c5f736 |
+ memcpy(m, name, nlen + 1);
|
|
|
c5f736 |
for (p = path; p; p = p->up) {
|
|
|
c5f736 |
if (p->elem_len) {
|
|
|
c5f736 |
m -= p->elem_len + 1;
|
|
|
c5f736 |
--
|
|
|
c5f736 |
2.4.3
|
|
|
c5f736 |
|