1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 __FBSDID("$FreeBSD$"); 54 55 #include "opt_ddb.h" 56 #ifndef DDB 57 #error "NetGDB cannot be used without DDB at this time" 58 #endif 59 60 #include <sys/param.h> 61 #include <sys/kdb.h> 62 #include <sys/sbuf.h> 63 #include <sys/socket.h> 64 #include <sys/sysctl.h> 65 #include <sys/ttydefaults.h> 66 67 #include <machine/gdb_machdep.h> 68 69 #ifdef DDB 70 #include <ddb/ddb.h> 71 #include <ddb/db_command.h> 72 #include <ddb/db_lex.h> 73 #endif 74 75 #include <net/debugnet.h> 76 #include <net/if.h> 77 #include <net/if_var.h> 78 #include <net/route.h> 79 80 #include <gdb/gdb.h> 81 #include <gdb/gdb_int.h> 82 #include <gdb/netgdb.h> 83 84 FEATURE(netgdb, "NetGDB support"); 85 SYSCTL_NODE(_debug_gdb, OID_AUTO, netgdb, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 86 "NetGDB parameters"); 87 88 static unsigned netgdb_debug; 89 SYSCTL_UINT(_debug_gdb_netgdb, OID_AUTO, debug, CTLFLAG_RWTUN, 90 &netgdb_debug, 0, 91 "Debug message verbosity (0: off; 1: on)"); 92 93 #define NETGDB_DEBUG(f, ...) do { \ 94 if (netgdb_debug > 0) \ 95 printf(("%s [%s:%d]: " f), __func__, __FILE__, __LINE__, ## \ 96 __VA_ARGS__); \ 97 } while (false) 98 99 static void netgdb_fini(void); 100 101 /* Runtime state. */ 102 static char netgdb_rxbuf[GDB_BUFSZ + 16]; /* Some overhead for framing. */ 103 static struct sbuf netgdb_rxsb; 104 static ssize_t netgdb_rx_off; 105 106 static struct debugnet_pcb *netgdb_conn; 107 static struct gdb_dbgport *netgdb_prev_dbgport; 108 static int *netgdb_prev_kdb_inactive; 109 110 /* TODO(CEM) disable ack mode */ 111 112 /* 113 * Receive non-TX ACK packets on the client port. 114 * 115 * The mbuf chain will have all non-debugnet framing headers removed 116 * (ethernet, inet, udp). It will start with a debugnet_msg_hdr, of 117 * which the header is guaranteed to be contiguous. If m_pullup is 118 * used, the supplied in-out mbuf pointer should be updated 119 * appropriately. 120 * 121 * If the handler frees the mbuf chain, it should set the mbuf pointer 122 * to NULL. Otherwise, the debugnet input framework will free the 123 * chain. 124 */ 125 static void 126 netgdb_rx(struct debugnet_pcb *pcb, struct mbuf **mb) 127 { 128 const struct debugnet_msg_hdr *dnh; 129 struct mbuf *m; 130 uint32_t rlen, count; 131 int error; 132 133 m = *mb; 134 dnh = mtod(m, const void *); 135 136 if (ntohl(dnh->mh_type) == DEBUGNET_FINISHED) { 137 sbuf_putc(&netgdb_rxsb, CTRL('C')); 138 return; 139 } 140 141 if (ntohl(dnh->mh_type) != DEBUGNET_DATA) { 142 printf("%s: Got unexpected debugnet message %u\n", 143 __func__, ntohl(dnh->mh_type)); 144 return; 145 } 146 147 rlen = ntohl(dnh->mh_len); 148 #define _SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len + 1)) 149 if (_SBUF_FREESPACE(&netgdb_rxsb) < rlen) { 150 NETGDB_DEBUG("Backpressure: Not ACKing RX of packet that " 151 "would overflow our buffer (%zd/%zd used).\n", 152 netgdb_rxsb.s_len, netgdb_rxsb.s_size); 153 return; 154 } 155 #undef _SBUF_FREESPACE 156 157 error = debugnet_ack_output(pcb, dnh->mh_seqno); 158 if (error != 0) { 159 printf("%s: Couldn't ACK rx packet %u; %d\n", __func__, 160 ntohl(dnh->mh_seqno), error); 161 /* 162 * Sender will re-xmit, and assuming the condition is 163 * transient, we'll process the packet's contentss later. 164 */ 165 return; 166 } 167 168 m_adj(m, sizeof(*dnh)); 169 dnh = NULL; 170 171 /* 172 * Inlined m_apply -- why isn't there a macro or inline function 173 * version? 174 */ 175 while (m != NULL && m->m_len == 0) 176 m = m->m_next; 177 while (rlen > 0) { 178 MPASS(m != NULL && m->m_len >= 0); 179 count = min((uint32_t)m->m_len, rlen); 180 (void)sbuf_bcat(&netgdb_rxsb, mtod(m, const void *), count); 181 rlen -= count; 182 m = m->m_next; 183 } 184 } 185 186 /* 187 * The following routines implement a pseudo GDB debugport (an emulated serial 188 * driver that the MI gdb(4) code does I/O with). 189 */ 190 191 static int 192 netgdb_dbg_getc(void) 193 { 194 int c; 195 196 while (true) { 197 /* Pull bytes off any currently cached packet first. */ 198 if (netgdb_rx_off < sbuf_len(&netgdb_rxsb)) { 199 c = netgdb_rxsb.s_buf[netgdb_rx_off]; 200 netgdb_rx_off++; 201 break; 202 } 203 204 /* Reached EOF? Reuse buffer. */ 205 sbuf_clear(&netgdb_rxsb); 206 netgdb_rx_off = 0; 207 208 /* Check for CTRL-C on console/serial, if any. */ 209 if (netgdb_prev_dbgport != NULL) { 210 c = netgdb_prev_dbgport->gdb_getc(); 211 if (c == CTRL('C')) 212 break; 213 } 214 215 debugnet_network_poll(netgdb_conn); 216 } 217 218 if (c == CTRL('C')) { 219 netgdb_fini(); 220 /* Caller gdb_getc() will print that we got ^C. */ 221 } 222 return (c); 223 } 224 225 static void 226 netgdb_dbg_sendpacket(const void *buf, size_t len) 227 { 228 struct debugnet_proto_aux aux; 229 int error; 230 231 MPASS(len <= UINT32_MAX); 232 233 /* 234 * GDB packet boundaries matter. debugnet_send() fragments a single 235 * request into many sequential debugnet messages. Mark full packet 236 * length and offset for potential reassembly by the proxy. 237 */ 238 aux = (struct debugnet_proto_aux) { 239 .dp_aux2 = len, 240 }; 241 242 error = debugnet_send(netgdb_conn, DEBUGNET_DATA, buf, len, &aux); 243 if (error != 0) { 244 printf("%s: Network error: %d; trying to switch back to ddb.\n", 245 __func__, error); 246 netgdb_fini(); 247 248 if (kdb_dbbe_select("ddb") != 0) 249 printf("The ddb backend could not be selected.\n"); 250 else { 251 printf("using longjmp, hope it works!\n"); 252 kdb_reenter(); 253 } 254 } 255 256 } 257 258 /* Just used for + / - GDB-level ACKs. */ 259 static void 260 netgdb_dbg_putc(int i) 261 { 262 char c; 263 264 c = i; 265 netgdb_dbg_sendpacket(&c, 1); 266 267 } 268 269 static struct gdb_dbgport netgdb_gdb_dbgport = { 270 .gdb_name = "netgdb", 271 .gdb_getc = netgdb_dbg_getc, 272 .gdb_putc = netgdb_dbg_putc, 273 .gdb_term = netgdb_fini, 274 .gdb_sendpacket = netgdb_dbg_sendpacket, 275 .gdb_dbfeatures = GDB_DBGP_FEAT_WANTTERM | GDB_DBGP_FEAT_RELIABLE, 276 }; 277 278 static void 279 netgdb_init(void) 280 { 281 struct kdb_dbbe *be, **iter; 282 283 /* 284 * Force enable GDB. (If no other debugports were registered at boot, 285 * KDB thinks it doesn't exist.) 286 */ 287 SET_FOREACH(iter, kdb_dbbe_set) { 288 be = *iter; 289 if (strcmp(be->dbbe_name, "gdb") != 0) 290 continue; 291 if (be->dbbe_active == -1) { 292 netgdb_prev_kdb_inactive = &be->dbbe_active; 293 be->dbbe_active = 0; 294 } 295 break; 296 } 297 298 /* Force netgdb debugport. */ 299 netgdb_prev_dbgport = gdb_cur; 300 gdb_cur = &netgdb_gdb_dbgport; 301 302 sbuf_new(&netgdb_rxsb, netgdb_rxbuf, sizeof(netgdb_rxbuf), 303 SBUF_FIXEDLEN); 304 netgdb_rx_off = 0; 305 } 306 307 static void 308 netgdb_fini(void) 309 { 310 311 /* TODO: tear down conn gracefully? */ 312 if (netgdb_conn != NULL) { 313 debugnet_free(netgdb_conn); 314 netgdb_conn = NULL; 315 } 316 317 sbuf_delete(&netgdb_rxsb); 318 319 gdb_cur = netgdb_prev_dbgport; 320 321 if (netgdb_prev_kdb_inactive != NULL) { 322 *netgdb_prev_kdb_inactive = -1; 323 netgdb_prev_kdb_inactive = NULL; 324 } 325 } 326 327 #ifdef DDB 328 /* 329 * Usage: netgdb -s <server> [-g <gateway -c <localip> -i <interface>] 330 * 331 * Order is not significant. 332 * 333 * Currently, this command does not support configuring encryption or 334 * compression. 335 */ 336 DB_FUNC(netgdb, db_netgdb_cmd, db_cmd_table, CS_OWN, NULL) 337 { 338 struct debugnet_ddb_config params; 339 struct debugnet_conn_params dcp; 340 struct debugnet_pcb *pcb; 341 int error; 342 343 if (!KERNEL_PANICKED()) { 344 /* TODO: This limitation should be removed in future work. */ 345 printf("%s: netgdb is currently limited to use only after a " 346 "panic. Sorry.\n", __func__); 347 return; 348 } 349 350 error = debugnet_parse_ddb_cmd("netgdb", ¶ms); 351 if (error != 0) { 352 db_printf("Error configuring netgdb: %d\n", error); 353 return; 354 } 355 356 /* 357 * Must initialize netgdb_rxsb before debugnet_connect(), because we 358 * might be getting rx handler callbacks from the send->poll path 359 * during debugnet_connect(). 360 */ 361 netgdb_init(); 362 363 if (!params.dd_has_client) 364 params.dd_client = INADDR_ANY; 365 if (!params.dd_has_gateway) 366 params.dd_gateway = INADDR_ANY; 367 368 dcp = (struct debugnet_conn_params) { 369 .dc_ifp = params.dd_ifp, 370 .dc_client = params.dd_client, 371 .dc_server = params.dd_server, 372 .dc_gateway = params.dd_gateway, 373 .dc_herald_port = NETGDB_HERALDPORT, 374 .dc_client_port = NETGDB_CLIENTPORT, 375 .dc_herald_aux2 = NETGDB_PROTO_V1, 376 .dc_rx_handler = netgdb_rx, 377 }; 378 379 error = debugnet_connect(&dcp, &pcb); 380 if (error != 0) { 381 printf("failed to contact netgdb server: %d\n", error); 382 netgdb_fini(); 383 return; 384 } 385 386 netgdb_conn = pcb; 387 388 if (kdb_dbbe_select("gdb") != 0) { 389 db_printf("The remote GDB backend could not be selected.\n"); 390 netgdb_fini(); 391 return; 392 } 393 394 /* 395 * Mark that we are done in ddb(4). Return -> kdb_trap() should 396 * re-enter with the new backend. 397 */ 398 db_cmd_loop_done = 1; 399 gdb_return_to_ddb = true; 400 db_printf("(detaching GDB will return control to DDB)\n"); 401 #if 0 402 /* Aspirational, but does not work reliably. */ 403 db_printf("(ctrl-c will return control to ddb)\n"); 404 #endif 405 } 406 #endif /* DDB */ 407