History

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.

Jakub Kicinski committed 8 years ago

Commit 531b0141 parent 8d1340610 files · +334 −9Browse files

Unified · Split

10 files
  1. tools/bpf/bpftool/Makefile +5 −1
  2. tools/bpf/bpftool/main.h +1 −0
  3. tools/bpf/bpftool/xlated_dumper.c +3 −3
  4. tools/build/feature/Makefile +4 −0
  5. tools/build/feature/test-reallocarray.c +8 −0
  6. tools/include/linux/compiler-gcc.h +4 −0
  7. tools/include/linux/overflow.h +278 −0
  8. tools/include/tools/libc_compat.h +20 −0
  9. tools/lib/bpf/Makefile +5 −1
  10. tools/lib/bpf/libbpf.c +6 −4
tools/bpf/bpftool/Makefile+5−1
@@ -52,7 +52,7 @@ INSTALL ?= install · 51 unmodified lines
5252 RM ?= rm -f
5353
5454 FEATURE_USER = .bpftool
55−FEATURE_TESTS = libbfd disassembler-four-args
55+FEATURE_TESTS = libbfd disassembler-four-args reallocarray
5656 FEATURE_DISPLAY = libbfd disassembler-four-args
5757
5858 check_feat := 1
@@ -75,6 +75,10 @@ ifeq ($(feature-disassembler-four-args), 1) · 16 unmodified lines
7575 CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
7676 endif
7777
78+ifeq ($(feature-reallocarray), 0)
79+CFLAGS += -DCOMPAT_NEED_REALLOCARRAY
80+endif
81+
7882 include $(wildcard $(OUTPUT)*.d)
7983
8084 all: $(OUTPUT)bpftool
tools/bpf/bpftool/main.h+1−0
@@ -42,6 +42,7 @@ · 41 unmodified lines
4242 #include <linux/compiler.h>
4343 #include <linux/kernel.h>
4444 #include <linux/hashtable.h>
45+#include <tools/libc_compat.h>
4546
4647 #include "json_writer.h"
4748
tools/bpf/bpftool/xlated_dumper.c+3−3
@@ -35,6 +35,7 @@ · 34 unmodified lines
3535 * POSSIBILITY OF SUCH DAMAGE.
3636 */
3737
38+#define _GNU_SOURCE
3839 #include <stdarg.h>
3940 #include <stdio.h>
4041 #include <stdlib.h>
@@ -66,9 +67,8 @@ void kernel_syms_load(struct dump_data *dd) · 25 unmodified lines
6667 while (!feof(fp)) {
6768 if (!fgets(buff, sizeof(buff), fp))
6869 break;
69− tmp = realloc(dd->sym_mapping,
70− (dd->sym_count + 1) *
71− sizeof(*dd->sym_mapping));
70+ tmp = reallocarray(dd->sym_mapping, dd->sym_count + 1,
71+ sizeof(*dd->sym_mapping));
7272 if (!tmp) {
7373 out:
7474 free(dd->sym_mapping);
tools/build/feature/Makefile+4−0
@@ -14,6 +14,7 @@ FILES= \ · 13 unmodified lines
1414 test-libaudit.bin \
1515 test-libbfd.bin \
1616 test-disassembler-four-args.bin \
17+ test-reallocarray.bin \
1718 test-liberty.bin \
1819 test-liberty-z.bin \
1920 test-cplus-demangle.bin \
@@ -204,6 +205,9 @@ $(OUTPUT)test-libbfd.bin: · 184 unmodified lines
204205 $(OUTPUT)test-disassembler-four-args.bin:
205206 $(BUILD) -DPACKAGE='"perf"' -lbfd -lopcodes
206207
208+$(OUTPUT)test-reallocarray.bin:
209+ $(BUILD)
210+
207211 $(OUTPUT)test-liberty.bin:
208212 $(CC) $(CFLAGS) -Wall -Werror -o $@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty
209213
tools/build/feature/test-reallocarray.c+8−0
@@ -0,0 +1,8 @@
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+}
tools/include/linux/compiler-gcc.h+4−0
@@ -36,3 +36,7 @@ · 35 unmodified lines
3636 #endif
3737 #define __printf(a, b) __attribute__((format(printf, a, b)))
3838 #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
tools/include/linux/overflow.h+278−0
@@ -0,0 +1,278 @@
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 */
tools/include/tools/libc_compat.h+20−0
@@ -0,0 +1,20 @@
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
tools/lib/bpf/Makefile+5−1
@@ -66,7 +66,7 @@ ifndef VERBOSE · 65 unmodified lines
6666 endif
6767
6868 FEATURE_USER = .libbpf
69−FEATURE_TESTS = libelf libelf-getphdrnum libelf-mmap bpf
69+FEATURE_TESTS = libelf libelf-getphdrnum libelf-mmap bpf reallocarray
7070 FEATURE_DISPLAY = libelf bpf
7171
7272 INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi -I$(srctree)/tools/perf
@@ -120,6 +120,10 @@ ifeq ($(feature-libelf-getphdrnum), 1) · 47 unmodified lines
120120 override CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
121121 endif
122122
123+ifeq ($(feature-reallocarray), 0)
124+ override CFLAGS += -DCOMPAT_NEED_REALLOCARRAY
125+endif
126+
123127 # Append required CFLAGS
124128 override CFLAGS += $(EXTRA_WARNINGS)
125129 override CFLAGS += -Werror -Wall
tools/lib/bpf/libbpf.c+6−4
@@ -22,6 +22,7 @@ · 21 unmodified lines
2222 * License along with this program; if not, see <http://www.gnu.org/licenses>
2323 */
2424
25+#define _GNU_SOURCE
2526 #include <stdlib.h>
2627 #include <stdio.h>
2728 #include <stdarg.h>
@@ -41,6 +42,7 @@ · 13 unmodified lines
4142 #include <sys/stat.h>
4243 #include <sys/types.h>
4344 #include <sys/vfs.h>
45+#include <tools/libc_compat.h>
4446 #include <libelf.h>
4547 #include <gelf.h>
4648
@@ -321,7 +323,7 @@ bpf_object__add_program(struct bpf_object *obj, void *data, size_t size, · 274 unmodified lines
321323 progs = obj->programs;
322324 nr_progs = obj->nr_programs;
323325
324− progs = realloc(progs, sizeof(progs[0]) * (nr_progs + 1));
326+ progs = reallocarray(progs, nr_progs + 1, sizeof(progs[0]));
325327 if (!progs) {
326328 /*
327329 * In this case the original obj->programs
@@ -822,8 +824,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj) · 494 unmodified lines
822824 continue;
823825 }
824826
825− reloc = realloc(reloc,
826− sizeof(*obj->efile.reloc) * nr_reloc);
827+ reloc = reallocarray(reloc, nr_reloc,
828+ sizeof(*obj->efile.reloc));
827829 if (!reloc) {
828830 pr_warning("realloc failed\n");
829831 err = -ENOMEM;
@@ -1115,7 +1117,7 @@ bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj, · 285 unmodified lines
11151117 return -LIBBPF_ERRNO__RELOC;
11161118 }
11171119 new_cnt = prog->insns_cnt + text->insns_cnt;
1118− new_insn = realloc(prog->insns, new_cnt * sizeof(*insn));
1120+ new_insn = reallocarray(prog->insns, new_cnt, sizeof(*insn));
11191121 if (!new_insn) {
11201122 pr_warning("oom in prog realloc\n");
11211123 return -ENOMEM;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t