iproute/backport-ipmaddr-fix-dereference-of-NULL-on-malloc-failure.patch

318 lines
14 KiB
Diff
Raw Normal View History

From 8cda7a24a971170b833009f392579cfea87711bf Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Mon, 8 May 2023 19:02:20 -0700
Subject: [PATCH] ipmaddr: fix dereference of NULL on malloc() failure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Found by -fanalyzer. This is a bug since beginning of initial
versions of ip multicast support (pre git).
ipmaddr.c: In function read_dev_mcast:
ipmaddr.c:105:25: warning: dereference of possibly-NULL ma [CWE-690] [-Wanalyzer-possible-null-dereference]
105 | memcpy(ma, &m, sizeof(m));
| ^~~~~~~~~~~~~~~~~~~~~~~~~
do_multiaddr: events 1-4
|
| 354 | int do_multiaddr(int argc, char **argv)
| | ^~~~~~~~~~~~
| | |
| | (1) entry to do_multiaddr
| 355 | {
| 356 | if (argc < 1)
| | ~
| | |
| | (2) following true branch (when argc <= 0)...
| 357 | return multiaddr_list(0, NULL);
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) ...to here
| | (4) calling multiaddr_list from do_multiaddr
|
+--> multiaddr_list: events 5-10
|
| 255 | static int multiaddr_list(int argc, char **argv)
| | ^~~~~~~~~~~~~~
| | |
| | (5) entry to multiaddr_list
|......
| 262 | while (argc > 0) {
| | ~~~~~~~~
| | |
| | (6) following false branch (when argc <= 0)...
|......
| 275 | if (!filter.family || filter.family == AF_PACKET)
| | ~ ~~~~~~~~~~~~~
| | | |
| | | (7) ...to here
| | (8) following true branch...
| 276 | read_dev_mcast(&list);
| | ~~~~~~~~~~~~~~~~~~~~~
| | |
| | (9) ...to here
| | (10) calling read_dev_mcast from multiaddr_list
|
+--> read_dev_mcast: events 11-12
|
| 82 | static void read_dev_mcast(struct ma_info **result_p)
| | ^~~~~~~~~~~~~~
| | |
| | (11) entry to read_dev_mcast
|......
| 87 | if (!fp)
| | ~
| | |
| | (12) following false branch (when fp is non-NULL)...
|
read_dev_mcast: event 13
|
|cc1:
| (13): ...to here
|
read_dev_mcast: events 14-17
|
| 90 | while (fgets(buf, sizeof(buf), fp)) {
| | ^~~~~
| | |
| | (14) following true branch...
| 91 | char hexa[256];
| 92 | struct ma_info m = { .addr.family = AF_PACKET };
| | ~
| | |
| | (15) ...to here
|......
| 103 | struct ma_info *ma = malloc(sizeof(m));
| | ~~~~~~~~~~~~~~~~~
| | |
| | (16) this call could return NULL
| 104 |
| 105 | memcpy(ma, &m, sizeof(m));
| | ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (17) ma could be NULL: unchecked value from (16)
|
ipmaddr.c: In function read_igmp:
ipmaddr.c:152:17: warning: dereference of possibly-NULL ma [CWE-690] [-Wanalyzer-possible-null-dereference]
152 | memcpy(ma, &m, sizeof(m));
| ^~~~~~~~~~~~~~~~~~~~~~~~~
do_multiaddr: events 1-4
|
| 354 | int do_multiaddr(int argc, char **argv)
| | ^~~~~~~~~~~~
| | |
| | (1) entry to do_multiaddr
| 355 | {
| 356 | if (argc < 1)
| | ~
| | |
| | (2) following true branch (when argc <= 0)...
| 357 | return multiaddr_list(0, NULL);
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) ...to here
| | (4) calling multiaddr_list from do_multiaddr
|
+--> multiaddr_list: events 5-10
|
| 255 | static int multiaddr_list(int argc, char **argv)
| | ^~~~~~~~~~~~~~
| | |
| | (5) entry to multiaddr_list
|......
| 262 | while (argc > 0) {
| | ~~~~~~~~
| | |
| | (6) following false branch (when argc <= 0)...
|......
| 275 | if (!filter.family || filter.family == AF_PACKET)
| | ~~~~~~~~~~~~~
| | |
| | (7) ...to here
| 276 | read_dev_mcast(&list);
| 277 | if (!filter.family || filter.family == AF_INET)
| | ~
| | |
| | (8) following true branch...
| 278 | read_igmp(&list);
| | ~~~~~~~~~~~~~~~~
| | |
| | (9) ...to here
| | (10) calling read_igmp from multiaddr_list
|
+--> read_igmp: events 11-14
|
| 116 | static void read_igmp(struct ma_info **result_p)
| | ^~~~~~~~~
| | |
| | (11) entry to read_igmp
|......
| 126 | if (!fp)
| | ~
| | |
| | (12) following false branch (when fp is non-NULL)...
| 127 | return;
| 128 | if (!fgets(buf, sizeof(buf), fp)) {
| | ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | | |
| | | (13) ...to here
| | (14) following false branch...
|
read_igmp: event 15
|
|cc1:
| (15): ...to here
|
read_igmp: events 16-19
|
| 133 | while (fgets(buf, sizeof(buf), fp)) {
| | ^~~~~
| | |
| | (16) following true branch...
|......
| 136 | if (buf[0] != '\t') {
| | ~~~~~~
| | |
| | (17) ...to here
|......
| 151 | ma = malloc(sizeof(m));
| | ~~~~~~~~~~~~~~~~~
| | |
| | (18) this call could return NULL
| 152 | memcpy(ma, &m, sizeof(m));
| | ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (19) ma could be NULL: unchecked value from (18)
|
ipmaddr.c: In function read_igmp6:
ipmaddr.c:181:25: warning: dereference of possibly-NULL ma [CWE-690] [-Wanalyzer-possible-null-dereference]
181 | memcpy(ma, &m, sizeof(m));
| ^~~~~~~~~~~~~~~~~~~~~~~~~
do_multiaddr: events 1-4
|
| 354 | int do_multiaddr(int argc, char **argv)
| | ^~~~~~~~~~~~
| | |
| | (1) entry to do_multiaddr
| 355 | {
| 356 | if (argc < 1)
| | ~
| | |
| | (2) following true branch (when argc <= 0)...
| 357 | return multiaddr_list(0, NULL);
| | ~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) ...to here
| | (4) calling multiaddr_list from do_multiaddr
|
+--> multiaddr_list: events 5-10
|
| 255 | static int multiaddr_list(int argc, char **argv)
| | ^~~~~~~~~~~~~~
| | |
| | (5) entry to multiaddr_list
|......
| 262 | while (argc > 0) {
| | ~~~~~~~~
| | |
| | (6) following false branch (when argc <= 0)...
|......
| 275 | if (!filter.family || filter.family == AF_PACKET)
| | ~~~~~~~~~~~~~
| | |
| | (7) ...to here
|......
| 279 | if (!filter.family || filter.family == AF_INET6)
| | ~
| | |
| | (8) following true branch...
| 280 | read_igmp6(&list);
| | ~~~~~~~~~~~~~~~~~
| | |
| | (9) ...to here
| | (10) calling read_igmp6 from multiaddr_list
|
+--> read_igmp6: events 11-12
|
| 159 | static void read_igmp6(struct ma_info **result_p)
| | ^~~~~~~~~~
| | |
| | (11) entry to read_igmp6
|......
| 164 | if (!fp)
| | ~
| | |
| | (12) following false branch (when fp is non-NULL)...
|
read_igmp6: event 13
|
|cc1:
| (13): ...to here
|
read_igmp6: events 14-17
|
| 167 | while (fgets(buf, sizeof(buf), fp)) {
| | ^~~~~
| | |
| | (14) following true branch...
| 168 | char hexa[256];
| 169 | struct ma_info m = { .addr.family = AF_INET6 };
| | ~
| | |
| | (15) ...to here
|......
| 179 | struct ma_info *ma = malloc(sizeof(m));
| | ~~~~~~~~~~~~~~~~~
| | |
| | (16) this call could return NULL
| 180 |
| 181 | memcpy(ma, &m, sizeof(m));
| | ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (17) ma could be NULL: unchecked value from (16)
|
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
ip/ipmaddr.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/ip/ipmaddr.c b/ip/ipmaddr.c
index f8d6b992..a8ef20ec 100644
--- a/ip/ipmaddr.c
+++ b/ip/ipmaddr.c
@@ -102,6 +102,8 @@ static void read_dev_mcast(struct ma_info **result_p)
if (len >= 0) {
struct ma_info *ma = malloc(sizeof(m));
+ if (ma == NULL)
+ break;
memcpy(ma, &m, sizeof(m));
ma->addr.bytelen = len;
ma->addr.bitlen = len<<3;
@@ -149,6 +151,9 @@ static void read_igmp(struct ma_info **result_p)
sscanf(buf, "%08x%d", (__u32 *)&m.addr.data, &m.users);
ma = malloc(sizeof(m));
+ if (ma == NULL)
+ break;
+
memcpy(ma, &m, sizeof(m));
maddr_ins(result_p, ma);
}
@@ -178,8 +183,10 @@ static void read_igmp6(struct ma_info **result_p)
if (len >= 0) {
struct ma_info *ma = malloc(sizeof(m));
- memcpy(ma, &m, sizeof(m));
+ if (ma == NULL)
+ break;
+ memcpy(ma, &m, sizeof(m));
ma->addr.bytelen = len;
ma->addr.bitlen = len<<3;
maddr_ins(result_p, ma);
--
2.27.0