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.
pull/8439/head
Rob Knegjens 2022-04-06 10:56:28 -07:00 zatwierdzone przez Damien George
rodzic 56978c3dde
commit d3d862769a
3 zmienionych plików z 33 dodań i 8 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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()

Wyświetl plik

@ -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):