Propagate correct error from path-related POSIX syscalls

This commit is contained in:
elicn
2024-07-02 21:01:44 +03:00
committed by Eli
parent bdda8e8c10
commit 9196ea019e
4 changed files with 28 additions and 18 deletions
+1 -4
View File
@@ -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)
+9 -3
View File
@@ -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}')
+16 -9
View File
@@ -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}')
+2 -2
View File
@@ -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] = []