diff --git a/qiling/os/filestruct.py b/qiling/os/filestruct.py index c57bbc54..511f505a 100644 --- a/qiling/os/filestruct.py +++ b/qiling/os/filestruct.py @@ -30,10 +30,7 @@ class ql_file: def open(cls, path: AnyStr, flags: int, mode: int, dir_fd: Optional[int] = None): mode &= 0x7fffffff - try: - fd = os.open(path, flags, mode, dir_fd=dir_fd) - except OSError as e: - raise QlSyscallError(e.errno, e.args[1] + ' : ' + e.filename) + fd = os.open(path, flags, mode, dir_fd=dir_fd) return cls(path, fd) diff --git a/qiling/os/posix/syscall/fcntl.py b/qiling/os/posix/syscall/fcntl.py index 5b1f2a9c..900f93d1 100644 --- a/qiling/os/posix/syscall/fcntl.py +++ b/qiling/os/posix/syscall/fcntl.py @@ -33,8 +33,14 @@ def __do_open(ql: Qiling, absvpath: str, flags: int, mode: int) -> int: try: ql.os.fd[idx] = ql.os.fs_mapper.open_ql_file(absvpath, flags, mode) - except QlSyscallError: - return -1 + except FileNotFoundError: + return -ENOENT + except FileExistsError: + return -EEXIST + except IsADirectoryError: + return -EISDIR + except PermissionError: + return -EACCES return idx @@ -54,7 +60,7 @@ def ql_syscall_openat(ql: Qiling, fd: int, path: int, flags: int, mode: int): vpath = ql.os.utils.read_cstring(path) absvpath = virtual_abspath_at(ql, vpath, fd) - regreturn = -1 if absvpath is None else __do_open(ql, absvpath, flags, mode) + regreturn = absvpath if isinstance(absvpath, int) else __do_open(ql, absvpath, flags, mode) ql.log.debug(f'openat({fd:d}, "{vpath}", {flags:#x}, 0{mode:o}) = {regreturn:d}') diff --git a/qiling/os/posix/syscall/unistd.py b/qiling/os/posix/syscall/unistd.py index 3c9b9147..74e41bd1 100644 --- a/qiling/os/posix/syscall/unistd.py +++ b/qiling/os/posix/syscall/unistd.py @@ -201,7 +201,16 @@ def ql_syscall_fdatasync(ql: Qiling, fd: int): return regreturn -def virtual_abspath_at(ql: Qiling, vpath: str, dirfd: int) -> Optional[str]: +def virtual_abspath_at(ql: Qiling, vpath: str, dirfd: int) -> Union[int, str]: + """Resolve the virtual absolute path based on the specified dirfd. + + Args: + vpath: relative virtual path to resolve + dirfd: base directory file descriptor + + Returns: the resolved absolute path, or an error code if could not resolve it + """ + if ql.os.path.is_virtual_abspath(vpath): return vpath @@ -223,14 +232,12 @@ def virtual_abspath_at(ql: Qiling, vpath: str, dirfd: int) -> Optional[str]: f = get_opened_fd(ql.os, dirfd) if f is None or not hasattr(f, 'name'): - # EBADF - return None + return -EBADF hpath = f.name if not os.path.isdir(hpath): - # ENOTDIR - return None + return -ENOTDIR basedir = ql.os.path.host_to_virtual_path(hpath) @@ -241,8 +248,8 @@ def ql_syscall_faccessat(ql: Qiling, dirfd: int, filename: int, mode: int): vpath = ql.os.utils.read_cstring(filename) vpath_at = virtual_abspath_at(ql, vpath, dirfd) - if vpath_at is None: - regreturn = -1 + if isinstance(vpath_at, int): + regreturn = vpath_at else: hpath = ql.os.path.virtual_to_host_path(vpath_at) @@ -467,7 +474,7 @@ def ql_syscall_readlinkat(ql: Qiling, dirfd: int, pathname: int, buf: int, bufsi vpath = ql.os.utils.read_cstring(pathname) absvpath = virtual_abspath_at(ql, vpath, dirfd) - regreturn = -1 if absvpath is None else __do_readlink(ql, absvpath, buf) + regreturn = absvpath if isinstance(absvpath, int) else __do_readlink(ql, absvpath, buf) ql.log.debug(f'readlinkat({dirfd:d}, "{vpath}", {buf:#x}, {bufsize:#x}) = {regreturn}') @@ -821,7 +828,7 @@ def ql_syscall_unlinkat(ql: Qiling, dirfd: int, pathname: int, flags: int): vpath = ql.os.utils.read_cstring(pathname) absvpath = virtual_abspath_at(ql, vpath, dirfd) - regreturn = -1 if absvpath is None else __do_unlink(ql, absvpath) + regreturn = absvpath if isinstance(absvpath, int) else __do_unlink(ql, absvpath) ql.log.debug(f'unlinkat({dirfd}, "{vpath}") = {regreturn}') diff --git a/tests/test_elf_multithread.py b/tests/test_elf_multithread.py index cefc8264..be48773f 100644 --- a/tests/test_elf_multithread.py +++ b/tests/test_elf_multithread.py @@ -64,8 +64,8 @@ class ELFTest(unittest.TestCase): os.remove(filename) self.assertGreaterEqual(len(contents), 4) - self.assertIn('Operation not permitted', contents[-2]) - self.assertIn('Operation not permitted', contents[-1]) + self.assertIn('Bad file descriptor', contents[-2]) + self.assertIn('Bad file descriptor', contents[-1]) def test_multithread_elf_linux_x86(self): logged: List[str] = []