diff --git a/miasm/os_dep/linux/environment.py b/miasm/os_dep/linux/environment.py index 4d24e85a2..e292a02ad 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,20 +283,23 @@ 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) + + + 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) - 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 + + log.debug("-> {!r}".format(out_path)) return out_path def get_path_inode(self, real_path): @@ -301,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( 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