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 83 FEATURE(netgdb, "NetGDB support"); 84 SYSCTL_NODE(_debug_gdb, OID_AUTO, netgdb, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 85 "NetGDB parameters"); 86 87 static unsigned netgdb_debug; 88 SYSCTL_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 98 static void netgdb_fini(void); 99 100 /* Runtime state. */ 101 static char netgdb_rxbuf[GDB_BUFSZ + 16]; /* Some overhead for framing. */ 102 static struct sbuf netgdb_rxsb; 103 static ssize_t netgdb_rx_off; 104 105 static struct debugnet_pcb *netgdb_conn; 106 static struct gdb_dbgport *netgdb_prev_dbgport; 107 static 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 */ 118 static int 119 netgdb_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 149 static void 150 netgdb_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 160 static int 161 netgdb_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 194 static void 195 netgdb_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. */ 228 static void 229 netgdb_dbg_putc(int i) 230 { 231 char c; 232 233 c = i; 234 netgdb_dbg_sendpacket(&c, 1); 235 236 } 237 238 static 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 247 static void 248 netgdb_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 276 static void 277 netgdb_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 */ 305 DB_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", ¶ms); 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