Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools: bpf: make use of reallocarray

reallocarray() is a safer variant of realloc which checks for
multiplication overflow in case of array allocation. Since it's
not available in Glibc < 2.26 import kernel's overflow.h and
add a static inline implementation when needed. Use feature
detection to probe for existence of reallocarray.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: Jiong Wang <jiong.wang@netronome.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

authored by

Jakub Kicinski and committed by
Daniel Borkmann
531b014e 8d13406c

+334 -9
+5 -1
tools/bpf/bpftool/Makefile
··· 52 52 RM ?= rm -f 53 53 54 54 FEATURE_USER = .bpftool 55 - FEATURE_TESTS = libbfd disassembler-four-args 55 + FEATURE_TESTS = libbfd disassembler-four-args reallocarray 56 56 FEATURE_DISPLAY = libbfd disassembler-four-args 57 57 58 58 check_feat := 1 ··· 73 73 74 74 ifeq ($(feature-disassembler-four-args), 1) 75 75 CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE 76 + endif 77 + 78 + ifeq ($(feature-reallocarray), 0) 79 + CFLAGS += -DCOMPAT_NEED_REALLOCARRAY 76 80 endif 77 81 78 82 include $(wildcard $(OUTPUT)*.d)
+1
tools/bpf/bpftool/main.h
··· 42 42 #include <linux/compiler.h> 43 43 #include <linux/kernel.h> 44 44 #include <linux/hashtable.h> 45 + #include <tools/libc_compat.h> 45 46 46 47 #include "json_writer.h" 47 48
+3 -3
tools/bpf/bpftool/xlated_dumper.c
··· 35 35 * POSSIBILITY OF SUCH DAMAGE. 36 36 */ 37 37 38 + #define _GNU_SOURCE 38 39 #include <stdarg.h> 39 40 #include <stdio.h> 40 41 #include <stdlib.h> ··· 67 66 while (!feof(fp)) { 68 67 if (!fgets(buff, sizeof(buff), fp)) 69 68 break; 70 - tmp = realloc(dd->sym_mapping, 71 - (dd->sym_count + 1) * 72 - sizeof(*dd->sym_mapping)); 69 + tmp = reallocarray(dd->sym_mapping, dd->sym_count + 1, 70 + sizeof(*dd->sym_mapping)); 73 71 if (!tmp) { 74 72 out: 75 73 free(dd->sym_mapping);
+4
tools/build/feature/Makefile
··· 14 14 test-libaudit.bin \ 15 15 test-libbfd.bin \ 16 16 test-disassembler-four-args.bin \ 17 + test-reallocarray.bin \ 17 18 test-liberty.bin \ 18 19 test-liberty-z.bin \ 19 20 test-cplus-demangle.bin \ ··· 204 203 205 204 $(OUTPUT)test-disassembler-four-args.bin: 206 205 $(BUILD) -DPACKAGE='"perf"' -lbfd -lopcodes 206 + 207 + $(OUTPUT)test-reallocarray.bin: 208 + $(BUILD) 207 209 208 210 $(OUTPUT)test-liberty.bin: 209 211 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty
+8
tools/build/feature/test-reallocarray.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #define _GNU_SOURCE 3 + #include <stdlib.h> 4 + 5 + int main(void) 6 + { 7 + return !!reallocarray(NULL, 1, 1); 8 + }
+4
tools/include/linux/compiler-gcc.h
··· 36 36 #endif 37 37 #define __printf(a, b) __attribute__((format(printf, a, b))) 38 38 #define __scanf(a, b) __attribute__((format(scanf, a, b))) 39 + 40 + #if GCC_VERSION >= 50100 41 + #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 42 + #endif
+278
tools/include/linux/overflow.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR MIT */ 2 + #ifndef __LINUX_OVERFLOW_H 3 + #define __LINUX_OVERFLOW_H 4 + 5 + #include <linux/compiler.h> 6 + 7 + /* 8 + * In the fallback code below, we need to compute the minimum and 9 + * maximum values representable in a given type. These macros may also 10 + * be useful elsewhere, so we provide them outside the 11 + * COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW block. 12 + * 13 + * It would seem more obvious to do something like 14 + * 15 + * #define type_min(T) (T)(is_signed_type(T) ? (T)1 << (8*sizeof(T)-1) : 0) 16 + * #define type_max(T) (T)(is_signed_type(T) ? ((T)1 << (8*sizeof(T)-1)) - 1 : ~(T)0) 17 + * 18 + * Unfortunately, the middle expressions, strictly speaking, have 19 + * undefined behaviour, and at least some versions of gcc warn about 20 + * the type_max expression (but not if -fsanitize=undefined is in 21 + * effect; in that case, the warning is deferred to runtime...). 22 + * 23 + * The slightly excessive casting in type_min is to make sure the 24 + * macros also produce sensible values for the exotic type _Bool. [The 25 + * overflow checkers only almost work for _Bool, but that's 26 + * a-feature-not-a-bug, since people shouldn't be doing arithmetic on 27 + * _Bools. Besides, the gcc builtins don't allow _Bool* as third 28 + * argument.] 29 + * 30 + * Idea stolen from 31 + * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html - 32 + * credit to Christian Biere. 33 + */ 34 + #define is_signed_type(type) (((type)(-1)) < (type)1) 35 + #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type))) 36 + #define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T))) 37 + #define type_min(T) ((T)((T)-type_max(T)-(T)1)) 38 + 39 + 40 + #ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 41 + /* 42 + * For simplicity and code hygiene, the fallback code below insists on 43 + * a, b and *d having the same type (similar to the min() and max() 44 + * macros), whereas gcc's type-generic overflow checkers accept 45 + * different types. Hence we don't just make check_add_overflow an 46 + * alias for __builtin_add_overflow, but add type checks similar to 47 + * below. 48 + */ 49 + #define check_add_overflow(a, b, d) ({ \ 50 + typeof(a) __a = (a); \ 51 + typeof(b) __b = (b); \ 52 + typeof(d) __d = (d); \ 53 + (void) (&__a == &__b); \ 54 + (void) (&__a == __d); \ 55 + __builtin_add_overflow(__a, __b, __d); \ 56 + }) 57 + 58 + #define check_sub_overflow(a, b, d) ({ \ 59 + typeof(a) __a = (a); \ 60 + typeof(b) __b = (b); \ 61 + typeof(d) __d = (d); \ 62 + (void) (&__a == &__b); \ 63 + (void) (&__a == __d); \ 64 + __builtin_sub_overflow(__a, __b, __d); \ 65 + }) 66 + 67 + #define check_mul_overflow(a, b, d) ({ \ 68 + typeof(a) __a = (a); \ 69 + typeof(b) __b = (b); \ 70 + typeof(d) __d = (d); \ 71 + (void) (&__a == &__b); \ 72 + (void) (&__a == __d); \ 73 + __builtin_mul_overflow(__a, __b, __d); \ 74 + }) 75 + 76 + #else 77 + 78 + 79 + /* Checking for unsigned overflow is relatively easy without causing UB. */ 80 + #define __unsigned_add_overflow(a, b, d) ({ \ 81 + typeof(a) __a = (a); \ 82 + typeof(b) __b = (b); \ 83 + typeof(d) __d = (d); \ 84 + (void) (&__a == &__b); \ 85 + (void) (&__a == __d); \ 86 + *__d = __a + __b; \ 87 + *__d < __a; \ 88 + }) 89 + #define __unsigned_sub_overflow(a, b, d) ({ \ 90 + typeof(a) __a = (a); \ 91 + typeof(b) __b = (b); \ 92 + typeof(d) __d = (d); \ 93 + (void) (&__a == &__b); \ 94 + (void) (&__a == __d); \ 95 + *__d = __a - __b; \ 96 + __a < __b; \ 97 + }) 98 + /* 99 + * If one of a or b is a compile-time constant, this avoids a division. 100 + */ 101 + #define __unsigned_mul_overflow(a, b, d) ({ \ 102 + typeof(a) __a = (a); \ 103 + typeof(b) __b = (b); \ 104 + typeof(d) __d = (d); \ 105 + (void) (&__a == &__b); \ 106 + (void) (&__a == __d); \ 107 + *__d = __a * __b; \ 108 + __builtin_constant_p(__b) ? \ 109 + __b > 0 && __a > type_max(typeof(__a)) / __b : \ 110 + __a > 0 && __b > type_max(typeof(__b)) / __a; \ 111 + }) 112 + 113 + /* 114 + * For signed types, detecting overflow is much harder, especially if 115 + * we want to avoid UB. But the interface of these macros is such that 116 + * we must provide a result in *d, and in fact we must produce the 117 + * result promised by gcc's builtins, which is simply the possibly 118 + * wrapped-around value. Fortunately, we can just formally do the 119 + * operations in the widest relevant unsigned type (u64) and then 120 + * truncate the result - gcc is smart enough to generate the same code 121 + * with and without the (u64) casts. 122 + */ 123 + 124 + /* 125 + * Adding two signed integers can overflow only if they have the same 126 + * sign, and overflow has happened iff the result has the opposite 127 + * sign. 128 + */ 129 + #define __signed_add_overflow(a, b, d) ({ \ 130 + typeof(a) __a = (a); \ 131 + typeof(b) __b = (b); \ 132 + typeof(d) __d = (d); \ 133 + (void) (&__a == &__b); \ 134 + (void) (&__a == __d); \ 135 + *__d = (u64)__a + (u64)__b; \ 136 + (((~(__a ^ __b)) & (*__d ^ __a)) \ 137 + & type_min(typeof(__a))) != 0; \ 138 + }) 139 + 140 + /* 141 + * Subtraction is similar, except that overflow can now happen only 142 + * when the signs are opposite. In this case, overflow has happened if 143 + * the result has the opposite sign of a. 144 + */ 145 + #define __signed_sub_overflow(a, b, d) ({ \ 146 + typeof(a) __a = (a); \ 147 + typeof(b) __b = (b); \ 148 + typeof(d) __d = (d); \ 149 + (void) (&__a == &__b); \ 150 + (void) (&__a == __d); \ 151 + *__d = (u64)__a - (u64)__b; \ 152 + ((((__a ^ __b)) & (*__d ^ __a)) \ 153 + & type_min(typeof(__a))) != 0; \ 154 + }) 155 + 156 + /* 157 + * Signed multiplication is rather hard. gcc always follows C99, so 158 + * division is truncated towards 0. This means that we can write the 159 + * overflow check like this: 160 + * 161 + * (a > 0 && (b > MAX/a || b < MIN/a)) || 162 + * (a < -1 && (b > MIN/a || b < MAX/a) || 163 + * (a == -1 && b == MIN) 164 + * 165 + * The redundant casts of -1 are to silence an annoying -Wtype-limits 166 + * (included in -Wextra) warning: When the type is u8 or u16, the 167 + * __b_c_e in check_mul_overflow obviously selects 168 + * __unsigned_mul_overflow, but unfortunately gcc still parses this 169 + * code and warns about the limited range of __b. 170 + */ 171 + 172 + #define __signed_mul_overflow(a, b, d) ({ \ 173 + typeof(a) __a = (a); \ 174 + typeof(b) __b = (b); \ 175 + typeof(d) __d = (d); \ 176 + typeof(a) __tmax = type_max(typeof(a)); \ 177 + typeof(a) __tmin = type_min(typeof(a)); \ 178 + (void) (&__a == &__b); \ 179 + (void) (&__a == __d); \ 180 + *__d = (u64)__a * (u64)__b; \ 181 + (__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) || \ 182 + (__b < (typeof(__b))-1 && (__a > __tmin/__b || __a < __tmax/__b)) || \ 183 + (__b == (typeof(__b))-1 && __a == __tmin); \ 184 + }) 185 + 186 + 187 + #define check_add_overflow(a, b, d) \ 188 + __builtin_choose_expr(is_signed_type(typeof(a)), \ 189 + __signed_add_overflow(a, b, d), \ 190 + __unsigned_add_overflow(a, b, d)) 191 + 192 + #define check_sub_overflow(a, b, d) \ 193 + __builtin_choose_expr(is_signed_type(typeof(a)), \ 194 + __signed_sub_overflow(a, b, d), \ 195 + __unsigned_sub_overflow(a, b, d)) 196 + 197 + #define check_mul_overflow(a, b, d) \ 198 + __builtin_choose_expr(is_signed_type(typeof(a)), \ 199 + __signed_mul_overflow(a, b, d), \ 200 + __unsigned_mul_overflow(a, b, d)) 201 + 202 + 203 + #endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */ 204 + 205 + /** 206 + * array_size() - Calculate size of 2-dimensional array. 207 + * 208 + * @a: dimension one 209 + * @b: dimension two 210 + * 211 + * Calculates size of 2-dimensional array: @a * @b. 212 + * 213 + * Returns: number of bytes needed to represent the array or SIZE_MAX on 214 + * overflow. 215 + */ 216 + static inline __must_check size_t array_size(size_t a, size_t b) 217 + { 218 + size_t bytes; 219 + 220 + if (check_mul_overflow(a, b, &bytes)) 221 + return SIZE_MAX; 222 + 223 + return bytes; 224 + } 225 + 226 + /** 227 + * array3_size() - Calculate size of 3-dimensional array. 228 + * 229 + * @a: dimension one 230 + * @b: dimension two 231 + * @c: dimension three 232 + * 233 + * Calculates size of 3-dimensional array: @a * @b * @c. 234 + * 235 + * Returns: number of bytes needed to represent the array or SIZE_MAX on 236 + * overflow. 237 + */ 238 + static inline __must_check size_t array3_size(size_t a, size_t b, size_t c) 239 + { 240 + size_t bytes; 241 + 242 + if (check_mul_overflow(a, b, &bytes)) 243 + return SIZE_MAX; 244 + if (check_mul_overflow(bytes, c, &bytes)) 245 + return SIZE_MAX; 246 + 247 + return bytes; 248 + } 249 + 250 + static inline __must_check size_t __ab_c_size(size_t n, size_t size, size_t c) 251 + { 252 + size_t bytes; 253 + 254 + if (check_mul_overflow(n, size, &bytes)) 255 + return SIZE_MAX; 256 + if (check_add_overflow(bytes, c, &bytes)) 257 + return SIZE_MAX; 258 + 259 + return bytes; 260 + } 261 + 262 + /** 263 + * struct_size() - Calculate size of structure with trailing array. 264 + * @p: Pointer to the structure. 265 + * @member: Name of the array member. 266 + * @n: Number of elements in the array. 267 + * 268 + * Calculates size of memory needed for structure @p followed by an 269 + * array of @n @member elements. 270 + * 271 + * Return: number of bytes needed or SIZE_MAX on overflow. 272 + */ 273 + #define struct_size(p, member, n) \ 274 + __ab_c_size(n, \ 275 + sizeof(*(p)->member) + __must_be_array((p)->member),\ 276 + sizeof(*(p))) 277 + 278 + #endif /* __LINUX_OVERFLOW_H */
+20
tools/include/tools/libc_compat.h
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* Copyright (C) 2018 Netronome Systems, Inc. */ 3 + 4 + #ifndef __TOOLS_LIBC_COMPAT_H 5 + #define __TOOLS_LIBC_COMPAT_H 6 + 7 + #include <stdlib.h> 8 + #include <linux/overflow.h> 9 + 10 + #ifdef COMPAT_NEED_REALLOCARRAY 11 + static inline void *reallocarray(void *ptr, size_t nmemb, size_t size) 12 + { 13 + size_t bytes; 14 + 15 + if (unlikely(check_mul_overflow(nmemb, size, &bytes))) 16 + return NULL; 17 + return realloc(ptr, bytes); 18 + } 19 + #endif 20 + #endif
+5 -1
tools/lib/bpf/Makefile
··· 66 66 endif 67 67 68 68 FEATURE_USER = .libbpf 69 - FEATURE_TESTS = libelf libelf-getphdrnum libelf-mmap bpf 69 + FEATURE_TESTS = libelf libelf-getphdrnum libelf-mmap bpf reallocarray 70 70 FEATURE_DISPLAY = libelf bpf 71 71 72 72 INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi -I$(srctree)/tools/perf ··· 118 118 119 119 ifeq ($(feature-libelf-getphdrnum), 1) 120 120 override CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT 121 + endif 122 + 123 + ifeq ($(feature-reallocarray), 0) 124 + override CFLAGS += -DCOMPAT_NEED_REALLOCARRAY 121 125 endif 122 126 123 127 # Append required CFLAGS
+6 -4
tools/lib/bpf/libbpf.c
··· 22 22 * License along with this program; if not, see <http://www.gnu.org/licenses> 23 23 */ 24 24 25 + #define _GNU_SOURCE 25 26 #include <stdlib.h> 26 27 #include <stdio.h> 27 28 #include <stdarg.h> ··· 42 41 #include <sys/stat.h> 43 42 #include <sys/types.h> 44 43 #include <sys/vfs.h> 44 + #include <tools/libc_compat.h> 45 45 #include <libelf.h> 46 46 #include <gelf.h> 47 47 ··· 323 321 progs = obj->programs; 324 322 nr_progs = obj->nr_programs; 325 323 326 - progs = realloc(progs, sizeof(progs[0]) * (nr_progs + 1)); 324 + progs = reallocarray(progs, nr_progs + 1, sizeof(progs[0])); 327 325 if (!progs) { 328 326 /* 329 327 * In this case the original obj->programs ··· 824 822 continue; 825 823 } 826 824 827 - reloc = realloc(reloc, 828 - sizeof(*obj->efile.reloc) * nr_reloc); 825 + reloc = reallocarray(reloc, nr_reloc, 826 + sizeof(*obj->efile.reloc)); 829 827 if (!reloc) { 830 828 pr_warning("realloc failed\n"); 831 829 err = -ENOMEM; ··· 1117 1115 return -LIBBPF_ERRNO__RELOC; 1118 1116 } 1119 1117 new_cnt = prog->insns_cnt + text->insns_cnt; 1120 - new_insn = realloc(prog->insns, new_cnt * sizeof(*insn)); 1118 + new_insn = reallocarray(prog->insns, new_cnt, sizeof(*insn)); 1121 1119 if (!new_insn) { 1122 1120 pr_warning("oom in prog realloc\n"); 1123 1121 return -ENOMEM;