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.
This commit is contained in:
parent
56978c3dde
commit
d3d862769a
@ -133,13 +133,20 @@ The full list of supported commands are:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. 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.
|
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.
|
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,
|
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.
|
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:
|
- unmount the local directory from the remote device:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
@ -41,7 +41,16 @@ _COMMANDS = {
|
|||||||
"disconnect": (False, False, 0, "disconnect current device"),
|
"disconnect": (False, False, 0, "disconnect current device"),
|
||||||
"resume": (False, False, 0, "resume a previous mpremote session (will not auto soft-reset)"),
|
"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"),
|
"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"),
|
"umount": (True, False, 0, "unmount the local directory"),
|
||||||
"repl": (
|
"repl": (
|
||||||
False,
|
False,
|
||||||
@ -516,8 +525,12 @@ def main():
|
|||||||
pyb.enter_raw_repl(soft_reset=True)
|
pyb.enter_raw_repl(soft_reset=True)
|
||||||
auto_soft_reset = False
|
auto_soft_reset = False
|
||||||
elif cmd == "mount":
|
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)
|
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")
|
print(f"Local directory {path} is mounted at /remote")
|
||||||
elif cmd == "umount":
|
elif cmd == "umount":
|
||||||
pyb.umount_local()
|
pyb.umount_local()
|
||||||
|
@ -351,12 +351,13 @@ fs_hook_code = re.sub("buf4", "b4", fs_hook_code)
|
|||||||
|
|
||||||
|
|
||||||
class PyboardCommand:
|
class PyboardCommand:
|
||||||
def __init__(self, fin, fout, path):
|
def __init__(self, fin, fout, path, unsafe_links=False):
|
||||||
self.fin = fin
|
self.fin = fin
|
||||||
self.fout = fout
|
self.fout = fout
|
||||||
self.root = path + "/"
|
self.root = path + "/"
|
||||||
self.data_ilistdir = ["", []]
|
self.data_ilistdir = ["", []]
|
||||||
self.data_files = []
|
self.data_files = []
|
||||||
|
self.unsafe_links = unsafe_links
|
||||||
|
|
||||||
def rd_s8(self):
|
def rd_s8(self):
|
||||||
return struct.unpack("<b", self.fin.read(1))[0]
|
return struct.unpack("<b", self.fin.read(1))[0]
|
||||||
@ -397,8 +398,12 @@ class PyboardCommand:
|
|||||||
print(f"[{msg}]", end="\r\n")
|
print(f"[{msg}]", end="\r\n")
|
||||||
|
|
||||||
def path_check(self, path):
|
def path_check(self, path):
|
||||||
|
if not self.unsafe_links:
|
||||||
parent = os.path.realpath(self.root)
|
parent = os.path.realpath(self.root)
|
||||||
child = os.path.realpath(path)
|
child = os.path.realpath(path)
|
||||||
|
else:
|
||||||
|
parent = os.path.abspath(self.root)
|
||||||
|
child = os.path.abspath(path)
|
||||||
if parent != os.path.commonpath([parent, child]):
|
if parent != os.path.commonpath([parent, child]):
|
||||||
raise OSError(EPERM, "") # File is outside mounted dir
|
raise OSError(EPERM, "") # File is outside mounted dir
|
||||||
|
|
||||||
@ -612,13 +617,13 @@ class PyboardExtended(Pyboard):
|
|||||||
self.device_name = dev
|
self.device_name = dev
|
||||||
self.mounted = False
|
self.mounted = False
|
||||||
|
|
||||||
def mount_local(self, path):
|
def mount_local(self, path, unsafe_links=False):
|
||||||
fout = self.serial
|
fout = self.serial
|
||||||
if self.eval('"RemoteFS" in globals()') == b"False":
|
if self.eval('"RemoteFS" in globals()') == b"False":
|
||||||
self.exec_(fs_hook_code)
|
self.exec_(fs_hook_code)
|
||||||
self.exec_("__mount()")
|
self.exec_("__mount()")
|
||||||
self.mounted = True
|
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)
|
self.serial = SerialIntercept(self.serial, self.cmd)
|
||||||
|
|
||||||
def write_ctrl_d(self, out_callback):
|
def write_ctrl_d(self, out_callback):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user