From 601d30f37299056586003b819176a73a1fceffe9 Mon Sep 17 00:00:00 2001 From: Sh3idan Date: Thu, 19 Dec 2019 08:29:33 +0100 Subject: [PATCH 1/4] add check if path is already in sandbox + debug log messages --- miasm/os_dep/linux/environment.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/miasm/os_dep/linux/environment.py b/miasm/os_dep/linux/environment.py index 4d24e85a2..953e8cdbf 100644 --- a/miasm/os_dep/linux/environment.py +++ b/miasm/os_dep/linux/environment.py @@ -216,6 +216,13 @@ def __init__(self, base_path, linux_env): def resolve_path(self, path, follow_link=True): """Resolve @path to the corresponding sandboxed path""" + log.debug( + "resolve_path(path={!r}, follow_link={!r})".format( + path, + follow_link + ) + ) + # path_bytes is used for Python 2 / Python 3 compatibility path_bytes = not isinstance(path, str) path_sep = os.path.sep.encode() if path_bytes else os.path.sep @@ -276,12 +283,17 @@ def _convert_re(expr): elif _convert(passthrough) == path: return path - # Remove leading '/' if any - path = path.lstrip(path_sep) - base_path = os.path.abspath(_convert(self.base_path)) - out_path = os.path.join(base_path, path) + + if path.startswith(base_path): + out_path = path + else: + # Remove leading '/' if any + path = path.lstrip(path_sep) + out_path = os.path.join(base_path, path) + assert out_path.startswith(base_path + path_sep) + if os.path.islink(out_path): link_target = os.readlink(out_path) # Link can be absolute or relative -> absolute @@ -290,6 +302,9 @@ def _convert_re(expr): out_path = self.resolve_path(link) else: out_path = link + + log.debug("-> {!r}".format(out_path)) + return out_path def get_path_inode(self, real_path): From a9690a42acf51756594527f6aad943bfcb17cc64 Mon Sep 17 00:00:00 2001 From: Sh3idan Date: Thu, 19 Dec 2019 08:48:48 +0100 Subject: [PATCH 2/4] move assert before the return value --- miasm/os_dep/linux/environment.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miasm/os_dep/linux/environment.py b/miasm/os_dep/linux/environment.py index 953e8cdbf..64a43d085 100644 --- a/miasm/os_dep/linux/environment.py +++ b/miasm/os_dep/linux/environment.py @@ -292,7 +292,6 @@ def _convert_re(expr): path = path.lstrip(path_sep) out_path = os.path.join(base_path, path) - assert out_path.startswith(base_path + path_sep) if os.path.islink(out_path): link_target = os.readlink(out_path) @@ -303,6 +302,8 @@ def _convert_re(expr): else: out_path = link + assert out_path.startswith(base_path + path_sep) + log.debug("-> {!r}".format(out_path)) return out_path From e9768f0852531f29a439aa83ac2620debc410f17 Mon Sep 17 00:00:00 2001 From: Sh3idan Date: Thu, 19 Dec 2019 12:39:52 +0100 Subject: [PATCH 3/4] resolve_path only translate a path to a sandboxed path + readlink is reading link --- miasm/os_dep/linux/environment.py | 35 ++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/miasm/os_dep/linux/environment.py b/miasm/os_dep/linux/environment.py index 64a43d085..e292a02ad 100644 --- a/miasm/os_dep/linux/environment.py +++ b/miasm/os_dep/linux/environment.py @@ -293,19 +293,13 @@ def _convert_re(expr): out_path = os.path.join(base_path, path) - if os.path.islink(out_path): - link_target = os.readlink(out_path) - # Link can be absolute or relative -> absolute - link = os.path.normpath(os.path.join(os.path.dirname(path), link_target)) - if follow_link: - out_path = self.resolve_path(link) - else: - out_path = link + if os.path.islink(out_path) and follow_link: + target = self.readlink(out_path) + out_path = self.resolve_path(target) assert out_path.startswith(base_path + path_sep) log.debug("-> {!r}".format(out_path)) - return out_path def get_path_inode(self, real_path): @@ -317,10 +311,27 @@ def exists(self, path): return os.path.exists(sb_path) def readlink(self, path): - sb_path = self.resolve_path(path, follow_link=False) - if not os.path.islink(sb_path): + log.debug("readlink({!r})".format(path)) + + # check if path is a link + if not os.path.islink(path): + log.debug("-> {!r} is not a link".format(path)) return None - return os.readlink(sb_path) + + # resolve path (link name) + sb_link_name = self.resolve_path(path, follow_link=False) + + # get target + target = os.readlink(sb_link_name) + + # Link can be absolute or relative -> absolute + target = os.path.normpath(os.path.join(os.path.dirname(sb_link_name), target)) + + # resolve target + sb_target = self.resolve_path(target, follow_link=False) + + log.debug("-> {!r}".format(sb_target)) + return sb_target def statfs(self): return StatFSInfo( From 025923d5deb5086b30a850842011de428e0c40dc Mon Sep 17 00:00:00 2001 From: Sh3idan Date: Thu, 19 Dec 2019 14:54:01 +0100 Subject: [PATCH 4/4] sys_x86_64_readlink: fix concatenation between str and bytes --- miasm/os_dep/linux/syscall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/os_dep/linux/syscall.py b/miasm/os_dep/linux/syscall.py index ca631fc8d..6ec81ff39 100644 --- a/miasm/os_dep/linux/syscall.py +++ b/miasm/os_dep/linux/syscall.py @@ -707,7 +707,7 @@ def sys_x86_64_readlink(jitter, linux_env): # Not a link jitter.cpu.RAX = -1 else: - data = link[:bufsize - 1] + b"\x00" + data = link[:bufsize - 1].encode() + b"\x00" jitter.vm.set_mem(buf, data) jitter.cpu.RAX = len(data) - 1