Bug Summary

File:programs/pluto/send.c
Warning:line 142, column 3
Null pointer passed as an argument to a 'nonnull' parameter

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 send.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="send.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/send.c -faddrsig
1/*
2 * sending packets, for libreswan
3 *
4 * Copyright (C) 1997 Angelos D. Keromytis.
5 * Copyright (C) 1998-2002, 2013,2016 D. Hugh Redelmeier <hugh@mimosa.com>
6 * Copyright (C) 2003-2008 Michael C Richardson <mcr@xelerance.com>
7 * Copyright (C) 2003-2010 Paul Wouters <paul@xelerance.com>
8 * Copyright (C) 2008-2009 David McCullough <david_mccullough@securecomputing.com>
9 * Copyright (C) 2009 Avesh Agarwal <avagarwa@redhat.com>
10 * Copyright (C) 2010 Tuomo Soini <tis@foobar.fi>
11 * Copyright (C) 2012-2019 Paul Wouters <pwouters@redhat.com>
12 * Copyright (C) 2013 Wolfgang Nothdurft <wolfgang@linogate.de>
13 * Copyright (C) 2016-2019 Andrew Cagney <cagney@gnu.org>
14 * Copyright (C) 2017-2019 D. Hugh Redelmeier <hugh@mimosa.com>
15 * Copyright (C) 2019 Antony Antony <antony@phenome.org>
16 *
17 * This program is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2 of the License, or (at your
20 * option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
21 *
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 * for more details.
26 *
27 */
28
29#include <unistd.h> /* for usleep() */
30#include <errno(*__errno_location ()).h>
31
32#include "defs.h"
33
34#include "send.h"
35
36#include "log.h"
37#include "state.h"
38#include "server.h"
39#include "demux.h"
40#include "pluto_stats.h"
41#include "ip_endpoint.h"
42#include "ip_sockaddr.h"
43#include "ip_protocol.h"
44#include "iface.h"
45
46/* send_ike_msg logic is broken into layers.
47 * The rest of the system thinks it is simple.
48 * We have three entrypoints that control options
49 * for reporting write failure and actions on resending (fragment?):
50 * send_ike_msg(), resend_ike_v1_msg(), and send_keepalive().
51 *
52 * The first two call send_or_resend_ike_msg().
53 * That handles an IKE message.
54 * It calls send_v1_frags() if the message needs to be fragmented.
55 * Otherwise it calls send_packet() to send it in one gulp.
56 *
57 * send_v1_frags() breaks an IKE message into fragments and sends
58 * them by send_packet().
59 *
60 * send_keepalive() calls send_packet() directly: uses a special
61 * tiny packet; non-ESP marker does not apply; logging on write error
62 * is suppressed.
63 *
64 * send_packet() sends a UDP packet, possibly prefixed by a non-ESP Marker
65 * for NATT. It accepts two chunks because this avoids double-copying.
66 */
67
68bool_Bool send_chunks(const char *where, bool_Bool just_a_keepalive,
69 so_serial_t serialno, /* can be SOS_NOBODY */
70 const struct iface_port *interface,
71 ip_address remote_endpoint,
72 chunk_t a, chunk_t b)
73{
74 /* NOTE: on system with limited stack, buf could be made static */
75 uint8_t buf[MAX_OUTPUT_UDP_SIZE65536];
76
77 /* Each fragment, if we are doing NATT, needs a non-ESP_Marker prefix.
78 * natt_bonus is the size of the addition (0 if not needed).
79 */
80 size_t natt_bonus;
81
82 if (interface == NULL((void*)0)) {
5
Assuming 'interface' is not equal to NULL
6
Taking false branch
83 libreswan_log("Cannot send packet - interface vanished!")loglog(RC_LOG, "Cannot send packet - interface vanished!");
84 return FALSE0;
85 }
86
87 /* bandaid */
88 if (a.ptr == NULL((void*)0)) {
7
Assuming the condition is false
8
Taking false branch
89 libreswan_log("Cannot send packet - a.ptr is NULL")loglog(RC_LOG, "Cannot send packet - a.ptr is NULL");
90 return FALSE0;
91 }
92
93 /*
94 * XXX:
95 *
96 * Isn't it a bit late to be checking for this? demux should
97 * have rejected a packet with a bogus remote address, and
98 * connection should have rejected a bogus address in a
99 * connection configuration?
100 *
101 * Code attempting to call this function with
102 * hsetportof(port,addr) where addr is invalid also get an
103 * expecation failed message.
104 */
105 if (isanyaddr(&remote_endpoint)) {
9
Assuming the condition is false
10
Taking false branch
106 /* not asserting, who knows what nonsense a user can generate */
107 endpoint_buf b;
108 libreswan_log("Will not send packet to bogus address %s",loglog(RC_LOG, "Will not send packet to bogus address %s", str_sensitive_endpoint
(&remote_endpoint, &b))
109 str_sensitive_endpoint(&remote_endpoint, &b))loglog(RC_LOG, "Will not send packet to bogus address %s", str_sensitive_endpoint
(&remote_endpoint, &b))
;
110 return FALSE0;
111 }
112
113 /*
114 * If we are doing NATT, so that the other end doesn't mistake
115 * this message for ESP, each message needs a non-ESP_Marker
116 * prefix. natt_bonus is the size of the addition (0 if not
117 * needed).
118 */
119 natt_bonus = !just_a_keepalive &&
12
'?' condition is true
120 interface->esp_encapsulation_enabled ?
11
Assuming the condition is true
121 NON_ESP_MARKER_SIZE4 : 0;
122
123 const uint8_t *ptr;
124 size_t len = natt_bonus + a.len + b.len;
125 ssize_t wlen;
126
127 if (len > MAX_OUTPUT_UDP_SIZE65536) {
13
Assuming 'len' is <= MAX_OUTPUT_UDP_SIZE
14
Taking false branch
128 loglog(RC_LOG_SERIOUS, "send_ike_msg(): really too big %zu bytes", len);
129 return FALSE0;
130 }
131
132 if (len != a.len) {
15
Assuming the condition is true
16
Taking true branch
133 /* copying required */
134
135 /* 1. non-ESP Marker (0x00 octets) */
136 memset(buf, 0x00, natt_bonus);
137
138 /* 2. chunk a */
139 memcpy(buf + natt_bonus, a.ptr, a.len);
140
141 /* 3. chunk b */
142 memcpy(buf + natt_bonus + a.len, b.ptr, b.len);
17
Null pointer passed as an argument to a 'nonnull' parameter
143
144 ptr = buf;
145 } else {
146 ptr = a.ptr;
147 }
148
149 if (DBGP(DBG_BASE)(cur_debugging & (((lset_t)1 << (DBG_BASE_IX))))) {
150 endpoint_buf lb;
151 endpoint_buf rb;
152 DBG_log("sending %zu bytes for %s through %s from %s to %s using %s (for #%lu)",
153 len, where,
154 interface->ip_dev->id_rname,
155 str_endpoint(&interface->local_endpoint, &lb),
156 str_endpoint(&remote_endpoint, &rb),
157 interface->protocol->name,
158 serialno);
159 DBG_dump(NULL((void*)0), ptr, len);
160 }
161
162 wlen = interface->io->write_packet(interface, ptr, len, &remote_endpoint);
163
164 if (wlen != (ssize_t)len) {
165 if (!just_a_keepalive) {
166 endpoint_buf lb;
167 endpoint_buf rb;
168 LOG_ERRNO(errno, "send on %s from %s to %s using %s failed in %s",{ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "send on %s from %s to %s using %s failed in %s", interface
->ip_dev->id_rname, str_endpoint(&interface->local_endpoint
, &lb), str_sensitive_endpoint(&remote_endpoint, &
rb), interface->protocol->name, where); jam_string(buf,
"."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream
(buf); } }
169 interface->ip_dev->id_rname,{ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "send on %s from %s to %s using %s failed in %s", interface
->ip_dev->id_rname, str_endpoint(&interface->local_endpoint
, &lb), str_sensitive_endpoint(&remote_endpoint, &
rb), interface->protocol->name, where); jam_string(buf,
"."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream
(buf); } }
170 str_endpoint(&interface->local_endpoint, &lb),{ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "send on %s from %s to %s using %s failed in %s", interface
->ip_dev->id_rname, str_endpoint(&interface->local_endpoint
, &lb), str_sensitive_endpoint(&remote_endpoint, &
rb), interface->protocol->name, where); jam_string(buf,
"."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream
(buf); } }
171 str_sensitive_endpoint(&remote_endpoint, &rb),{ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "send on %s from %s to %s using %s failed in %s", interface
->ip_dev->id_rname, str_endpoint(&interface->local_endpoint
, &lb), str_sensitive_endpoint(&remote_endpoint, &
rb), interface->protocol->name, where); jam_string(buf,
"."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream
(buf); } }
172 interface->protocol->name,{ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "send on %s from %s to %s using %s failed in %s", interface
->ip_dev->id_rname, str_endpoint(&interface->local_endpoint
, &lb), str_sensitive_endpoint(&remote_endpoint, &
rb), interface->protocol->name, where); jam_string(buf,
"."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream
(buf); } }
173 where){ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "send on %s from %s to %s using %s failed in %s", interface
->ip_dev->id_rname, str_endpoint(&interface->local_endpoint
, &lb), str_sensitive_endpoint(&remote_endpoint, &
rb), interface->protocol->name, where); jam_string(buf,
"."); jam(buf, " ""Errno %d: %s", (e_), strerror(e_)); jambuf_to_error_stream
(buf); } }
;
174 }
175 return FALSE0;
176 }
177
178 pstats_ike_out_bytes += len;
179
180 /* Send a duplicate packet when this impair is enabled - used for testing */
181 if (impair.jacob_two_two) {
182 /* sleep for half a second, and second another packet */
183 usleep(500000);
184 endpoint_buf b;
185 endpoint_buf ib;
186 DBG_log("JACOB 2-2: resending %zu bytes for %s through %s from %s to %s:",
187 len,
188 where,
189 interface->ip_dev->id_rname,
190 str_endpoint(&interface->local_endpoint, &ib),
191 str_endpoint(&remote_endpoint, &b));
192
193 ip_sockaddr remote_sa = sockaddr_from_endpoint(&remote_endpoint);
194 wlen = sendto(interface->fd, ptr, len, 0, &remote_sa.sa.sa, remote_sa.len);
195 if (wlen != (ssize_t)len) {
196 if (!just_a_keepalive) {
197 LOG_ERRNO(errno,{ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "sendto on %s to %s failed in %s", interface->ip_dev
->id_rname, str_endpoint(&remote_endpoint, &b), where
); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror
(e_)); jambuf_to_error_stream(buf); } }
198 "sendto on %s to %s failed in %s",{ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "sendto on %s to %s failed in %s", interface->ip_dev
->id_rname, str_endpoint(&remote_endpoint, &b), where
); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror
(e_)); jambuf_to_error_stream(buf); } }
199 interface->ip_dev->id_rname,{ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "sendto on %s to %s failed in %s", interface->ip_dev
->id_rname, str_endpoint(&remote_endpoint, &b), where
); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror
(e_)); jambuf_to_error_stream(buf); } }
200 str_endpoint(&remote_endpoint, &b),{ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "sendto on %s to %s failed in %s", interface->ip_dev
->id_rname, str_endpoint(&remote_endpoint, &b), where
); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror
(e_)); jambuf_to_error_stream(buf); } }
201 where){ int e_ = (*__errno_location ()); 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)) { jam(buf, "ERROR: "); jam_cur_prefix(buf); jam
(buf, "sendto on %s to %s failed in %s", interface->ip_dev
->id_rname, str_endpoint(&remote_endpoint, &b), where
); jam_string(buf, "."); jam(buf, " ""Errno %d: %s", (e_), strerror
(e_)); jambuf_to_error_stream(buf); } }
;
202 }
203 return FALSE0;
204 }
205 }
206 return TRUE1;
207}
208
209bool_Bool send_chunk(const char *where, so_serial_t serialno, /* can be SOS_NOBODY */
210 const struct iface_port *interface,
211 ip_address remote_endpoint, chunk_t packet)
212{
213 return send_chunks(where, FALSE0, serialno,
214 interface, remote_endpoint,
215 packet, EMPTY_CHUNK((const chunk_t) { .ptr = ((void*)0), .len = 0 }));
216}
217
218bool_Bool send_chunks_using_state(struct state *st, const char *where,
219 chunk_t a, chunk_t b)
220{
221 return send_chunks(where, FALSE0,
3
Null pointer value stored to 'b.ptr'
4
Calling 'send_chunks'
222 st->st_serialno, st->st_interface,
223 st->st_remote_endpoint, a, b);
224}
225
226bool_Bool send_chunk_using_state(struct state *st, const char *where, chunk_t packet)
227{
228 return send_chunks_using_state(st, where, packet, EMPTY_CHUNK((const chunk_t) { .ptr = ((void*)0), .len = 0 }));
2
Calling 'send_chunks_using_state'
229}
230
231bool_Bool send_ike_msg_without_recording(struct state *st, pb_stream *pbs,
232 const char *where)
233{
234 return send_chunk_using_state(st, where, same_out_pbs_as_chunk(pbs));
1
Calling 'send_chunk_using_state'
235}
236
237/*
238 * send keepalive is special in two ways:
239 * We don't want send errors logged (too noisy).
240 * We don't want the packet prefixed with a non-ESP Marker.
241 */
242bool_Bool send_keepalive(struct state *st, const char *where)
243{
244 static unsigned char ka_payload = 0xff;
245
246 return send_chunks(where, TRUE1,
247 st->st_serialno, st->st_interface,
248 st->st_remote_endpoint,
249 THING_AS_CHUNK(ka_payload)chunk2(&(ka_payload), sizeof(ka_payload)),
250 EMPTY_CHUNK((const chunk_t) { .ptr = ((void*)0), .len = 0 }));
251}