Bug Summary

File:programs/pluto/timer.c
Warning:line 549, column 16
Access to field 'st_logger' results in a dereference of a null pointer (loaded from variable 'st')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name timer.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 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -resource-dir /usr/lib64/clang/13.0.0 -D TimeZoneOffset=timezone -D PIE -D NSS_IPSEC_PROFILE -D XFRM_LIFETIME_DEFAULT=30 -D USE_IKEv1 -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 HAVE_NM -D USE_PAM_AUTH -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 USE_NSS_KDF -D DEFAULT_RUNDIR="/run/pluto" -D IPSEC_CONF="/etc/ipsec.conf" -D IPSEC_CONFDDIR="/etc/ipsec.d" -D IPSEC_NSSDIR="/var/lib/ipsec/nss" -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/quick-libreswan-2/programs/pluto/linux-copy -D HERE_FILENAME="programs/pluto/timer.c" -internal-isystem /usr/lib64/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/11/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu99 -fdebug-compilation-dir=/home/build/quick-libreswan-2/programs/pluto -ferror-limit 19 -stack-protector 3 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-01-01-205714-1273399-1 -x c /home/build/quick-libreswan-2/programs/pluto/timer.c
1/* timer event handling
2 *
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-2019 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-2020 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 <stdio.h>
26#include <stdlib.h>
27#include <sys/types.h>
28#include <time.h>
29#include <unistd.h>
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <event2/event.h>
34#include <event2/event_struct.h>
35
36#include "sysdep.h"
37#include "constants.h"
38#include "defs.h"
39#include "id.h"
40#include "x509.h"
41#include "certs.h"
42#include "connections.h" /* needs id.h */
43#include "state.h"
44#include "packet.h"
45#include "demux.h" /* needs packet.h */
46#include "ipsec_doi.h" /* needs demux.h and state.h */
47#include "kernel.h" /* needs connections.h */
48#include "server.h"
49#include "log.h"
50#include "rnd.h"
51#include "timer.h"
52#include "whack.h"
53#include "ikev1_dpd.h"
54#include "ikev2.h"
55#include "ikev2_redirect.h"
56#include "pending.h" /* for flush_pending_by_connection */
57#include "ikev1_xauth.h"
58#ifdef USE_PAM_AUTH1
59#include "pam_auth.h"
60#endif
61#include "kernel.h" /* for kernel_ops */
62#include "nat_traversal.h"
63#include "pluto_sd.h"
64#include "ikev1_retry.h"
65#include "ikev2_retry.h"
66#include "fetch.h" /* for check_crls() */
67#include "pluto_stats.h"
68#include "iface.h"
69#include "ikev2_liveness.h"
70#include "ikev2_mobike.h"
71#include "ikev2_delete.h" /* for submit_v2_delete_exchange() */
72
73struct state_event **state_event(struct state *st, enum event_type type)
74{
75 /*
76 * Return a pointer to the event in the state object.
77 *
78 * XXX: why not just have an array and index it by KIND?
79 */
80 switch (type) {
81
82 case EVENT_v1_SEND_XAUTH:
83 return &st->st_v1_send_xauth_event;
84
85 case EVENT_v2_LIVENESS:
86 return &st->st_v2_liveness_event;
87
88 case EVENT_v2_ADDR_CHANGE:
89 return &st->st_v2_addr_change_event;
90 break;
91
92 case EVENT_v2_REKEY:
93 return &st->st_v2_rekey_event;
94 break;
95
96 case EVENT_v2_REAUTH:
97 return &st->st_v2_reauth_event;
98 break;
99
100 case EVENT_DPD:
101 case EVENT_DPD_TIMEOUT:
102 return &st->st_dpd_event;
103
104 case EVENT_RETRANSMIT:
105 return &st->st_retransmit_event;
106
107 case EVENT_SA_DISCARD:
108 case EVENT_SA_REPLACE:
109 case EVENT_SA_EXPIRE:
110 case EVENT_v1_REPLACE_IF_USED:
111 case EVENT_CRYPTO_TIMEOUT:
112 case EVENT_PAM_TIMEOUT:
113 case EVENT_v2_REDIRECT:
114 /*
115 * Many of these don't make sense - however that's
116 * what happens when (the replaced) default: is used.
117 */
118 return &st->st_event;
119
120 case EVENT_RETAIN:
121 case EVENT_NULL:
122 return NULL((void*)0);
123 }
124 bad_case(type)libreswan_bad_case("type", (type), ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/timer.c",
.line = 124, }; &here; }))
;
125}
126
127/*
128 * This file has the event handling routines. Events are
129 * kept as a linked list of event structures. These structures
130 * have information like event type, expiration time and a pointer
131 * to event specific data (for example, to a state structure).
132 */
133
134static void dispatch_event(struct state *st, enum event_type event_type,
135 deltatime_t event_delay);
136static event_callback_routine timer_event_cb;
137
138static void timer_event_cb(evutil_socket_tint unused_fd UNUSED__attribute__ ((unused)),
139 const short unused_event UNUSED__attribute__ ((unused)),
140 void *arg)
141{
142 /*
143 * Start billing before state is found.
144 */
145 threadtime_t inception = threadtime_start();
146
147 /*
148 * Get rid of the old timer event before calling the timer
149 * event processor.
150 */
151 struct state *st;
152 enum event_type event_type;
153 const char *event_name;
154 deltatime_t event_delay;
155
156 {
157 struct state_event *ev = arg;
158 passert(ev != NULL)({ _Bool assertion__ = ev != ((void*)0); if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/timer.c", .line = 158, }; &here
; }); const struct logger *logger_ = &failsafe_logger; llog_passert
(logger_, here, "%s", "ev != ((void*)0)"); } (void) 1; })
;
159 event_type = ev->ev_type;
160 event_name = enum_name_short(&event_type_names, event_type);
161 event_delay = ev->ev_delay;
162 st = ev->ev_state; /* note: *st might be changed; XXX: why? */
163 passert(st != NULL)({ _Bool assertion__ = st != ((void*)0); if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/timer.c", .line = 163, }; &here
; }); const struct logger *logger_ = &failsafe_logger; llog_passert
(logger_, here, "%s", "st != ((void*)0)"); } (void) 1; })
;
164 passert(event_name != NULL)({ _Bool assertion__ = event_name != ((void*)0); if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/timer.c", .line = 164, }
; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "event_name != ((void*)0)"
); } (void) 1; })
;
165
166 dbg("%s: processing %s-event@%p for %s SA #%lu in state %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: processing %s-event@%p for %s SA #%lu in state %s"
, __func__, event_name, ev, ((st)->st_clonedfrom == 0) ? "IKE"
: "CHILD", st->st_serialno, st->st_state->short_name
); } }
167 __func__, event_name, ev,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: processing %s-event@%p for %s SA #%lu in state %s"
, __func__, event_name, ev, ((st)->st_clonedfrom == 0) ? "IKE"
: "CHILD", st->st_serialno, st->st_state->short_name
); } }
168 IS_IKE_SA(st) ? "IKE" : "CHILD",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: processing %s-event@%p for %s SA #%lu in state %s"
, __func__, event_name, ev, ((st)->st_clonedfrom == 0) ? "IKE"
: "CHILD", st->st_serialno, st->st_state->short_name
); } }
169 st->st_serialno, st->st_state->short_name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: processing %s-event@%p for %s SA #%lu in state %s"
, __func__, event_name, ev, ((st)->st_clonedfrom == 0) ? "IKE"
: "CHILD", st->st_serialno, st->st_state->short_name
); } }
;
170
171 struct state_event **evp = state_event(st, event_type);
172 if (evp == NULL((void*)0)) {
173 pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/timer.c", .line = 173, }; &here; })
,
174 "#%lu has no .st_event field for %s",
175 st->st_serialno, event_name);
176 return;
177 }
178
179 if (*evp != ev) {
180 pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/timer.c", .line = 180, }; &here; })
,
181 "#%lu .st_event is %p but should be %s-pe@%p",
182 st->st_serialno, *evp, event_name, ev);
183 return;
184 }
185
186 /* everything useful has been extracted */
187 delete_pluto_event(evp);
188 arg = ev = *evp = NULL((void*)0); /* all gone */
189 }
190
191 statetime_t start = statetime_backdate(st, &inception);
192 dispatch_event(st, event_type, event_delay);
193 statetime_stop(&start, "%s() %s", __func__, event_name);
194}
195
196static void dispatch_event(struct state *st, enum event_type event_type,
197 deltatime_t event_delay)
198{
199 /*
200 * Check that st is as expected for the event type.
201 *
202 * For an event type associated with a state, remove the
203 * backpointer from the appropriate slot of the state object.
204 *
205 * We'll eventually either schedule a new event, or delete the
206 * state.
207 */
208 switch (event_type) {
209
210 case EVENT_v2_ADDR_CHANGE:
211 dbg("#%lu IKEv2 local address change", st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("#%lu IKEv2 local address change", st->st_serialno
); } }
;
212 ikev2_addr_change(st);
213 break;
214
215 case EVENT_RETRANSMIT:
216 dbg("IKEv%d retransmit event", st->st_ike_version){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("IKEv%d retransmit event", st->st_connection
->ike_version); } }
;
217 switch (st->st_ike_versionst_connection->ike_version) {
218 case IKEv2:
219 retransmit_v2_msg(st);
220 break;
221#ifdef USE_IKEv11
222 case IKEv1:
223 retransmit_v1_msg(st);
224 break;
225#endif
226 default:
227 bad_case(st->st_ike_version)libreswan_bad_case("st->st_ike_version", (st->st_connection
->ike_version), ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/timer.c", .line = 227, }
; &here; }))
;
228 }
229 break;
230
231#ifdef USE_IKEv11
232 case EVENT_v1_SEND_XAUTH:
233 dbg("XAUTH: event EVENT_v1_SEND_XAUTH #%lu %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("XAUTH: event EVENT_v1_SEND_XAUTH #%lu %s", st
->st_serialno, st->st_state->name); } }
234 st->st_serialno, st->st_state->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("XAUTH: event EVENT_v1_SEND_XAUTH #%lu %s", st
->st_serialno, st->st_state->name); } }
;
235 xauth_send_request(st);
236 break;
237#endif
238
239 case EVENT_v2_LIVENESS:
240 liveness_check(st);
241 break;
242
243 case EVENT_v2_REKEY:
244 pexpect(st->st_ike_version == IKEv2)({ _Bool assertion__ = st->st_connection->ike_version ==
IKEv2; if (!assertion__) { where_t here_ = ({ static const struct
where here = { .func = __func__, .file = "programs/pluto/timer.c"
, .line = 244, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "st->st_connection->ike_version == IKEv2"
); } assertion__; })
;
245 v2_event_sa_rekey(st);
246 break;
247
248 case EVENT_v2_REAUTH:
249 pexpect(st->st_ike_version == IKEv2)({ _Bool assertion__ = st->st_connection->ike_version ==
IKEv2; if (!assertion__) { where_t here_ = ({ static const struct
where here = { .func = __func__, .file = "programs/pluto/timer.c"
, .line = 249, }; &here; }); const struct logger *logger_
= &failsafe_logger; llog_pexpect(logger_, here_, "%s", "st->st_connection->ike_version == IKEv2"
); } assertion__; })
;
250 v2_event_sa_reauth(st);
251 break;
252
253 case EVENT_SA_REPLACE:
254 case EVENT_v1_REPLACE_IF_USED:
255 switch (st->st_ike_versionst_connection->ike_version) {
256 case IKEv2:
257 pexpect(event_type == EVENT_SA_REPLACE)({ _Bool assertion__ = event_type == EVENT_SA_REPLACE; if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/timer.c", .line = 257, }
; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "event_type == EVENT_SA_REPLACE"
); } assertion__; })
;
258 v2_event_sa_replace(st);
259 break;
260 case IKEv1:
261 pexpect(event_type == EVENT_SA_REPLACE ||({ _Bool assertion__ = event_type == EVENT_SA_REPLACE || event_type
== EVENT_v1_REPLACE_IF_USED; if (!assertion__) { where_t here_
= ({ static const struct where here = { .func = __func__, .file
= "programs/pluto/timer.c", .line = 262, }; &here; }); const
struct logger *logger_ = &failsafe_logger; llog_pexpect(
logger_, here_, "%s", "event_type == EVENT_SA_REPLACE || event_type == EVENT_v1_REPLACE_IF_USED"
); } assertion__; })
262 event_type == EVENT_v1_REPLACE_IF_USED)({ _Bool assertion__ = event_type == EVENT_SA_REPLACE || event_type
== EVENT_v1_REPLACE_IF_USED; if (!assertion__) { where_t here_
= ({ static const struct where here = { .func = __func__, .file
= "programs/pluto/timer.c", .line = 262, }; &here; }); const
struct logger *logger_ = &failsafe_logger; llog_pexpect(
logger_, here_, "%s", "event_type == EVENT_SA_REPLACE || event_type == EVENT_v1_REPLACE_IF_USED"
); } assertion__; })
;
263 struct connection *c = st->st_connection;
264 const char *satype = IS_IKE_SA(st)((st)->st_clonedfrom == 0) ? "IKE" : "CHILD";
265
266 so_serial_t newer_sa = get_newer_sa_from_connection(st);
267 if (newer_sa != SOS_NOBODY0) {
268 /* not very interesting: no need to replace */
269 dbg("not replacing stale %s SA %lu; #%lu will do",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("not replacing stale %s SA %lu; #%lu will do",
satype, st->st_serialno, newer_sa); } }
270 satype, st->st_serialno, newer_sa){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("not replacing stale %s SA %lu; #%lu will do",
satype, st->st_serialno, newer_sa); } }
;
271 } else if (event_type == EVENT_v1_REPLACE_IF_USED &&
272 !monobefore(mononow(), monotime_add(st->st_outbound_time, c->sa_rekey_margin))) {
273 /*
274 * we observed no recent use: no need to replace
275 *
276 * The sampling effects mean that st_outbound_time
277 * could be up to SHUNT_SCAN_INTERVAL more recent
278 * than actual traffic because the sampler looks at
279 * change over that interval.
280 * st_outbound_time could also not yet reflect traffic
281 * in the last SHUNT_SCAN_INTERVAL.
282 * We expect that SHUNT_SCAN_INTERVAL is smaller than
283 * c->sa_rekey_margin so that the effects of this will
284 * be unimportant.
285 * This is just an optimization: correctness is not
286 * at stake.
287 */
288 dbg("not replacing stale %s SA: inactive for %jds",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("not replacing stale %s SA: inactive for %jds"
, satype, deltasecs(monotimediff(mononow(), st->st_outbound_time
))); } }
289 satype, deltasecs(monotimediff(mononow(), st->st_outbound_time))){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("not replacing stale %s SA: inactive for %jds"
, satype, deltasecs(monotimediff(mononow(), st->st_outbound_time
))); } }
;
290 } else {
291 dbg("replacing stale %s SA",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("replacing stale %s SA", ((st)->st_clonedfrom
== 0) ? "ISAKMP" : "IPsec"); } }
292 IS_IKE_SA(st) ? "ISAKMP" : "IPsec"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("replacing stale %s SA", ((st)->st_clonedfrom
== 0) ? "ISAKMP" : "IPsec"); } }
;
293 /*
294 * XXX: this call gets double billed -
295 * both to the state being deleted and
296 * to the new state being created.
297 */
298 ipsecdoi_replace(st, 1);
299 }
300
301 event_delete(EVENT_v2_LIVENESS, st);
302 event_delete(EVENT_DPD, st);
303 event_schedule(EVENT_SA_EXPIRE, st->st_replace_margin, st);
304 break;
305 default:
306 bad_case(st->st_ike_version)libreswan_bad_case("st->st_ike_version", (st->st_connection
->ike_version), ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/timer.c", .line = 306, }
; &here; }))
;
307 }
308 break;
309
310 case EVENT_SA_EXPIRE:
311 {
312 struct connection *c = st->st_connection;
313 const char *satype = IS_IKE_SA(st)((st)->st_clonedfrom == 0) ? "IKE" : "CHILD";
314 so_serial_t newer_sa = get_newer_sa_from_connection(st);
315
316 if (newer_sa != SOS_NOBODY0) {
317 /* not very interesting: already superseded */
318 dbg("%s SA expired (superseded by #%lu)",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s SA expired (superseded by #%lu)", satype, newer_sa
); } }
319 satype, newer_sa){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s SA expired (superseded by #%lu)", satype, newer_sa
); } }
;
320 } else if (!IS_IKE_SA_ESTABLISHED(st)((st)->st_state->kind == STATE_V2_ESTABLISHED_IKE_SA) &&
321 !IS_V1_ISAKMP_SA_ESTABLISHED(st)((((lset_t)1 << ((st)->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)0))
) {
322 /* not very interesting: failed IKE attempt */
323 dbg("un-established partial Child SA timeout (SA expired)"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("un-established partial Child SA timeout (SA expired)"
); } }
;
324 pstat_sa_failed(st, REASON_EXCHANGE_TIMEOUT);
325 } else {
326 log_state(RC_LOG, st, "%s SA expired (%s)", satype,
327 (c->policy & POLICY_DONT_REKEY((lset_t)1 << (POLICY_DONT_REKEY_IX))) ? "--dontrekey" : "LATEST!");
328 }
329
330 /* Delete this state object. It must be in the hash table. */
331 switch (st->st_ike_versionst_connection->ike_version) {
332 case IKEv2:
333 {
334 struct ike_sa *ike = ike_sa(st, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/timer.c", .line = 334, }; &here; })
);
335 if (ike == NULL((void*)0)) {
336 /*
337 * XXX: SNAFU with IKE SA replacing
338 * itself (but not deleting its
339 * children?) simultaneous to a CHILD
340 * SA failing to establish and
341 * attempting to delete / replace
342 * itself?
343 *
344 * Because these things are
345 * not serialized it is hard
346 * to say.
347 */
348 log_state(RC_LOG_SERIOUS, st, "Child SA lost its IKE SA #%lu",
349 st->st_clonedfrom);
350 delete_state(st);
351 st = NULL((void*)0);
352 } else if (IS_IKE_SA(st)((st)->st_clonedfrom == 0)) {
353 /* IKEv2 parent, delete children too */
354 dbg("IKEv2 SA expired, delete whole family"){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("IKEv2 SA expired, delete whole family"); } }
;
355 passert(&ike->sa == st)({ _Bool assertion__ = &ike->sa == st; if (!assertion__
) { where_t here = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/timer.c", .line = 355, }
; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_passert(logger_, here, "%s", "&ike->sa == st");
} (void) 1; })
;
356 delete_ike_family(ike, PROBABLY_SEND_DELETE);
357 /* note: no md->st to clear */
358 st = NULL((void*)0);
359 } else if (IS_IKE_SA_ESTABLISHED(&ike->sa)((&ike->sa)->st_state->kind == STATE_V2_ESTABLISHED_IKE_SA
)
) {
360 /* note: no md->st to clear */
361 submit_v2_delete_exchange(ike, pexpect_child_sa(st));
362 st = NULL((void*)0);
363 } else {
364 delete_state(st);
365 st = NULL((void*)0);
366 }
367 break;
368 }
369 case IKEv1:
370 delete_state(st);
371 /* note: no md->st to clear */
372 /* st = NULL; */
373 break;
374 default:
375 bad_case(st->st_ike_version)libreswan_bad_case("st->st_ike_version", (st->st_connection
->ike_version), ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/timer.c", .line = 375, }
; &here; }))
;
376 }
377 break;
378 }
379
380 case EVENT_SA_DISCARD:
381 /*
382 * The state failed to complete within a reasonable
383 * time, or the state failed but was left to live for
384 * a while so re-transmits could work, or the state is
385 * being garbage collected. Either way, time to
386 * delete it.
387 */
388 if (deltatime_cmp(event_delay, >, deltatime_zero)(deltatime_sub_sign(event_delay, deltatime_zero) > 0)) {
389 /* Don't bother logging 0 delay */
390 deltatime_buf dtb;
391 log_state(RC_LOG, st, "deleting incomplete state after %s seconds",
392 str_deltatime(event_delay, &dtb));
393 }
394 /*
395 * If no other reason has been given then this is a
396 * timeout.
397 */
398 pstat_sa_failed(st, REASON_EXCHANGE_TIMEOUT);
399 /*
400 * XXX: this is scary overkill - delete_state() likes
401 * to resurect things and/or send messages. What's
402 * needed is a lower-level discard_state() that just
403 * does its job.
404 *
405 * XXX: for IKEv2, it looks like delete_state() will
406 * stop spontaneously sending messages (and hopefully
407 * spontaneously deleting IKE families).
408 */
409 delete_state(st);
410 break;
411
412 case EVENT_v2_REDIRECT:
413 initiate_redirect(st);
414 break;
415
416#ifdef USE_IKEv11
417 case EVENT_DPD:
418 dpd_event(st);
419 break;
420
421 case EVENT_DPD_TIMEOUT:
422 dpd_timeout(st);
423 break;
424
425#ifdef USE_PAM_AUTH1
426 case EVENT_PAM_TIMEOUT:
427 dbg("PAM thread timeout on state #%lu", st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("PAM thread timeout on state #%lu", st->st_serialno
); } }
;
428 pam_auth_abort(st, "timeout");
429 /*
430 * Things get cleaned up when the PAM process exits.
431 *
432 * Should this schedule an event for the case when the
433 * child process (which is SIGKILLed) doesn't exit!?!
434 */
435 break;
436#endif
437#endif
438 case EVENT_CRYPTO_TIMEOUT:
439 dbg("event crypto_failed on state #%lu, aborting",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("event crypto_failed on state #%lu, aborting",
st->st_serialno); } }
440 st->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("event crypto_failed on state #%lu, aborting",
st->st_serialno); } }
;
441 pstat_sa_failed(st, REASON_CRYPTO_TIMEOUT);
442 delete_state(st);
443 /* note: no md->st to clear */
444 break;
445
446
447 default:
448 bad_case(event_type)libreswan_bad_case("event_type", (event_type), ({ static const
struct where here = { .func = __func__, .file = "programs/pluto/timer.c"
, .line = 448, }; &here; }))
;
449 }
450}
451
452/*
453 * Delete all of the lifetime events (if any).
454 *
455 * Most lifetime events (things that kill the state) try to share a
456 * single .st_event. However, there has been and likely will be
457 * exceptions (for instance the retransmit timer), and the code below
458 * is written to deal with it.
459 *
460 * XXX:
461 *
462 * The decision to have all the loosely lifetime related timers
463 * (retransmit, rekey, replace, ...) share a single .st_event field is
464 * ... unfortunate. The code has to constantly juggle the field
465 * deciding which event is next. Far easier to set and forget each
466 * independently. This is why the retransmit timer has been split
467 * off.
468 */
469void delete_event(struct state *st)
470{
471 struct liveness {
472 const char *name;
473 struct state_event **event;
474 } events[] = {
475 { "st_event", &st->st_event, },
476 };
477 for (unsigned e = 0; e < elemsof(events)(sizeof(events) / sizeof(*(events))); e++) {
478 struct liveness *l = &events[e];
479 if (*(l->event) == NULL((void*)0)) {
480 dbg("state #%lu has no .%s to delete", st->st_serialno,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("state #%lu has no .%s to delete", st->st_serialno
, l->name); } }
481 l->name){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("state #%lu has no .%s to delete", st->st_serialno
, l->name); } }
;
482 } else {
483 esb_buf b;
484 dbg("state #%lu deleting .%s %s",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("state #%lu deleting .%s %s", st->st_serialno
, l->name, enum_show(&event_type_names, (*l->event)
->ev_type, &b)); } }
485 st->st_serialno, l->name,{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("state #%lu deleting .%s %s", st->st_serialno
, l->name, enum_show(&event_type_names, (*l->event)
->ev_type, &b)); } }
486 enum_show(&event_type_names, (*l->event)->ev_type, &b)){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("state #%lu deleting .%s %s", st->st_serialno
, l->name, enum_show(&event_type_names, (*l->event)
->ev_type, &b)); } }
;
487 delete_pluto_event(l->event);
488 }
489 }
490}
491
492/*
493 * This routine schedules a state event.
494 */
495void event_schedule(enum event_type type, deltatime_t delay, struct state *st)
496{
497 passert(st != NULL)({ _Bool assertion__ = st != ((void*)0); if (!assertion__) { where_t
here = ({ static const struct where here = { .func = __func__
, .file = "programs/pluto/timer.c", .line = 497, }; &here
; }); const struct logger *logger_ = &failsafe_logger; llog_passert
(logger_, here, "%s", "st != ((void*)0)"); } (void) 1; })
;
498 /*
499 * Scheduling a month into the future is most likely a bug.
500 * pexpect() causes us to flag this in our test cases
501 */
502 pexpect(deltasecs(delay) < secs_per_day * 31)({ _Bool assertion__ = deltasecs(delay) < secs_per_day * 31
; if (!assertion__) { where_t here_ = ({ static const struct where
here = { .func = __func__, .file = "programs/pluto/timer.c",
.line = 502, }; &here; }); const struct logger *logger_ =
&failsafe_logger; llog_pexpect(logger_, here_, "%s", "deltasecs(delay) < secs_per_day * 31"
); } assertion__; })
;
503
504 const char *en = enum_name(&event_type_names, type);
505
506 struct state_event **evp = state_event(st, type);
507 if (evp == NULL((void*)0)) {
508 pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/timer.c", .line = 508, }; &here; })
,
509 "#%lu has no .st_*event field for %s",
510 st->st_serialno,
511 enum_name(&event_type_names, type));
512 return;
513 }
514
515 if (*evp != NULL((void*)0)) {
516 /* help debugging by stumbling on */
517 pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/timer.c", .line = 517, }; &here; })
,
518 "#%lu already has a scheduled %s; forcing replacement",
519 st->st_serialno,
520 enum_name(&event_type_names, type));
521 delete_pluto_event(evp);
522 }
523
524 struct state_event *ev = alloc_thing(struct state_event, en)((struct state_event*) alloc_bytes(sizeof(struct state_event)
, (en)))
;
525 dbg("%s: newref %s-pe@%p", __func__, en, ev){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("%s: newref %s-pe@%p", __func__, en, ev); } }
;
526 ev->ev_type = type;
527 ev->ev_name = en;
528 ev->ev_state = st;
529 ev->ev_epoch = mononow();
530 ev->ev_delay = delay;
531 ev->ev_time = monotime_add(ev->ev_epoch, delay);
532 *evp = ev;
533
534 deltatime_buf buf;
535 dbg("inserting event %s, timeout in %s seconds for #%lu",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("inserting event %s, timeout in %s seconds for #%lu"
, en, str_deltatime(delay, &buf), ev->ev_state->st_serialno
); } }
536 en, str_deltatime(delay, &buf),{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("inserting event %s, timeout in %s seconds for #%lu"
, en, str_deltatime(delay, &buf), ev->ev_state->st_serialno
); } }
537 ev->ev_state->st_serialno){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("inserting event %s, timeout in %s seconds for #%lu"
, en, str_deltatime(delay, &buf), ev->ev_state->st_serialno
); } }
;
538
539 fire_timer_photon_torpedo(&ev->ev, timer_event_cb, ev, delay);
540}
541
542/*
543 * Delete a state backlinked event (if any); leave *evp == NULL.
544 */
545void event_delete(enum event_type type, struct state *st)
546{
547 struct state_event **evp = state_event(st, type);
548 if (evp == NULL((void*)0)) {
3
Assuming 'evp' is equal to NULL
4
Taking true branch
549 pexpect_failllog_pexpect(st->st_logger, HERE({ static const struct where here = { .func = __func__, .file
= "programs/pluto/timer.c", .line = 549, }; &here; })
,
5
Access to field 'st_logger' results in a dereference of a null pointer (loaded from variable 'st')
550 "#%lu has no .st_event field for %s",
551 st->st_serialno, enum_name(&event_type_names, type));
552 return;
553 }
554 if (*evp != NULL((void*)0)) {
555 dbg("#%lu requesting %s-pe@%p be deleted",{ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("#%lu requesting %s-pe@%p be deleted", st->
st_serialno, enum_name(&event_type_names, (*evp)->ev_type
), *evp); } }
556 st->st_serialno, enum_name(&event_type_names, (*evp)->ev_type), *evp){ if ((cur_debugging & (((lset_t)1 << (DBG_BASE_IX)
)))) { DBG_log("#%lu requesting %s-pe@%p be deleted", st->
st_serialno, enum_name(&event_type_names, (*evp)->ev_type
), *evp); } }
;
557 pexpect(st == (*evp)->ev_state)({ _Bool assertion__ = st == (*evp)->ev_state; if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/timer.c", .line = 557, }
; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "st == (*evp)->ev_state"
); } assertion__; })
;
558 delete_pluto_event(evp);
559 pexpect((*evp) == NULL)({ _Bool assertion__ = (*evp) == ((void*)0); if (!assertion__
) { where_t here_ = ({ static const struct where here = { .func
= __func__, .file = "programs/pluto/timer.c", .line = 559, }
; &here; }); const struct logger *logger_ = &failsafe_logger
; llog_pexpect(logger_, here_, "%s", "(*evp) == ((void*)0)");
} assertion__; })
;
560 };
561}
562
563void event_force(enum event_type type, struct state *st)
564{
565 event_delete(type, st);
1
Passing value via 2nd parameter 'st'
2
Calling 'event_delete'
566 deltatime_t delay = deltatime(0);
567 event_schedule(type, delay, st);
568}
569
570void call_state_event_handler(struct logger *logger, struct state *st,
571 enum event_type event_type)
572{
573 const char *event_name = enum_name_short(&event_type_names, event_type);
574 if (event_name == NULL((void*)0)) {
575 llog(RC_COMMENT, logger, "%d is not a valid event", event_type);
576 return;
577 }
578
579 /* sanity checks */
580 struct state_event **evp = state_event(st, event_type);
581 if (evp == NULL((void*)0)) {
582 llog(RC_COMMENT, logger, "%s is not a valid event", event_name);
583 return;
584 }
585
586 /*
587 * Like timer_event_cb(), delete the old event before calling
588 * the event handler.
589 */
590 deltatime_t event_delay = deltatime(1);
591 if (*evp == NULL((void*)0)) {
592 llog(RC_COMMENT, logger,
593 "no existing %s event to delete", event_name);
594 } else if ((*evp)->ev_type != event_type) {
595 llog(RC_COMMENT, logger,
596 "deleting existing %s event occupying the slot shared with %s",
597 enum_name(&event_type_names, (*evp)->ev_type),
598 event_name);
599 delete_pluto_event(evp);
600 } else {
601 llog(RC_COMMENT, logger,
602 "deleting existing %s event",
603 event_name);
604 event_delay = (*evp)->ev_delay;
605 delete_pluto_event(evp);
606 }
607
608 llog(RC_COMMENT, logger, "calling %s event handler", event_name);
609 dispatch_event(st, event_type, event_delay);
610}