1*4882a593SmuzhiyunFrom 5775eb40862b67468ced816e6d7560dbe22a3670 Mon Sep 17 00:00:00 2001
2*4882a593SmuzhiyunFrom: Peter Jones <pjones@redhat.com>
3*4882a593SmuzhiyunDate: Mon, 15 Jun 2020 12:15:29 -0400
4*4882a593SmuzhiyunSubject: [PATCH] calloc: Make sure we always have an overflow-checking
5*4882a593Smuzhiyun calloc() available
6*4882a593SmuzhiyunMIME-Version: 1.0
7*4882a593SmuzhiyunContent-Type: text/plain; charset=UTF-8
8*4882a593SmuzhiyunContent-Transfer-Encoding: 8bit
9*4882a593Smuzhiyun
10*4882a593SmuzhiyunThis tries to make sure that everywhere in this source tree, we always have
11*4882a593Smuzhiyunan appropriate version of calloc() (i.e. grub_calloc(), xcalloc(), etc.)
12*4882a593Smuzhiyunavailable, and that they all safely check for overflow and return NULL when
13*4882a593Smuzhiyunit would occur.
14*4882a593Smuzhiyun
15*4882a593SmuzhiyunSigned-off-by: Peter Jones <pjones@redhat.com>
16*4882a593SmuzhiyunReviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
17*4882a593SmuzhiyunSigned-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
18*4882a593Smuzhiyun---
19*4882a593Smuzhiyun grub-core/kern/emu/misc.c          | 12 +++++++++
20*4882a593Smuzhiyun grub-core/kern/emu/mm.c            | 10 ++++++++
21*4882a593Smuzhiyun grub-core/kern/mm.c                | 40 ++++++++++++++++++++++++++++++
22*4882a593Smuzhiyun grub-core/lib/libgcrypt_wrap/mem.c | 11 ++++++--
23*4882a593Smuzhiyun grub-core/lib/posix_wrap/stdlib.h  |  8 +++++-
24*4882a593Smuzhiyun include/grub/emu/misc.h            |  1 +
25*4882a593Smuzhiyun include/grub/mm.h                  |  6 +++++
26*4882a593Smuzhiyun 7 files changed, 85 insertions(+), 3 deletions(-)
27*4882a593Smuzhiyun
28*4882a593Smuzhiyundiff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c
29*4882a593Smuzhiyunindex 65db79baa..dfd8a8ec4 100644
30*4882a593Smuzhiyun--- a/grub-core/kern/emu/misc.c
31*4882a593Smuzhiyun+++ b/grub-core/kern/emu/misc.c
32*4882a593Smuzhiyun@@ -85,6 +85,18 @@ grub_util_error (const char *fmt, ...)
33*4882a593Smuzhiyun   exit (1);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun+void *
37*4882a593Smuzhiyun+xcalloc (grub_size_t nmemb, grub_size_t size)
38*4882a593Smuzhiyun+{
39*4882a593Smuzhiyun+  void *p;
40*4882a593Smuzhiyun+
41*4882a593Smuzhiyun+  p = calloc (nmemb, size);
42*4882a593Smuzhiyun+  if (!p)
43*4882a593Smuzhiyun+    grub_util_error ("%s", _("out of memory"));
44*4882a593Smuzhiyun+
45*4882a593Smuzhiyun+  return p;
46*4882a593Smuzhiyun+}
47*4882a593Smuzhiyun+
48*4882a593Smuzhiyun void *
49*4882a593Smuzhiyun xmalloc (grub_size_t size)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyundiff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c
52*4882a593Smuzhiyunindex f262e95e3..145b01d37 100644
53*4882a593Smuzhiyun--- a/grub-core/kern/emu/mm.c
54*4882a593Smuzhiyun+++ b/grub-core/kern/emu/mm.c
55*4882a593Smuzhiyun@@ -25,6 +25,16 @@
56*4882a593Smuzhiyun #include <string.h>
57*4882a593Smuzhiyun #include <grub/i18n.h>
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun+void *
60*4882a593Smuzhiyun+grub_calloc (grub_size_t nmemb, grub_size_t size)
61*4882a593Smuzhiyun+{
62*4882a593Smuzhiyun+  void *ret;
63*4882a593Smuzhiyun+  ret = calloc (nmemb, size);
64*4882a593Smuzhiyun+  if (!ret)
65*4882a593Smuzhiyun+    grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
66*4882a593Smuzhiyun+  return ret;
67*4882a593Smuzhiyun+}
68*4882a593Smuzhiyun+
69*4882a593Smuzhiyun void *
70*4882a593Smuzhiyun grub_malloc (grub_size_t size)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyundiff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
73*4882a593Smuzhiyunindex ee88ff611..f2822a836 100644
74*4882a593Smuzhiyun--- a/grub-core/kern/mm.c
75*4882a593Smuzhiyun+++ b/grub-core/kern/mm.c
76*4882a593Smuzhiyun@@ -67,8 +67,10 @@
77*4882a593Smuzhiyun #include <grub/dl.h>
78*4882a593Smuzhiyun #include <grub/i18n.h>
79*4882a593Smuzhiyun #include <grub/mm_private.h>
80*4882a593Smuzhiyun+#include <grub/safemath.h>
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun #ifdef MM_DEBUG
83*4882a593Smuzhiyun+# undef grub_calloc
84*4882a593Smuzhiyun # undef grub_malloc
85*4882a593Smuzhiyun # undef grub_zalloc
86*4882a593Smuzhiyun # undef grub_realloc
87*4882a593Smuzhiyun@@ -375,6 +377,30 @@ grub_memalign (grub_size_t align, grub_size_t size)
88*4882a593Smuzhiyun   return 0;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun+/*
92*4882a593Smuzhiyun+ * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on
93*4882a593Smuzhiyun+ * integer overflow.
94*4882a593Smuzhiyun+ */
95*4882a593Smuzhiyun+void *
96*4882a593Smuzhiyun+grub_calloc (grub_size_t nmemb, grub_size_t size)
97*4882a593Smuzhiyun+{
98*4882a593Smuzhiyun+  void *ret;
99*4882a593Smuzhiyun+  grub_size_t sz = 0;
100*4882a593Smuzhiyun+
101*4882a593Smuzhiyun+  if (grub_mul (nmemb, size, &sz))
102*4882a593Smuzhiyun+    {
103*4882a593Smuzhiyun+      grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
104*4882a593Smuzhiyun+      return NULL;
105*4882a593Smuzhiyun+    }
106*4882a593Smuzhiyun+
107*4882a593Smuzhiyun+  ret = grub_memalign (0, sz);
108*4882a593Smuzhiyun+  if (!ret)
109*4882a593Smuzhiyun+    return NULL;
110*4882a593Smuzhiyun+
111*4882a593Smuzhiyun+  grub_memset (ret, 0, sz);
112*4882a593Smuzhiyun+  return ret;
113*4882a593Smuzhiyun+}
114*4882a593Smuzhiyun+
115*4882a593Smuzhiyun /* Allocate SIZE bytes and return the pointer.  */
116*4882a593Smuzhiyun void *
117*4882a593Smuzhiyun grub_malloc (grub_size_t size)
118*4882a593Smuzhiyun@@ -561,6 +587,20 @@ grub_mm_dump (unsigned lineno)
119*4882a593Smuzhiyun   grub_printf ("\n");
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun+void *
123*4882a593Smuzhiyun+grub_debug_calloc (const char *file, int line, grub_size_t nmemb, grub_size_t size)
124*4882a593Smuzhiyun+{
125*4882a593Smuzhiyun+  void *ptr;
126*4882a593Smuzhiyun+
127*4882a593Smuzhiyun+  if (grub_mm_debug)
128*4882a593Smuzhiyun+    grub_printf ("%s:%d: calloc (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE ") = ",
129*4882a593Smuzhiyun+		 file, line, size);
130*4882a593Smuzhiyun+  ptr = grub_calloc (nmemb, size);
131*4882a593Smuzhiyun+  if (grub_mm_debug)
132*4882a593Smuzhiyun+    grub_printf ("%p\n", ptr);
133*4882a593Smuzhiyun+  return ptr;
134*4882a593Smuzhiyun+}
135*4882a593Smuzhiyun+
136*4882a593Smuzhiyun void *
137*4882a593Smuzhiyun grub_debug_malloc (const char *file, int line, grub_size_t size)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyundiff --git a/grub-core/lib/libgcrypt_wrap/mem.c b/grub-core/lib/libgcrypt_wrap/mem.c
140*4882a593Smuzhiyunindex beeb661a3..74c6eafe5 100644
141*4882a593Smuzhiyun--- a/grub-core/lib/libgcrypt_wrap/mem.c
142*4882a593Smuzhiyun+++ b/grub-core/lib/libgcrypt_wrap/mem.c
143*4882a593Smuzhiyun@@ -4,6 +4,7 @@
144*4882a593Smuzhiyun #include <grub/crypto.h>
145*4882a593Smuzhiyun #include <grub/dl.h>
146*4882a593Smuzhiyun #include <grub/env.h>
147*4882a593Smuzhiyun+#include <grub/safemath.h>
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun GRUB_MOD_LICENSE ("GPLv3+");
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun@@ -36,7 +37,10 @@ void *
152*4882a593Smuzhiyun gcry_xcalloc (size_t n, size_t m)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun   void *ret;
155*4882a593Smuzhiyun-  ret = grub_zalloc (n * m);
156*4882a593Smuzhiyun+  size_t sz;
157*4882a593Smuzhiyun+  if (grub_mul (n, m, &sz))
158*4882a593Smuzhiyun+    grub_fatal ("gcry_xcalloc would overflow");
159*4882a593Smuzhiyun+  ret = grub_zalloc (sz);
160*4882a593Smuzhiyun   if (!ret)
161*4882a593Smuzhiyun     grub_fatal ("gcry_xcalloc failed");
162*4882a593Smuzhiyun   return ret;
163*4882a593Smuzhiyun@@ -56,7 +60,10 @@ void *
164*4882a593Smuzhiyun gcry_xcalloc_secure (size_t n, size_t m)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun   void *ret;
167*4882a593Smuzhiyun-  ret = grub_zalloc (n * m);
168*4882a593Smuzhiyun+  size_t sz;
169*4882a593Smuzhiyun+  if (grub_mul (n, m, &sz))
170*4882a593Smuzhiyun+    grub_fatal ("gcry_xcalloc would overflow");
171*4882a593Smuzhiyun+  ret = grub_zalloc (sz);
172*4882a593Smuzhiyun   if (!ret)
173*4882a593Smuzhiyun     grub_fatal ("gcry_xcalloc failed");
174*4882a593Smuzhiyun   return ret;
175*4882a593Smuzhiyundiff --git a/grub-core/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h
176*4882a593Smuzhiyunindex 3b46f47ff..7a8d385e9 100644
177*4882a593Smuzhiyun--- a/grub-core/lib/posix_wrap/stdlib.h
178*4882a593Smuzhiyun+++ b/grub-core/lib/posix_wrap/stdlib.h
179*4882a593Smuzhiyun@@ -21,6 +21,7 @@
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun #include <grub/mm.h>
182*4882a593Smuzhiyun #include <grub/misc.h>
183*4882a593Smuzhiyun+#include <grub/safemath.h>
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun static inline void
186*4882a593Smuzhiyun free (void *ptr)
187*4882a593Smuzhiyun@@ -37,7 +38,12 @@ malloc (grub_size_t size)
188*4882a593Smuzhiyun static inline void *
189*4882a593Smuzhiyun calloc (grub_size_t size, grub_size_t nelem)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun-  return grub_zalloc (size * nelem);
192*4882a593Smuzhiyun+  grub_size_t sz;
193*4882a593Smuzhiyun+
194*4882a593Smuzhiyun+  if (grub_mul (size, nelem, &sz))
195*4882a593Smuzhiyun+    return NULL;
196*4882a593Smuzhiyun+
197*4882a593Smuzhiyun+  return grub_zalloc (sz);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun static inline void *
201*4882a593Smuzhiyundiff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h
202*4882a593Smuzhiyunindex ce464cfd0..ff9c48a64 100644
203*4882a593Smuzhiyun--- a/include/grub/emu/misc.h
204*4882a593Smuzhiyun+++ b/include/grub/emu/misc.h
205*4882a593Smuzhiyun@@ -47,6 +47,7 @@ grub_util_device_is_mapped (const char *dev);
206*4882a593Smuzhiyun #define GRUB_HOST_PRIuLONG_LONG "llu"
207*4882a593Smuzhiyun #define GRUB_HOST_PRIxLONG_LONG "llx"
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun+void * EXPORT_FUNC(xcalloc) (grub_size_t nmemb, grub_size_t size) WARN_UNUSED_RESULT;
210*4882a593Smuzhiyun void * EXPORT_FUNC(xmalloc) (grub_size_t size) WARN_UNUSED_RESULT;
211*4882a593Smuzhiyun void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) WARN_UNUSED_RESULT;
212*4882a593Smuzhiyun char * EXPORT_FUNC(xstrdup) (const char *str) WARN_UNUSED_RESULT;
213*4882a593Smuzhiyundiff --git a/include/grub/mm.h b/include/grub/mm.h
214*4882a593Smuzhiyunindex 28e2e53eb..9c38dd3ca 100644
215*4882a593Smuzhiyun--- a/include/grub/mm.h
216*4882a593Smuzhiyun+++ b/include/grub/mm.h
217*4882a593Smuzhiyun@@ -29,6 +29,7 @@
218*4882a593Smuzhiyun #endif
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun void grub_mm_init_region (void *addr, grub_size_t size);
221*4882a593Smuzhiyun+void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
222*4882a593Smuzhiyun void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
223*4882a593Smuzhiyun void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
224*4882a593Smuzhiyun void EXPORT_FUNC(grub_free) (void *ptr);
225*4882a593Smuzhiyun@@ -48,6 +49,9 @@ extern int EXPORT_VAR(grub_mm_debug);
226*4882a593Smuzhiyun void grub_mm_dump_free (void);
227*4882a593Smuzhiyun void grub_mm_dump (unsigned lineno);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun+#define grub_calloc(nmemb, size)	\
230*4882a593Smuzhiyun+  grub_debug_calloc (GRUB_FILE, __LINE__, nmemb, size)
231*4882a593Smuzhiyun+
232*4882a593Smuzhiyun #define grub_malloc(size)	\
233*4882a593Smuzhiyun   grub_debug_malloc (GRUB_FILE, __LINE__, size)
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun@@ -63,6 +67,8 @@ void grub_mm_dump (unsigned lineno);
236*4882a593Smuzhiyun #define grub_free(ptr)	\
237*4882a593Smuzhiyun   grub_debug_free (GRUB_FILE, __LINE__, ptr)
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun+void *EXPORT_FUNC(grub_debug_calloc) (const char *file, int line,
240*4882a593Smuzhiyun+				      grub_size_t nmemb, grub_size_t size);
241*4882a593Smuzhiyun void *EXPORT_FUNC(grub_debug_malloc) (const char *file, int line,
242*4882a593Smuzhiyun 				      grub_size_t size);
243*4882a593Smuzhiyun void *EXPORT_FUNC(grub_debug_zalloc) (const char *file, int line,
244*4882a593Smuzhiyun--
245*4882a593Smuzhiyun2.26.2
246*4882a593Smuzhiyun
247