Skip to content

Commit df605c7

Browse files
authored
Merge pull request #1021 from flit/bugfix/server_security
Default probe server to local only, plus associated cleanup.
2 parents 18252c8 + 6c3c7c8 commit df605c7

File tree

8 files changed

+36
-24
lines changed

8 files changed

+36
-24
lines changed

docs/options.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,15 @@ Whether to resume a halted target when disconnecting.
254254
Controls whether all 256 ADIv5 AP addresses will be probed.
255255
</td></tr>
256256

257+
<tr><td>serve_local_only</td>
258+
<td>bool</td>
259+
<td>True</td>
260+
<td>
261+
When this option is True, the GDB server, probe server, semihosting telnet, and raw SWV server are only served
262+
on localhost, making them inaccessible across the network. Set to False to enable connecting to these ports
263+
from any machine on the network.
264+
</td></tr>
265+
257266
<tr><td>smart_flash</td>
258267
<td>bool</td>
259268
<td>True</td>
@@ -372,15 +381,6 @@ Whether to use GDB syscalls for semihosting file access operations, or to have p
372381
operations. This is most useful if GDB is running on a remote system.
373382
</td></tr>
374383

375-
<tr><td>serve_local_only</td>
376-
<td>bool</td>
377-
<td>True</td>
378-
<td>
379-
When this option is True, the GDB server and semihosting telnet ports are only served on localhost,
380-
making them inaccessible across the network. If False, you can connect to these ports from any
381-
machine that is on the same network.
382-
</td></tr>
383-
384384
<tr><td>step_into_interrupt</td>
385385
<td>bool</td>
386386
<td>False</td>

pyocd/__main__.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -348,10 +348,13 @@ def build_parser(self):
348348
help="Send setting to DAPAccess layer.")
349349
serverParser.add_argument("-p", "--port", dest="port_number", type=int, default=None,
350350
help="Set the server's port number (default 5555).")
351-
serverParser.add_argument("--local-only", dest="serve_local_only", default=False, action="store_true",
352-
help="Allow remote TCP/IP connections (default is yes).")
351+
serverParser.add_argument("--allow-remote", dest="serve_local_only", default=None, action="store_false",
352+
help="Allow remote TCP/IP connections (default is no).")
353+
serverParser.add_argument("--local-only", default=False, action="store_true",
354+
help="Ignored and deprecated. Server is local only by default. Use --alow-remote to enable remote "
355+
"connections.")
353356
serverParser.add_argument("-u", "--uid", dest="unique_id",
354-
help="Serve only the specified probe. Can be used multiple times.")
357+
help="Serve the specified probe.")
355358
serverParser.set_defaults(verbose=0, quiet=0)
356359

357360
self._parser = parser
@@ -882,7 +885,9 @@ def do_server(self):
882885
# probe, we don't set it in the session because we don't want the board, target, etc objects
883886
# to be created.
884887
session_options = convert_session_options(self._args.options)
885-
session = Session(probe=None, options=session_options)
888+
session = Session(probe=None,
889+
serve_local_only=self._args.serve_local_only,
890+
options=session_options)
886891

887892
# The ultimate intent is to serve all available probes by default. For now we just serve
888893
# a single probe.

