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