1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2019 Isilon Systems, LLC.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28/*
29 * netgdb.c
30 * FreeBSD subsystem supporting debugging the FreeBSD kernel over the network.
31 *
32 * There are three pieces necessary to use NetGDB.
33 *
34 * First, a dedicated proxy server must be running to accept connections from
35 * both NetGDB and gdb(1), and pass bidirectional traffic between the two
36 * protocols.
37 *
38 * Second, The NetGDB client is activated much like ordinary 'gdb' and
39 * similarly to 'netdump' in ddb(4).  Like other debugnet(4) clients
40 * (netdump(4)), the network interface on the route to the proxy server must be
41 * online and support debugnet(4).
42 *
43 * Finally, the remote (k)gdb(1) uses 'target remote <proxy>:<port>' to connect
44 * to the proxy server.
45 *
46 * NetGDBv1 speaks the literal GDB remote serial protocol, and uses a 1:1
47 * relationship between GDB packets and plain debugnet packets.  There is no
48 * encryption utilized to keep debugging sessions private, so this is only
49 * appropriate for local segments or trusted networks.
50 */
51
52#include <sys/cdefs.h>
53#include "opt_ddb.h"
54#ifndef DDB
55#error "NetGDB cannot be used without DDB at this time"
56#endif
57
58#include <sys/errno.h>
59#include <sys/param.h>
60#include <sys/kdb.h>
61#include <sys/sbuf.h>
62#include <sys/socket.h>
63#include <sys/sysctl.h>
64#include <sys/ttydefaults.h>
65
66#include <machine/gdb_machdep.h>
67
68#ifdef DDB
69#include <ddb/ddb.h>
70#include <ddb/db_command.h>
71#include <ddb/db_lex.h>
72#endif
73
74#include <net/debugnet.h>
75#include <net/if.h>
76#include <net/if_var.h>
77#include <net/route.h>
78
79#include <gdb/gdb.h>
80#include <gdb/gdb_int.h>
81#include <gdb/netgdb.h>
82
83FEATURE(netgdb, "NetGDB support");
84SYSCTL_NODE(_debug_gdb, OID_AUTO, netgdb, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
85    "NetGDB parameters");
86
87static unsigned netgdb_debug;
88SYSCTL_UINT(_debug_gdb_netgdb, OID_AUTO, debug, CTLFLAG_RWTUN,
89    &netgdb_debug, 0,
90    "Debug message verbosity (0: off; 1: on)");
91
92#define	NETGDB_DEBUG(f, ...) do {						\
93	if (netgdb_debug > 0)							\
94		printf(("%s [%s:%d]: " f), __func__, __FILE__, __LINE__, ##	\
95		    __VA_ARGS__);						\
96} while (false)
97
98static void netgdb_fini(void);
99
100/* Runtime state. */
101static char netgdb_rxbuf[GDB_BUFSZ + 16];	/* Some overhead for framing. */
102static struct sbuf netgdb_rxsb;
103static ssize_t netgdb_rx_off;
104
105static struct debugnet_pcb *netgdb_conn;
106static struct gdb_dbgport *netgdb_prev_dbgport;
107static int *netgdb_prev_kdb_inactive;
108
109/* TODO(CEM) disable ack mode */
110
111/*
112 * Attempt to accept the incoming packet. If we run into ENOBUFS or another
113 * error, return it.
114 *
115 * The mbuf chain will have all framing headers removed (ethernet, inet, udp,
116 * debugnet).
117 */
118static int
119netgdb_rx(struct mbuf *m)
120{
121	uint32_t rlen, count;
122
123	rlen = m->m_pkthdr.len;
124#define	_SBUF_FREESPACE(s)	((s)->s_size - ((s)->s_len + 1))
125	if (_SBUF_FREESPACE(&netgdb_rxsb) < rlen) {
126		NETGDB_DEBUG("Backpressure: Not ACKing RX of packet that "
127		    "would overflow our buffer (%zd/%zd used).\n",
128		    netgdb_rxsb.s_len, netgdb_rxsb.s_size);
129		return (ENOBUFS);
130	}
131#undef _SBUF_FREESPACE
132
133	/*
134	 * Inlined m_apply -- why isn't there a macro or inline function
135	 * version?
136	 */
137	while (m != NULL && m->m_len == 0)
138		m = m->m_next;
139	while (rlen > 0) {
140		MPASS(m != NULL && m->m_len >= 0);
141		count = min((uint32_t)m->m_len, rlen);
142		(void)sbuf_bcat(&netgdb_rxsb, mtod(m, const void *), count);
143		rlen -= count;
144		m = m->m_next;
145	}
146	return (0);
147}
148
149static void
150netgdb_finish(void)
151{
152	sbuf_putc(&netgdb_rxsb, CTRL('C'));
153}
154
155/*
156 * The following routines implement a pseudo GDB debugport (an emulated serial
157 * driver that the MI gdb(4) code does I/O with).
158 */
159
160static int
161netgdb_dbg_getc(void)
162{
163	int c;
164
165	while (true) {
166		/* Pull bytes off any currently cached packet first. */
167		if (netgdb_rx_off < sbuf_len(&netgdb_rxsb)) {
168			c = netgdb_rxsb.s_buf[netgdb_rx_off];
169			netgdb_rx_off++;
170			break;
171		}
172
173		/* Reached EOF?  Reuse buffer. */
174		sbuf_clear(&netgdb_rxsb);
175		netgdb_rx_off = 0;
176
177		/* Check for CTRL-C on console/serial, if any. */
178		if (netgdb_prev_dbgport != NULL) {
179			c = netgdb_prev_dbgport->gdb_getc();
180			if (c == CTRL('C'))
181				break;
182		}
183
184		debugnet_network_poll(netgdb_conn);
185	}
186
187	if (c == CTRL('C')) {
188		netgdb_fini();
189		/* Caller gdb_getc() will print that we got ^C. */
190	}
191	return (c);
192}
193
194static void
195netgdb_dbg_sendpacket(const void *buf, size_t len)
196{
197	struct debugnet_proto_aux aux;
198	int error;
199
200	MPASS(len <= UINT32_MAX);
201
202	/*
203	 * GDB packet boundaries matter.  debugnet_send() fragments a single
204	 * request into many sequential debugnet messages.  Mark full packet
205	 * length and offset for potential reassembly by the proxy.
206	 */
207	aux = (struct debugnet_proto_aux) {
208		.dp_aux2 = len,
209	};
210
211	error = debugnet_send(netgdb_conn, DEBUGNET_DATA, buf, len, &aux);
212	if (error != 0) {
213		printf("%s: Network error: %d; trying to switch back to ddb.\n",
214		    __func__, error);
215		netgdb_fini();
216
217		if (kdb_dbbe_select("ddb") != 0)
218			printf("The ddb backend could not be selected.\n");
219		else {
220			printf("using longjmp, hope it works!\n");
221			kdb_reenter();
222		}
223	}
224
225}
226
227/* Just used for + / - GDB-level ACKs. */
228static void
229netgdb_dbg_putc(int i)
230{
231	char c;
232
233	c = i;
234	netgdb_dbg_sendpacket(&c, 1);
235
236}
237
238static struct gdb_dbgport netgdb_gdb_dbgport = {
239	.gdb_name = "netgdb",
240	.gdb_getc = netgdb_dbg_getc,
241	.gdb_putc = netgdb_dbg_putc,
242	.gdb_term = netgdb_fini,
243	.gdb_sendpacket = netgdb_dbg_sendpacket,
244	.gdb_dbfeatures = GDB_DBGP_FEAT_WANTTERM | GDB_DBGP_FEAT_RELIABLE,
245};
246
247static void
248netgdb_init(void)
249{
250	struct kdb_dbbe *be, **iter;
251
252	/*
253	 * Force enable GDB.  (If no other debugports were registered at boot,
254	 * KDB thinks it doesn't exist.)
255	 */
256	SET_FOREACH(iter, kdb_dbbe_set) {
257		be = *iter;
258		if (strcmp(be->dbbe_name, "gdb") != 0)
259			continue;
260		if (be->dbbe_active == -1) {
261			netgdb_prev_kdb_inactive = &be->dbbe_active;
262			be->dbbe_active = 0;
263		}
264		break;
265	}
266
267	/* Force netgdb debugport. */
268	netgdb_prev_dbgport = gdb_cur;
269	gdb_cur = &netgdb_gdb_dbgport;
270
271	sbuf_new(&netgdb_rxsb, netgdb_rxbuf, sizeof(netgdb_rxbuf),
272	    SBUF_FIXEDLEN);
273	netgdb_rx_off = 0;
274}
275
276static void
277netgdb_fini(void)
278{
279
280	/* TODO: tear down conn gracefully? */
281	if (netgdb_conn != NULL) {
282		debugnet_free(netgdb_conn);
283		netgdb_conn = NULL;
284	}
285
286	sbuf_delete(&netgdb_rxsb);
287
288	gdb_cur = netgdb_prev_dbgport;
289
290	if (netgdb_prev_kdb_inactive != NULL) {
291		*netgdb_prev_kdb_inactive = -1;
292		netgdb_prev_kdb_inactive = NULL;
293	}
294}
295
296#ifdef DDB
297/*
298 * Usage: netgdb -s <server> [-g <gateway -c <localip> -i <interface>]
299 *
300 * Order is not significant.
301 *
302 * Currently, this command does not support configuring encryption or
303 * compression.
304 */
305DB_COMMAND_FLAGS(netgdb, db_netgdb_cmd, CS_OWN)
306{
307	struct debugnet_ddb_config params;
308	struct debugnet_conn_params dcp;
309	struct debugnet_pcb *pcb;
310	char proxy_buf[INET_ADDRSTRLEN];
311	int error;
312
313	if (!KERNEL_PANICKED()) {
314		/* TODO: This limitation should be removed in future work. */
315		printf("%s: netgdb is currently limited to use only after a "
316		    "panic.  Sorry.\n", __func__);
317		return;
318	}
319
320	error = debugnet_parse_ddb_cmd("netgdb", &params);
321	if (error != 0) {
322		db_printf("Error configuring netgdb: %d\n", error);
323		return;
324	}
325
326	/*
327	 * Must initialize netgdb_rxsb before debugnet_connect(), because we
328	 * might be getting rx handler callbacks from the send->poll path
329	 * during debugnet_connect().
330	 */
331	netgdb_init();
332
333	if (!params.dd_has_client)
334		params.dd_client = INADDR_ANY;
335	if (!params.dd_has_gateway)
336		params.dd_gateway = INADDR_ANY;
337
338	dcp = (struct debugnet_conn_params) {
339		.dc_ifp = params.dd_ifp,
340		.dc_client = params.dd_client,
341		.dc_server = params.dd_server,
342		.dc_gateway = params.dd_gateway,
343		.dc_herald_port = NETGDB_HERALDPORT,
344		.dc_client_port = NETGDB_CLIENTPORT,
345		.dc_herald_aux2 = NETGDB_PROTO_V1,
346		.dc_rx_handler = netgdb_rx,
347		.dc_finish_handler = netgdb_finish,
348	};
349
350	error = debugnet_connect(&dcp, &pcb);
351	if (error != 0) {
352		printf("failed to contact netgdb server: %d\n", error);
353		netgdb_fini();
354		return;
355	}
356
357	netgdb_conn = pcb;
358
359	if (kdb_dbbe_select("gdb") != 0) {
360		db_printf("The remote GDB backend could not be selected.\n");
361		netgdb_fini();
362		return;
363	}
364
365	/*
366	 * Mark that we are done in ddb(4).  Return -> kdb_trap() should
367	 * re-enter with the new backend.
368	 */
369	db_cmd_loop_done = 1;
370	gdb_return_to_ddb = true;
371	db_printf("(detaching GDB will return control to DDB)\n");
372
373	const in_addr_t *proxy_addr = debugnet_get_server_addr(netgdb_conn);
374	const uint16_t proxy_port = debugnet_get_server_port(netgdb_conn) + 1;
375	inet_ntop(AF_INET, proxy_addr, proxy_buf, sizeof(proxy_buf));
376	if (inet_ntop(AF_INET, proxy_addr, proxy_buf, sizeof(proxy_buf)) == NULL) {
377		db_printf("Connected to proxy. "
378		    "Use target remote <proxy address>:%hu to begin debugging.\n",
379		    proxy_port);
380	} else {
381		db_printf("Connected to proxy. "
382		    "Use target remote %s:%hu to begin debugging.\n",
383		    proxy_buf, proxy_port);
384	}
385#if 0
386	/* Aspirational, but does not work reliably. */
387	db_printf("(ctrl-c will return control to ddb)\n");
388#endif
389}
390#endif /* DDB */
391