summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Knegjens <rob@knegjens.net>2022-04-06 10:56:28 -0700
committerDamien George <damien@micropython.org>2022-04-11 15:15:04 +1000
commitd3d862769ad9f1317702b921dda1912d9a673948 (patch)
tree17a9666b2fb50cb7355eee19b26986e120268835
parent56978c3dde3440367438a89353ba73b32c8cdbc2 (diff)
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.
-rw-r--r--docs/reference/mpremote.rst9
-rw-r--r--tools/mpremote/mpremote/main.py17
-rw-r--r--tools/mpremote/mpremote/pyboardextended.py15
3 files changed, 33 insertions, 8 deletions
diff --git a/docs/reference/mpremote.rst b/docs/reference/mpremote.rst
index 727431fcf..2bbed56b8 100644
--- a/docs/reference/mpremote.rst
+++ b/docs/reference/mpremote.rst
@@ -133,13 +133,20 @@ The full list of supported commands are:
.. code-block:: bash
- $ mpremote mount <local-dir>
+ $ mpremote mount [options] <local-dir>
During usage, Ctrl-D will soft-reboot and normally reconnect the mount automatically.
If the unit has a main.py running at startup however the remount cannot occur.
In this case a raw mode soft reboot can be used: Ctrl-A Ctrl-D to reboot,
then Ctrl-B to get back to normal repl at which point the mount will be ready.
+ Options are:
+
+ - ``-l``, ``--unsafe-links``: By default an error will be raised if the device
+ accesses a file or directory which is outside (up one or more directory levels) the
+ local directory that is mounted. This option disables this check for symbolic
+ links, allowing the device to follow symbolic links outside of the local directory.
+
- unmount the local directory from the remote device:
.. code-block:: bash
diff --git a/tools/mpremote/mpremote/main.py b/tools/mpremote/mpremote/main.py
index 50ad73cc1..ccf174bb5 100644
--- a/tools/mpremote/mpremote/main.py
+++ b/tools/mpremote/mpremote/main.py
@@ -41,7 +41,16 @@ _COMMANDS = {
"disconnect": (False, False, 0, "disconnect current device"),
"resume": (False, False, 0, "resume a previous mpremote session (will not auto soft-reset)"),
"soft-reset": (False, True, 0, "perform a soft-reset of the device"),
- "mount": (True, False, 1, "mount local directory on device"),
+ "mount": (
+ True,
+ False,
+ 1,
+ """\
+ mount local directory on device
+ options:
+ --unsafe-links, -l
+ follow symbolic links pointing outside of local directory""",
+ ),
"umount": (True, False, 0, "unmount the local directory"),
"repl": (
False,
@@ -516,8 +525,12 @@ def main():
pyb.enter_raw_repl(soft_reset=True)
auto_soft_reset = False
elif cmd == "mount":
+ unsafe_links = False
+ if args[0] == "--unsafe-links" or args[0] == "-l":
+ args.pop(0)
+ unsafe_links = True
path = args.pop(0)
- pyb.mount_local(path)
+ pyb.mount_local(path, unsafe_links=unsafe_links)
print(f"Local directory {path} is mounted at /remote")
elif cmd == "umount":
pyb.umount_local()
diff --git a/tools/mpremote/mpremote/pyboardextended.py b/tools/mpremote/mpremote/pyboardextended.py
index ccdb37a0c..d3b4cb6d8 100644
--- a/tools/mpremote/mpremote/pyboardextended.py
+++ b/tools/mpremote/mpremote/pyboardextended.py
@@ -351,12 +351,13 @@ fs_hook_code = re.sub("buf4", "b4", fs_hook_code)
class PyboardCommand:
- def __init__(self, fin, fout, path):
+ def __init__(self, fin, fout, path, unsafe_links=False):
self.fin = fin
self.fout = fout
self.root = path + "/"
self.data_ilistdir = ["", []]
self.data_files = []
+ self.unsafe_links = unsafe_links
def rd_s8(self):
return struct.unpack("<b", self.fin.read(1))[0]
@@ -397,8 +398,12 @@ class PyboardCommand:
print(f"[{msg}]", end="\r\n")
def path_check(self, path):
- parent = os.path.realpath(self.root)
- child = os.path.realpath(path)
+ if not self.unsafe_links:
+ parent = os.path.realpath(self.root)
+ child = os.path.realpath(path)
+ else:
+ parent = os.path.abspath(self.root)
+ child = os.path.abspath(path)
if parent != os.path.commonpath([parent, child]):
raise OSError(EPERM, "") # File is outside mounted dir
@@ -612,13 +617,13 @@ class PyboardExtended(Pyboard):
self.device_name = dev
self.mounted = False
- def mount_local(self, path):
+ def mount_local(self, path, unsafe_links=False):
fout = self.serial
if self.eval('"RemoteFS" in globals()') == b"False":
self.exec_(fs_hook_code)
self.exec_("__mount()")
self.mounted = True
- self.cmd = PyboardCommand(self.serial, fout, path)
+ self.cmd = PyboardCommand(self.serial, fout, path, unsafe_links=unsafe_links)
self.serial = SerialIntercept(self.serial, self.cmd)
def write_ctrl_d(self, out_callback):