Bug Summary

File:build-scan/../src/core/ip-address-access.c
Warning:line 180, column 17
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ip-address-access.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/core/libcore.a.p -I src/core -I ../src/core -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I /usr/include/libmount -I /usr/include/blkid -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/core/ip-address-access.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <stdio.h>
4#include <stdlib.h>
5
6#include "alloc-util.h"
7#include "bpf-firewall.h"
8#include "extract-word.h"
9#include "hostname-util.h"
10#include "ip-address-access.h"
11#include "parse-util.h"
12#include "string-util.h"
13
14int config_parse_ip_address_access(
15 const char *unit,
16 const char *filename,
17 unsigned line,
18 const char *section,
19 unsigned section_line,
20 const char *lvalue,
21 int ltype,
22 const char *rvalue,
23 void *data,
24 void *userdata) {
25
26 IPAddressAccessItem **list = data;
27 const char *p;
28 int r;
29
30 assert(list)do { if ((__builtin_expect(!!(!(list)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("list"), "../src/core/ip-address-access.c"
, 30, __PRETTY_FUNCTION__); } while (0)
;
1
Assuming 'list' is non-null
2
Taking false branch
3
Loop condition is false. Exiting loop
31
32 if (isempty(rvalue)) {
4
Taking false branch
33 *list = ip_address_access_free_all(*list);
34 return 0;
35 }
36
37 p = rvalue;
38
39 for (;;) {
5
Loop condition is true. Entering loop body
40 _cleanup_free___attribute__((cleanup(freep))) IPAddressAccessItem *a = NULL((void*)0);
41 _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0);
42
43 r = extract_first_word(&p, &word, NULL((void*)0), 0);
44 if (r == 0)
6
Assuming 'r' is equal to 0
7
Taking true branch
45 break;
8
Execution continues on line 135
46 if (r == -ENOMEM12)
47 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/ip-address-access.c"
, 47, __func__)
;
48 if (r < 0) {
49 log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue)({ int _level = (4), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/core/ip-address-access.c", 49, __func__
, "Invalid syntax, ignoring: %s", rvalue) : -abs(_e); })
;
50 break;
51 }
52
53 a = new0(IPAddressAccessItem, 1)((IPAddressAccessItem*) calloc((1), sizeof(IPAddressAccessItem
)))
;
54 if (!a)
55 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/ip-address-access.c"
, 55, __func__)
;
56
57 if (streq(word, "any")(strcmp((word),("any")) == 0)) {
58 /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */
59
60 a->family = AF_INET2;
61 LIST_APPEND(items, *list, a)do { typeof(*(*list)) *_tail; do { typeof(*(*list)) *_item = (
*list); if (!_item) (_tail) = ((void*)0); else { while (_item
->items_next) _item = _item->items_next; (_tail) = _item
; } } while (0); do { typeof(*(*list)) **_head = &(*list)
, *_a = (_tail), *_b = (a); do { if ((__builtin_expect(!!(!(_b
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_b"), "../src/core/ip-address-access.c"
, 61, __PRETTY_FUNCTION__); } while (0); if (!_a) { if ((_b->
items_next = *_head)) _b->items_next->items_prev = _b; _b
->items_prev = ((void*)0); *_head = _b; } else { if ((_b->
items_next = _a->items_next)) _b->items_next->items_prev
= _b; _b->items_prev = _a; _a->items_next = _b; } } while
(0); } while (0)
;
62
63 a = new0(IPAddressAccessItem, 1)((IPAddressAccessItem*) calloc((1), sizeof(IPAddressAccessItem
)))
;
64 if (!a)
65 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/ip-address-access.c"
, 65, __func__)
;
66
67 a->family = AF_INET610;
68
69 } else if (is_localhost(word)) {
70 /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */
71
72 a->family = AF_INET2;
73 a->address.in.s_addr = htobe32(0x7f000000)__bswap_32 (0x7f000000);
74 a->prefixlen = 8;
75 LIST_APPEND(items, *list, a)do { typeof(*(*list)) *_tail; do { typeof(*(*list)) *_item = (
*list); if (!_item) (_tail) = ((void*)0); else { while (_item
->items_next) _item = _item->items_next; (_tail) = _item
; } } while (0); do { typeof(*(*list)) **_head = &(*list)
, *_a = (_tail), *_b = (a); do { if ((__builtin_expect(!!(!(_b
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_b"), "../src/core/ip-address-access.c"
, 75, __PRETTY_FUNCTION__); } while (0); if (!_a) { if ((_b->
items_next = *_head)) _b->items_next->items_prev = _b; _b
->items_prev = ((void*)0); *_head = _b; } else { if ((_b->
items_next = _a->items_next)) _b->items_next->items_prev
= _b; _b->items_prev = _a; _a->items_next = _b; } } while
(0); } while (0)
;
76
77 a = new0(IPAddressAccessItem, 1)((IPAddressAccessItem*) calloc((1), sizeof(IPAddressAccessItem
)))
;
78 if (!a)
79 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/ip-address-access.c"
, 79, __func__)
;
80
81 a->family = AF_INET610;
82 a->address.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT{ { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } };
83 a->prefixlen = 128;
84
85 } else if (streq(word, "link-local")(strcmp((word),("link-local")) == 0)) {
86
87 /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */
88
89 a->family = AF_INET2;
90 a->address.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16))__bswap_32 ((169U << 24 | 254U << 16));
91 a->prefixlen = 16;
92 LIST_APPEND(items, *list, a)do { typeof(*(*list)) *_tail; do { typeof(*(*list)) *_item = (
*list); if (!_item) (_tail) = ((void*)0); else { while (_item
->items_next) _item = _item->items_next; (_tail) = _item
; } } while (0); do { typeof(*(*list)) **_head = &(*list)
, *_a = (_tail), *_b = (a); do { if ((__builtin_expect(!!(!(_b
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_b"), "../src/core/ip-address-access.c"
, 92, __PRETTY_FUNCTION__); } while (0); if (!_a) { if ((_b->
items_next = *_head)) _b->items_next->items_prev = _b; _b
->items_prev = ((void*)0); *_head = _b; } else { if ((_b->
items_next = _a->items_next)) _b->items_next->items_prev
= _b; _b->items_prev = _a; _a->items_next = _b; } } while
(0); } while (0)
;
93
94 a = new0(IPAddressAccessItem, 1)((IPAddressAccessItem*) calloc((1), sizeof(IPAddressAccessItem
)))
;
95 if (!a)
96 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/ip-address-access.c"
, 96, __func__)
;
97
98 a->family = AF_INET610;
99 a->address.in6 = (struct in6_addr) {
100 .s6_addr32__in6_u.__u6_addr32[0] = htobe32(0xfe800000)__bswap_32 (0xfe800000)
101 };
102 a->prefixlen = 64;
103
104 } else if (streq(word, "multicast")(strcmp((word),("multicast")) == 0)) {
105
106 /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */
107
108 a->family = AF_INET2;
109 a->address.in.s_addr = htobe32((UINT32_C(224) << 24))__bswap_32 ((224U << 24));
110 a->prefixlen = 4;
111 LIST_APPEND(items, *list, a)do { typeof(*(*list)) *_tail; do { typeof(*(*list)) *_item = (
*list); if (!_item) (_tail) = ((void*)0); else { while (_item
->items_next) _item = _item->items_next; (_tail) = _item
; } } while (0); do { typeof(*(*list)) **_head = &(*list)
, *_a = (_tail), *_b = (a); do { if ((__builtin_expect(!!(!(_b
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_b"), "../src/core/ip-address-access.c"
, 111, __PRETTY_FUNCTION__); } while (0); if (!_a) { if ((_b->
items_next = *_head)) _b->items_next->items_prev = _b; _b
->items_prev = ((void*)0); *_head = _b; } else { if ((_b->
items_next = _a->items_next)) _b->items_next->items_prev
= _b; _b->items_prev = _a; _a->items_next = _b; } } while
(0); } while (0)
;
112
113 a = new0(IPAddressAccessItem, 1)((IPAddressAccessItem*) calloc((1), sizeof(IPAddressAccessItem
)))
;
114 if (!a)
115 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/ip-address-access.c"
, 115, __func__)
;
116
117 a->family = AF_INET610;
118 a->address.in6 = (struct in6_addr) {
119 .s6_addr32__in6_u.__u6_addr32[0] = htobe32(0xff000000)__bswap_32 (0xff000000)
120 };
121 a->prefixlen = 8;
122
123 } else {
124 r = in_addr_prefix_from_string_auto(word, &a->family, &a->address, &a->prefixlen);
125 if (r < 0) {
126 log_syntax(unit, LOG_WARNING, filename, line, r, "Address prefix is invalid, ignoring assignment: %s", word)({ int _level = (4), _e = (r); (log_get_max_level_realm(LOG_REALM_SYSTEMD
) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level
, filename, line, _e, "../src/core/ip-address-access.c", 126,
__func__, "Address prefix is invalid, ignoring assignment: %s"
, word) : -abs(_e); })
;
127 return 0;
128 }
129 }
130
131 LIST_APPEND(items, *list, a)do { typeof(*(*list)) *_tail; do { typeof(*(*list)) *_item = (
*list); if (!_item) (_tail) = ((void*)0); else { while (_item
->items_next) _item = _item->items_next; (_tail) = _item
; } } while (0); do { typeof(*(*list)) **_head = &(*list)
, *_a = (_tail), *_b = (a); do { if ((__builtin_expect(!!(!(_b
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_b"), "../src/core/ip-address-access.c"
, 131, __PRETTY_FUNCTION__); } while (0); if (!_a) { if ((_b->
items_next = *_head)) _b->items_next->items_prev = _b; _b
->items_prev = ((void*)0); *_head = _b; } else { if ((_b->
items_next = _a->items_next)) _b->items_next->items_prev
= _b; _b->items_prev = _a; _a->items_next = _b; } } while
(0); } while (0)
;
132 a = NULL((void*)0);
133 }
134
135 *list = ip_address_access_reduce(*list);
9
Calling 'ip_address_access_reduce'
136
137 if (*list) {
138 r = bpf_firewall_supported();
139 if (r < 0)
140 return r;
141 if (r == BPF_FIREWALL_UNSUPPORTED) {
142 static bool_Bool warned = false0;
143
144 log_full(warned ? LOG_DEBUG : LOG_WARNING,({ int _level = (((warned ? 7 : 4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/ip-address-access.c", 146, __func__, "File %s:%u configures an IP firewall (%s=%s), but the local system does not support BPF/cgroup based firewalling.\n"
"Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first loaded unit using IP firewalling.)"
, filename, line, lvalue, rvalue) : -abs(_e); })
145 "File %s:%u configures an IP firewall (%s=%s), but the local system does not support BPF/cgroup based firewalling.\n"({ int _level = (((warned ? 7 : 4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/ip-address-access.c", 146, __func__, "File %s:%u configures an IP firewall (%s=%s), but the local system does not support BPF/cgroup based firewalling.\n"
"Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first loaded unit using IP firewalling.)"
, filename, line, lvalue, rvalue) : -abs(_e); })
146 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first loaded unit using IP firewalling.)", filename, line, lvalue, rvalue)({ int _level = (((warned ? 7 : 4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/core/ip-address-access.c", 146, __func__, "File %s:%u configures an IP firewall (%s=%s), but the local system does not support BPF/cgroup based firewalling.\n"
"Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first loaded unit using IP firewalling.)"
, filename, line, lvalue, rvalue) : -abs(_e); })
;
147
148 warned = true1;
149 }
150 }
151
152 return 0;
153}
154
155IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first) {
156 IPAddressAccessItem *next, *p = first;
157
158 while (p) {
159 next = p->items_next;
160 free(p);
161
162 p = next;
163 }
164
165 return NULL((void*)0);
166}
167
168IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first) {
169 IPAddressAccessItem *a, *b, *tmp;
170 int r;
171
172 /* Drops all entries from the list that are covered by another entry in full, thus removing all redundant
173 * entries. */
174
175 LIST_FOREACH_SAFE(items, a, tmp, first)for ((a) = (first); (a) && (((tmp) = (a)->items_next
), 1); (a) = (tmp))
{
10
Assuming 'a' is non-null
11
Loop condition is true. Entering loop body
32
Assuming 'a' is non-null
33
Loop condition is true. Entering loop body
176
177 /* Drop irrelevant bits */
178 (void) in_addr_mask(a->family, &a->address, a->prefixlen);
179
180 LIST_FOREACH(items, b, first)for ((b) = (first); (b); (b) = (b)->items_next) {
12
Loop condition is true. Entering loop body
15
Loop condition is true. Entering loop body
34
Loop condition is true. Entering loop body
38
Use of memory after it is freed
181
182 if (a
12.1
'a' is equal to 'b'
== b
)
13
Taking true branch
16
Assuming 'a' is not equal to 'b'
17
Taking false branch
35
Assuming 'a' is equal to 'b'
36
Taking true branch
183 continue;
14
Execution continues on line 180
37
Execution continues on line 180
184
185 if (a->family != b->family)
18
Assuming 'a->family' is equal to 'b->family'
19
Taking false branch
186 continue;
187
188 if (b->prefixlen > a->prefixlen)
20
Assuming 'b->prefixlen' is <= 'a->prefixlen'
21
Taking false branch
189 continue;
190
191 r = in_addr_prefix_covers(b->family,
192 &b->address,
193 b->prefixlen,
194 &a->address);
195 if (r > 0) {
22
Assuming 'r' is > 0
23
Taking true branch
196 /* b covers a fully, then let's drop a */
197 LIST_REMOVE(items, first, a)do { typeof(*(first)) **_head = &(first), *_item = (a); do
{ if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("_item"), "../src/core/ip-address-access.c"
, 197, __PRETTY_FUNCTION__); } while (0); if (_item->items_next
) _item->items_next->items_prev = _item->items_prev;
if (_item->items_prev) _item->items_prev->items_next
= _item->items_next; else { do { if ((__builtin_expect(!!
(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/core/ip-address-access.c", 197
, __PRETTY_FUNCTION__); } while (0); *_head = _item->items_next
; } _item->items_next = _item->items_prev = ((void*)0);
} while (0)
;
24
Taking false branch
25
Loop condition is false. Exiting loop
26
Taking true branch
27
Assuming field 'items_prev' is non-null
28
Taking true branch
29
Loop condition is false. Exiting loop
198 free(a);
30
Memory is released
199 break;
31
Execution continues on line 175
200 }
201 }
202 }
203
204 return first;
205}