Bug Summary

File:programs/pluto/retry.c
Warning:line 211, column 6
Access to field 'st_state' results in a dereference of a null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name retry.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 -mrelocation-model pic -pic-level 2 -pic-is-pie -mthread-model posix -mdisable-fp-elim -relaxed-aliasing -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -resource-dir /usr/lib64/clang/8.0.0 -D TimeZoneOffset=timezone -D linux -D PIE -D NSS_IPSEC_PROFILE -D XFRM_SUPPORT -D USE_XFRM_INTERFACE -D USE_DNSSEC -D DEFAULT_DNSSEC_ROOTKEY_FILE="/var/lib/unbound/root.key" -D HAVE_LABELED_IPSEC -D HAVE_SECCOMP -D LIBCURL -D USE_LINUX_AUDIT -D USE_SYSTEMD_WATCHDOG -D HAVE_NM -D XAUTH_HAVE_PAM -D USE_3DES -D USE_AES -D USE_CAMELLIA -D USE_CHACHA -D USE_DH31 -D USE_MD5 -D USE_SHA1 -D USE_SHA2 -D USE_PRF_AES_XCBC -D DEFAULT_RUNDIR="/run/pluto" -D IPSEC_CONF="/etc/ipsec.conf" -D IPSEC_CONFDDIR="/etc/ipsec.d" -D IPSEC_NSSDIR="/etc/ipsec.d" -D IPSEC_CONFDIR="/etc" -D IPSEC_EXECDIR="/usr/local/libexec/ipsec" -D IPSEC_SBINDIR="/usr/local/sbin" -D IPSEC_VARDIR="/var" -D POLICYGROUPSDIR="/etc/ipsec.d/policies" -D IPSEC_SECRETS_FILE="/etc/ipsec.secrets" -D FORCE_PR_ASSERT -D USE_FORK=1 -D USE_VFORK=0 -D USE_DAEMON=0 -D USE_PTHREAD_SETSCHEDPRIO=1 -D GCC_LINT -D HAVE_LIBCAP_NG -I . -I ../../OBJ.linux.x86_64/programs/pluto -I ../../include -I /usr/include/nss3 -I /usr/include/nspr4 -I /home/build/libreswan/programs/pluto/linux-copy -D HERE_BASENAME="retry.c" -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/8.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-missing-field-initializers -std=gnu99 -fdebug-compilation-dir /home/build/libreswan/programs/pluto -ferror-limit 19 -fmessage-length 0 -stack-protector 3 -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-output=html -o /tmp/scan-build-2020-09-09-193337-25440-1 -x c /home/build/libreswan/programs/pluto/retry.c -faddrsig
1/*
2 * timer event handling
3 * Copyright (C) 1997 Angelos D. Keromytis.
4 * Copyright (C) 1998-2001 D. Hugh Redelmeier.
5 * Copyright (C) 2005-2008 Michael Richardson <mcr@xelerance.com>
6 * Copyright (C) 2008-2010 Paul Wouters <paul@xelerance.com>
7 * Copyright (C) 2009 David McCullough <david_mccullough@securecomputing.com>
8 * Copyright (C) 2012 Avesh Agarwal <avagarwa@redhat.com>
9 * Copyright (C) 2012-2015 Paul Wouters <pwouters@redhat.com>
10 * Copyright (C) 2013 Matt Rogers <mrogers@redhat.com>
11 * Copyright (C) 2017 Antony Antony <antony@phenome.org>
12 * Copyright (C) 2017-2019 Andrew Cagney <cagney@gnu.org>
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25#include "defs.h"
26#include "state.h"
27#include "retry.h"
28#include "log.h"
29#include "ip_address.h"
30#include "connections.h"
31#include "ikev1_send.h"
32#include "ikev2_send.h"
33#include "demux.h" /* for state_transition_fn used by ipsec_doi.h */
34#include "ipsec_doi.h"
35#include "ikev2.h" /* for need_this_intiator() */
36#include "pluto_stats.h"
37
38/* Time to retransmit, or give up.
39 *
40 * Generally, we'll only try to send the message
41 * MAXIMUM_RETRANSMISSIONS times. Each time we double
42 * our patience.
43 *
44 * As a special case, if this is the first initiating message
45 * of a Main Mode exchange, and we have been directed to try
46 * forever, we'll extend the number of retransmissions to
47 * MAXIMUM_RETRANSMISSIONS_INITIAL times, with all these
48 * extended attempts having the same patience. The intention
49 * is to reduce the bother when nobody is home.
50 *
51 * Since IKEv1 is not reliable for the Quick Mode responder,
52 * we'll extend the number of retransmissions as well to
53 * improve the reliability.
54 */
55void retransmit_v1_msg(struct state *st)
56{
57 struct connection *c = st->st_connection;
58 unsigned long try = st->st_try;
59 unsigned long try_limit = c->sa_keying_tries;
60
61 set_cur_state(st)log_push_state(st, (where_t) { .func = __func__, .basename = "retry.c"
, .line = 61})
;
62
63 /* Paul: this line can say attempt 3 of 2 because the cleanup happens when over the maximum */
64 address_buf b;
65 connection_buf cib;
66 dbg("handling event EVENT_RETRANSMIT for %s "PRI_CONNECTION" #%lu keying attempt %lu of %lu; retransmit %lu",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("handling event EVENT_RETRANSMIT for %s ""\"%s\"%s"
" #%lu keying attempt %lu of %lu; retransmit %lu", str_address
(&c->spd.that.host_addr, &b), (c)->name, str_connection_instance
(c, &cib), st->st_serialno, try, try_limit, retransmit_count
(st) + 1); } }
67 str_address(&c->spd.that.host_addr, &b),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("handling event EVENT_RETRANSMIT for %s ""\"%s\"%s"
" #%lu keying attempt %lu of %lu; retransmit %lu", str_address
(&c->spd.that.host_addr, &b), (c)->name, str_connection_instance
(c, &cib), st->st_serialno, try, try_limit, retransmit_count
(st) + 1); } }
68 pri_connection(c, &cib),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("handling event EVENT_RETRANSMIT for %s ""\"%s\"%s"
" #%lu keying attempt %lu of %lu; retransmit %lu", str_address
(&c->spd.that.host_addr, &b), (c)->name, str_connection_instance
(c, &cib), st->st_serialno, try, try_limit, retransmit_count
(st) + 1); } }
69 st->st_serialno, try, try_limit,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("handling event EVENT_RETRANSMIT for %s ""\"%s\"%s"
" #%lu keying attempt %lu of %lu; retransmit %lu", str_address
(&c->spd.that.host_addr, &b), (c)->name, str_connection_instance
(c, &cib), st->st_serialno, try, try_limit, retransmit_count
(st) + 1); } }
70 retransmit_count(st) + 1){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("handling event EVENT_RETRANSMIT for %s ""\"%s\"%s"
" #%lu keying attempt %lu of %lu; retransmit %lu", str_address
(&c->spd.that.host_addr, &b), (c)->name, str_connection_instance
(c, &cib), st->st_serialno, try, try_limit, retransmit_count
(st) + 1); } }
;
71
72 switch (retransmit(st)) {
73 case RETRANSMIT_YES:
74 resend_recorded_v1_ike_msg(st, "EVENT_RETRANSMIT");
75 return;
76 case RETRANSMIT_NO:
77 return;
78 case RETRANSMITS_TIMED_OUT:
79 break;
80 case DELETE_ON_RETRANSMIT:
81 /* disable re-key code */
82 try = 0;
83 break;
84 }
85
86 if (try != 0 && (try <= try_limit || try_limit == 0)) {
87 /*
88 * A lot like EVENT_SA_REPLACE, but over again. Since
89 * we know that st cannot be in use, we can delete it
90 * right away.
91 */
92 char story[80]; /* arbitrary limit */
93
94 try++;
95 snprintf(story, sizeof(story), try_limit == 0 ?
96 "starting keying attempt %ld of an unlimited number" :
97 "starting keying attempt %ld of at most %ld",
98 try, try_limit);
99
100 /* ??? DBG and real-world code mixed */
101 if (!DBGP(DBG_WHACKWATCH)(cur_debugging & (((lset_t)1 << (DBG_WHACKWATCH_IX)
)))
) {
102 if (fd_p(st->st_whack_sockst_logger->object_whackfd)) {
103 /*
104 * Release whack because the observer
105 * will get bored.
106 */
107 loglog(RC_COMMENT,
108 "%s, but releasing whack",
109 story);
110 release_pending_whacks(st, story);
111 } else if ((c->policy & POLICY_OPPORTUNISTIC((lset_t)1 << (POLICY_OPPORTUNISTIC_IX))) == LEMPTY((lset_t)0)) {
112 /* no whack: just log */
113 libreswan_log("%s", story)loglog(RC_LOG, "%s", story);
114 }
115 } else if ((c->policy & POLICY_OPPORTUNISTIC((lset_t)1 << (POLICY_OPPORTUNISTIC_IX))) == LEMPTY((lset_t)0)) {
116 loglog(RC_COMMENT, "%s", story);
117 }
118
119 ipsecdoi_replace(st, try);
120 }
121
122 set_cur_state(st)log_push_state(st, (where_t) { .func = __func__, .basename = "retry.c"
, .line = 122})
; /* ipsecdoi_replace would reset cur_state, set it again */
123 pstat_sa_failed(st, REASON_TOO_MANY_RETRANSMITS);
124
125 /* placed here because IKEv1 doesn't do a proper state change to STF_FAIL/STF_FATAL */
126 linux_audit_conn(st, IS_IKE_SA(st)((st)->st_clonedfrom == 0) ? LAK_PARENT_FAIL : LAK_CHILD_FAIL);
127
128 delete_state(st);
129 /* note: no md->st to clear */
130}
131
132void retransmit_v2_msg(struct state *st)
133{
134 passert(st != NULL){ _Bool assertion__ = st != ((void*)0); if (!assertion__) { lsw_passert_fail
((where_t) { .func = __func__, .basename = "retry.c" , .line =
134}, "%s", "st != NULL"); } }
;
1
Assuming 'st' is not equal to null
2
Taking false branch
135 struct ike_sa *ike = ike_sa(st, HERE(where_t) { .func = __func__, .basename = "retry.c" , .line =
135}
);
3
'ike' initialized here
136 if (ike == NULL((void*)0)) {
4
Assuming 'ike' is equal to NULL
5
Taking true branch
137 dbg("no ike sa so going away"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("no ike sa so going away"); } }
;
6
Assuming the condition is false
7
Taking false branch
138 delete_state(st);
139 }
140
141 set_cur_state(st)log_push_state(st, (where_t) { .func = __func__, .basename = "retry.c"
, .line = 141})
;
142 struct connection *c = st->st_connection;
143 unsigned long try_limit = c->sa_keying_tries;
144 unsigned long try = st->st_try + 1;
145
146 /*
147 * Paul: this line can stay attempt 3 of 2 because the cleanup
148 * happens when over the maximum
149 */
150 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
8
Assuming the condition is false
9
Taking false branch
151 ipstr_buf b;
152 connection_buf cib;
153 DBG_log("handling event EVENT_RETRANSMIT for %s "PRI_CONNECTION"\"%s\"%s"" #%lu attempt %lu of %lu",
154 ipstr(&c->spd.that.host_addr, &b),
155 pri_connection(c, &cib)(c)->name, str_connection_instance(c, &cib),
156 st->st_serialno, try, try_limit);
157 DBG_log("and parent for %s "PRI_CONNECTION"\"%s\"%s"" #%lu keying attempt %lu of %lu; retransmit %lu",
158 ipstr(&c->spd.that.host_addr, &b),
159 pri_connection(c, &cib)(c)->name, str_connection_instance(c, &cib),
160 ike->sa.st_serialno,
161 ike->sa.st_try, try_limit,
162 retransmit_count(&ike->sa) + 1);
163 }
164
165 /*
166 * if this connection has a newer Child SA than this state
167 * this negotiation is not relevant any more. would this
168 * cover if there are multiple CREATE_CHILD_SA pending on this
169 * IKE negotiation ???
170 *
171 * XXX: Suspect this is to handle a race where the other end
172 * brings up the connection first? For that case, shouldn't
173 * this state have been deleted?
174 */
175 if (st->st_establishing_sa == IKE_SA &&
10
Assuming the condition is false
176 c->newest_isakmp_sa > st->st_serialno) {
177 log_state(RC_LOG, st,
178 "suppressing retransmit because IKE SA was superseded #%lu try=%lu; drop this negotiation",
179 c->newest_isakmp_sa, st->st_try);
180 pstat_sa_failed(st, REASON_TOO_MANY_RETRANSMITS);
181 delete_state(st);
182 return;
183 } else if (st->st_establishing_sa == IPSEC_SA &&
11
Assuming the condition is false
184 c->newest_ipsec_sa > st->st_serialno) {
185 log_state(RC_LOG, st,
186 "suppressing retransmit because CHILD SA was superseded by #%lu try=%lu; drop this negotiation",
187 c->newest_ipsec_sa, st->st_try);
188 pstat_sa_failed(st, REASON_TOO_MANY_RETRANSMITS);
189 delete_state(st);
190 return;
191 }
192
193 switch (retransmit(st)) {
12
Control jumps to 'case RETRANSMITS_TIMED_OUT:' at line 200
194 case RETRANSMIT_YES:
195 send_recorded_v2_message(ike, "EVENT_RETRANSMIT",
196 MESSAGE_REQUEST);
197 return;
198 case RETRANSMIT_NO:
199 return;
200 case RETRANSMITS_TIMED_OUT:
201 break;
13
Execution continues on line 211
202 case DELETE_ON_RETRANSMIT:
203 /* disable revival code */
204 try = 0;
205 break;
206 }
207
208 /*
209 * The entire family is dead dead head
210 */
211 if (IS_IKE_SA_ESTABLISHED(&ike->sa)( ((((lset_t)1 << ((&ike->sa)->st_state->kind
)) & (((lset_t)1 << (STATE_MAIN_R3)) | ((lset_t)1 <<
(STATE_MAIN_I4)) | ((lset_t)1 << (STATE_AGGR_I2)) | ((
lset_t)1 << (STATE_AGGR_R2)) | ((lset_t)1 << (STATE_XAUTH_R0
)) | ((lset_t)1 << (STATE_XAUTH_R1)) | ((lset_t)1 <<
(STATE_MODE_CFG_R0)) | ((lset_t)1 << (STATE_MODE_CFG_R1
)) | ((lset_t)1 << (STATE_MODE_CFG_R2)) | ((lset_t)1 <<
(STATE_MODE_CFG_I1)) | ((lset_t)1 << (STATE_XAUTH_I0))
| ((lset_t)1 << (STATE_XAUTH_I1)) | ((lset_t)1 <<
(STATE_V2_ESTABLISHED_IKE_SA)))) != ((lset_t)0)) || ((((&
ike->sa)->st_state->kind == STATE_V2_ESTABLISHED_IKE_SA
) && !((&ike->sa)->st_clonedfrom != 0)) &&
((&ike->sa)->st_clonedfrom == 0)))
) {
14
Access to field 'st_state' results in a dereference of a null pointer
212 /*
213 * Since the IKE SA is established, mimic the
214 * (probably wrong) behaviour of the old liveness code
215 * path - it needs to revive all the connections under
216 * the IKE SA and not just this one child(?).
217 */
218 /* already logged */
219 liveness_action(st->st_connection, st->st_ike_version);
220 /* presumably liveness_action() deletes the state? */
221 return;
222 }
223
224 if (try != 0 && (try <= try_limit || try_limit == 0)) {
225 /*
226 * A lot like EVENT_SA_REPLACE, but over again.
227 * Since we know that st cannot be in use,
228 * we can delete it right away.
229 */
230 char story[80]; /* arbitrary limit */
231
232 snprintf(story, sizeof(story), try_limit == 0 ?
233 "starting keying attempt %ld of an unlimited number" :
234 "starting keying attempt %ld of at most %ld",
235 try, try_limit);
236
237 if (fd_p(st->st_whack_sockst_logger->object_whackfd)) {
238 /*
239 * Release whack because the observer will
240 * get bored.
241 */
242 loglog(RC_COMMENT, "%s, but releasing whack",
243 story);
244 release_pending_whacks(st, story);
245 } else if ((c->policy & POLICY_OPPORTUNISTIC((lset_t)1 << (POLICY_OPPORTUNISTIC_IX))) == LEMPTY((lset_t)0)) {
246 /* no whack: just log to syslog */
247 libreswan_log("%s", story)loglog(RC_LOG, "%s", story);
248 }
249
250 ipsecdoi_replace(st, try);
251 } else {
252 dbg("maximum number of keyingtries reached - deleting state"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("maximum number of keyingtries reached - deleting state"
); } }
;
253 }
254
255 if (&ike->sa != st) {
256 set_cur_state(&ike->sa)log_push_state(&ike->sa, (where_t) { .func = __func__,
.basename = "retry.c" , .line = 256})
; /* now we are on pst */
257 if (ike->sa.st_state->kind == STATE_PARENT_I2) {
258 pstat_sa_failed(&ike->sa, REASON_TOO_MANY_RETRANSMITS);
259 delete_state(&ike->sa);
260 } else {
261 free_v2_message_queues(st);
262 }
263 }
264
265 set_cur_state(st)log_push_state(st, (where_t) { .func = __func__, .basename = "retry.c"
, .line = 265})
; /* ipsecdoi_replace would reset cur_state, set it again */
266
267 /*
268 * XXX There should not have been a child sa unless this was a timeout of
269 * our CREATE_CHILD_SA request. But our code has moved from parent to child
270 */
271
272 pstat_sa_failed(st, REASON_TOO_MANY_RETRANSMITS);
273 delete_state(st);
274
275 /* note: no md->st to clear */
276}
277
278bool_Bool ikev2_schedule_retry(struct state *st)
279{
280 struct connection *c = st->st_connection;
281 unsigned long try = st->st_try;
282 unsigned long try_limit = c->sa_keying_tries;
283 if (try_limit > 0 && try >= try_limit) {
284 dbg("maximum number of retries reached - deleting state"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("maximum number of retries reached - deleting state"
); } }
;
285 return false0;
286 }
287 LOG_JAMBUF(RC_COMMENT, st->st_logger, buf)for (char lswbuf[((size_t)1024)], *lswbuf_ = lswbuf; lswbuf_ !=
((void*)0); lswbuf_ = ((void*)0)) for (struct jambuf jambuf =
array_as_jambuf((lswbuf), sizeof(lswbuf)), *buf = &jambuf
; buf != ((void*)0); buf = ((void*)0)) for (({ if (((RC_COMMENT
) & STREAM_MASK) != DEBUG_STREAM || (cur_debugging & (
((lset_t)1 << (DBG_ADD_PREFIX_IX))))) { (st->st_logger
)->object_vec->jam_object_prefix(buf, (st->st_logger
)->object); } }); buf != ((void*)0); jambuf_to_logger(buf,
(st->st_logger), RC_COMMENT), buf = ((void*)0))
{
288 jam(buf, "scheduling retry attempt %ld of ", try);
289 if (try_limit == 0) {
290 jam_string(buf, "an unlimited number");
291 } else {
292 jam(buf, "at most %ld", try_limit);
293 }
294 if (fd_p(st->st_whack_sockst_logger->object_whackfd)) {
295 jam_string(buf, ", but releasing whack");
296 }
297 }
298
299 /*
300 * release_pending_whacks() will release ST (and ST's parent
301 * if it exists and has the same whack). For instance, when
302 * the AUTH exchange somehow digs a hole where the child sa
303 * gets a timeout.
304 *
305 * XXX: The child SA 'diging a hole' is likely a bug.
306 */
307 release_pending_whacks(st, "scheduling a retry");
308
309 /*
310 * XXX: Should the parent or child get re-scheduled? Does it
311 * flip to the parent when the child's timer expires?
312 */
313 suppress_retransmits(st);
314 return true1;
315}