iproute/backport-netem-fix-NULL-deref-on-allocation-failure.patch

198 lines
9.3 KiB
Diff
Raw Normal View History

From 6c266d7c22a8f4f631d278ba6102f1b1d2bca148 Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Mon, 8 May 2023 19:36:14 -0700
Subject: [PATCH] netem: fix NULL deref on allocation failure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
q_netem.c: In function get_distribution:
q_netem.c:159:35: warning: dereference of possibly-NULL data [CWE-690] [-Wanalyzer-possible-null-dereference]
159 | data[n++] = x;
| ~~~~~~~~~~^~~
netem_parse_opt: events 1-24
|
| 192 | static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv,
| | ^~~~~~~~~~~~~~~
| | |
| | (1) entry to netem_parse_opt
|......
| 212 | for ( ; argc > 0; --argc, ++argv) {
| | ~~~~~~~~
| | |
| | (2) following true branch (when argc > 0)...
| 213 | if (matches(*argv, "limit") == 0) {
| | ~~~~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(3) ...to here
| | (4) following true branch...
|......
| 219 | } else if (matches(*argv, "latency") == 0 ||
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | || |
| | |(5) ...to here (8) following true branch...
| | (6) following true branch...
| 220 | matches(*argv, "delay") == 0) {
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (7) ...to here
|......
| 243 | } else if (matches(*argv, "loss") == 0 ||
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | || |
| | |(9) ...to here (12) following true branch...
| | (10) following true branch...
| 244 | matches(*argv, "drop") == 0) {
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (11) ...to here
|......
| 366 | } else if (matches(*argv, "ecn") == 0) {
| | ~~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(13) ...to here
| | (14) following true branch...
| 367 | present[TCA_NETEM_ECN] = 1;
| 368 | } else if (matches(*argv, "reorder") == 0) {
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(15) ...to here
| | (16) following true branch...
|......
| 383 | } else if (matches(*argv, "corrupt") == 0) {
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(17) ...to here
| | (18) following true branch...
|......
| 398 | } else if (matches(*argv, "gap") == 0) {
| | ~~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(19) ...to here
| | (20) following true branch...
|......
| 404 | } else if (matches(*argv, "duplicate") == 0) {
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(21) ...to here
| | (22) following true branch...
|......
| 417 | } else if (matches(*argv, "distribution") == 0) {
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | ||
| | |(23) ...to here
| | (24) following false branch...
|
netem_parse_opt: event 25
|
|../include/utils.h:50:29:
| 50 | #define NEXT_ARG() do { argv++; if (--argc <= 0) incomplete_command(); } while(0)
| | ~~~~^~
| | |
| | (25) ...to here
q_netem.c:418:25: note: in expansion of macro NEXT_ARG
| 418 | NEXT_ARG();
| | ^~~~~~~~
|
netem_parse_opt: event 26
|
|../include/utils.h:50:36:
| 50 | #define NEXT_ARG() do { argv++; if (--argc <= 0) incomplete_command(); } while(0)
| | ^
| | |
| | (26) following false branch (when argc != 0)...
q_netem.c:418:25: note: in expansion of macro NEXT_ARG
| 418 | NEXT_ARG();
| | ^~~~~~~~
|
netem_parse_opt: events 27-29
|
| 419 | dist_data = calloc(sizeof(dist_data[0]), MAX_DIST);
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (27) ...to here
| | (28) this call could return NULL
| 420 | dist_size = get_distribution(*argv, dist_data, MAX_DIST);
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (29) calling get_distribution from netem_parse_opt
|
+--> get_distribution: events 30-31
|
| 124 | static int get_distribution(const char *type, __s16 *data, int maxdata)
| | ^~~~~~~~~~~~~~~~
| | |
| | (30) entry to get_distribution
|......
| 135 | if (f == NULL) {
| | ~
| | |
| | (31) following false branch (when f is non-NULL)...
|
get_distribution: event 32
|
|cc1:
| (32): ...to here
|
get_distribution: events 33-35
|
| 142 | while (getline(&line, &len, f) != -1) {
| | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
| | |
| | (33) following true branch...
|......
| 145 | if (*line == '\n' || *line == '#')
| | ~~~~~~
| | ||
| | |(34) ...to here
| | (35) following false branch...
|
get_distribution: event 36
|
|cc1:
| (36): ...to here
|
get_distribution: events 37-41
|
| 150 | if (endp == p)
| | ^
| | |
| | (37) following false branch...
|......
| 153 | if (n >= maxdata) {
| | ~
| | |
| | (38) ...to here
| | (39) following false branch (when n < maxdata)...
|......
| 159 | data[n++] = x;
| | ~~~~~~~~~~~~~
| | | |
| | | (41) data + (long unsigned int)n * 2 could be NULL: unchecked value from (28)
| | (40) ...to here
|
Fixes: c1b81cb5fe92 ("netem potential dist table overflow")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
tc/q_netem.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tc/q_netem.c b/tc/q_netem.c
index 26402e9a..d1d79b0b 100644
--- a/tc/q_netem.c
+++ b/tc/q_netem.c
@@ -417,6 +417,9 @@ random_loss_model:
} else if (matches(*argv, "distribution") == 0) {
NEXT_ARG();
dist_data = calloc(sizeof(dist_data[0]), MAX_DIST);
+ if (dist_data == NULL)
+ return -1;
+
dist_size = get_distribution(*argv, dist_data, MAX_DIST);
if (dist_size <= 0) {
free(dist_data);
--
2.27.0