pyocd/core/options.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@
9191
"Whether to run target on disconnect."),
9292
OptionInfo('scan_all_aps', bool, False,
9393
"Controls whether all 256 ADIv5 AP addresses will be probed. Default is False."),
94+
OptionInfo('serve_local_only', bool, True,
95+
"When this option is True, the GDB server, probe server, and semihosting telnet, and raw SWV "
96+
"server are only served on localhost. Set to False to enable remote connections."),
9497
OptionInfo('smart_flash', bool, True,
9598
"If set to True, the flash loader will attempt to not program pages whose contents are not "
9699
"going to change by scanning target flash memory. A value of False will force all pages to "
@@ -127,9 +130,6 @@
127130
"semihosting will print to the console."),
128131
OptionInfo('semihost_use_syscalls', bool, False,
129132
"Whether to use GDB syscalls for semihosting file access operations."),
130-
OptionInfo('serve_local_only', bool, True,
131-
"When this option is True, the GDB server and semihosting telnet ports are only served on "
132-
"localhost."),
133133
OptionInfo('step_into_interrupt', bool, False,
134134
"Enable interrupts when performing step operations."),
135135
OptionInfo('swv_clock', int, 1000000,

pyocd/gdbserver/gdbserver.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,9 @@ def __init__(self, session, core=None):
167167
self.first_run_after_reset_or_flash = True
168168

169169
self.abstract_socket = ListenerSocket(self.port, self.packet_size)
170-
if self.serve_local_only:
171-
self.abstract_socket.host = 'localhost'
170+
if not self.serve_local_only:
171+
# We really should be binding to explicit interfaces, not all available.
172+
self.abstract_socket.host = ''
172173
self.abstract_socket.init()
173174
# Read back bound port in case auto-assigned (port 0)
174175
self.port = self.abstract_socket.port

pyocd/probe/tcp_probe_server.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class DebugProbeServer(threading.Thread):
3939
can be terminated by calling the stop() method, which will also kill the server thread.
4040
"""
4141

42-
def __init__(self, session, probe, port=None, serve_local_only=True):
42+
def __init__(self, session, probe, port=None, serve_local_only=None):
4343
"""! @brief Constructor.
4444
4545
@param self The object.
@@ -52,8 +52,8 @@ def __init__(self, session, probe, port=None, serve_local_only=True):
5252
@ref pyocd.probe.shared_probe_proxy.SharedDebugProbeProxy "SharedDebugProbeProxy"
5353
then a new proxy is created to allow the probe to be shared by multiple connections.
5454
@param port The TCP port number. Defaults to the 'probeserver.port' option if not provided.
55-
@param serve_local_only Boolean. Whether to restrict the server to be accessible only from
56-
localhost.
55+
@param serve_local_only Optional Boolean. Whether to restrict the server to be accessible only from
56+
localhost. If not specified (set to None), then the 'serve_local_only' session option is used.
5757
"""
5858
super(DebugProbeServer, self).__init__()
5959

@@ -78,6 +78,10 @@ def __init__(self, session, probe, port=None, serve_local_only=True):
7878
else:
7979
self._port = port
8080

81+
# Default to the serve_local_only session option.
82+
if serve_local_only is None:
83+
serve_local_only = session.options.get('serve_local_only')
84+
8185
host = 'localhost' if serve_local_only else ''
8286
address = (host, self._port)
8387

pyocd/trace/swv.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ def run(self):
159159

160160
swv_raw_server = StreamServer(
161161
self._session.options.get('swv_raw_port'),
162+
serve_local_only=self._session.options.get('serve_local_only'),
162163
name="SWV raw",
163164
is_read_only=True) \
164165
if self._session.options.get('swv_raw_enable') else None

pyocd/utility/server.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ def __init__(self, port, serve_local_only=True, name=None, is_read_only=True, ex
5656
self._is_read_only = is_read_only
5757
self._abstract_socket = None
5858
self._abstract_socket = ListenerSocket(port, 4096)
59-
if serve_local_only:
60-
self._abstract_socket.host = 'localhost'
59+
if not serve_local_only:
60+
# We really should be binding to explicit interfaces, not all available.
61+
self._abstract_socket.host = ''
6162
self._abstract_socket.init()
6263
self._port = self._abstract_socket.port
6364
self._buffer = bytearray()

pyocd/utility/sockets.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def __init__(self, port, packet_size):
2424
self.listener = None
2525
self.conn = None
2626
self.port = port
27-
self.host = ''
27+
self.host = 'localhost'
2828

2929
def init(self):
3030
if self.listener is None:

0 commit comments

Comments
 (0)