Skip to content

Commit d3d8627

Browse files
rknegjensdpgeorge
authored andcommitted
tools/mpremote: Add option to mount cmd to allow "unsafe" symlinks.
Specifying the option `--unsafe-links` (or `-l`) to `mpremote mount` will allow symlinks to be followed in the local directory that point outside of the base directory path. For the unsafe case the `path_check()` method of `PyboardCommand` still checks for a common path but without expanding symlinks. While this check is currently redundant, it makes the purpose of the method clearer for possible future uses or extensions.
1 parent 56978c3 commit d3d8627

3 files changed

Lines changed: 33 additions & 8 deletions

File tree

docs/reference/mpremote.rst

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,20 @@ The full list of supported commands are:
133133

134134
.. code-block:: bash
135135
136-
$ mpremote mount <local-dir>
136+
$ mpremote mount [options] <local-dir>
137137
138138
During usage, Ctrl-D will soft-reboot and normally reconnect the mount automatically.
139139
If the unit has a main.py running at startup however the remount cannot occur.
140140
In this case a raw mode soft reboot can be used: Ctrl-A Ctrl-D to reboot,
141141
then Ctrl-B to get back to normal repl at which point the mount will be ready.
142142

143+
Options are:
144+
145+
- ``-l``, ``--unsafe-links``: By default an error will be raised if the device
146+
accesses a file or directory which is outside (up one or more directory levels) the
147+
local directory that is mounted. This option disables this check for symbolic
148+
links, allowing the device to follow symbolic links outside of the local directory.
149+
143150
- unmount the local directory from the remote device:
144151

145152
.. code-block:: bash

tools/mpremote/mpremote/main.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,16 @@
4141
"disconnect": (False, False, 0, "disconnect current device"),
4242
"resume": (False, False, 0, "resume a previous mpremote session (will not auto soft-reset)"),
4343
"soft-reset": (False, True, 0, "perform a soft-reset of the device"),
44-
"mount": (True, False, 1, "mount local directory on device"),
44+
"mount": (
45+
True,
46+
False,
47+
1,
48+
"""\
49+
mount local directory on device
50+
options:
51+
--unsafe-links, -l
52+
follow symbolic links pointing outside of local directory""",
53+
),
4554
"umount": (True, False, 0, "unmount the local directory"),
4655
"repl": (
4756
False,
@@ -516,8 +525,12 @@ def main():
516525
pyb.enter_raw_repl(soft_reset=True)
517526
auto_soft_reset = False
518527
elif cmd == "mount":
528+
unsafe_links = False
529+
if args[0] == "--unsafe-links" or args[0] == "-l":
530+
args.pop(0)
531+
unsafe_links = True
519532
path = args.pop(0)
520-
pyb.mount_local(path)
533+
pyb.mount_local(path, unsafe_links=unsafe_links)
521534
print(f"Local directory {path} is mounted at /remote")
522535
elif cmd == "umount":
523536
pyb.umount_local()

tools/mpremote/mpremote/pyboardextended.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,12 +351,13 @@ def __mount():
351351

352352

353353
class PyboardCommand:
354-
def __init__(self, fin, fout, path):
354+
def __init__(self, fin, fout, path, unsafe_links=False):
355355
self.fin = fin
356356
self.fout = fout
357357
self.root = path + "/"
358358
self.data_ilistdir = ["", []]
359359
self.data_files = []
360+
self.unsafe_links = unsafe_links
360361

361362
def rd_s8(self):
362363
return struct.unpack("<b", self.fin.read(1))[0]
@@ -397,8 +398,12 @@ def log_cmd(self, msg):
397398
print(f"[{msg}]", end="\r\n")
398399

399400
def path_check(self, path):
400-
parent = os.path.realpath(self.root)
401-
child = os.path.realpath(path)
401+
if not self.unsafe_links:
402+
parent = os.path.realpath(self.root)
403+
child = os.path.realpath(path)
404+
else:
405+
parent = os.path.abspath(self.root)
406+
child = os.path.abspath(path)
402407
if parent != os.path.commonpath([parent, child]):
403408
raise OSError(EPERM, "") # File is outside mounted dir
404409

@@ -612,13 +617,13 @@ def __init__(self, dev, *args, **kwargs):
612617
self.device_name = dev
613618
self.mounted = False
614619

615-
def mount_local(self, path):
620+
def mount_local(self, path, unsafe_links=False):
616621
fout = self.serial
617622
if self.eval('"RemoteFS" in globals()') == b"False":
618623
self.exec_(fs_hook_code)
619624
self.exec_("__mount()")
620625
self.mounted = True
621-
self.cmd = PyboardCommand(self.serial, fout, path)
626+
self.cmd = PyboardCommand(self.serial, fout, path, unsafe_links=unsafe_links)
622627
self.serial = SerialIntercept(self.serial, self.cmd)
623628

624629
def write_ctrl_d(self, out_callback):

0 commit comments

Comments
 (0)