mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
Propagate correct error from more POSIX syscalls
This commit is contained in:
@@ -107,7 +107,7 @@ def ql_syscall_fcntl(ql: Qiling, fd: int, cmd: int, arg: int):
|
||||
f = get_opened_fd(ql.os, fd)
|
||||
|
||||
if f is None:
|
||||
return -1
|
||||
return -EBADF
|
||||
|
||||
if cmd == F_DUPFD:
|
||||
if arg not in range(NR_OPEN):
|
||||
@@ -137,7 +137,7 @@ def ql_syscall_fcntl(ql: Qiling, fd: int, cmd: int, arg: int):
|
||||
regreturn = 0
|
||||
|
||||
else:
|
||||
regreturn = -1
|
||||
regreturn = -EINVAL
|
||||
|
||||
return regreturn
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ def syscall_mmap_impl(ql: Qiling, addr: int, length: int, prot: int, flags: int,
|
||||
if flags & (mmap_flags.MAP_FIXED | mmap_flags.MAP_FIXED_NOREPLACE):
|
||||
# on non-QNX systems, base must be aligned to page boundary
|
||||
if addr & (pagesize - 1) and ql.os.type != QL_OS.QNX:
|
||||
return -1 # errno: EINVAL
|
||||
return -EINVAL
|
||||
|
||||
# if not, use the base address as a hint but always above or equal to
|
||||
# the value specified in /proc/sys/vm/mmap_min_addr (here: mmap_address)
|
||||
@@ -146,7 +146,7 @@ def syscall_mmap_impl(ql: Qiling, addr: int, length: int, prot: int, flags: int,
|
||||
|
||||
if flags & mmap_flags.MAP_FIXED_NOREPLACE:
|
||||
if not ql.mem.is_available(lbound, mapping_size):
|
||||
return -1 # errno: EEXIST
|
||||
return -EEXIST
|
||||
|
||||
elif flags & mmap_flags.MAP_FIXED:
|
||||
ql.log.debug(f'{api_name}: unmapping memory between {lbound:#x}-{ubound:#x} to make room for fixed mapping')
|
||||
@@ -164,12 +164,12 @@ def syscall_mmap_impl(ql: Qiling, addr: int, length: int, prot: int, flags: int,
|
||||
fd = ql.unpacks(ql.pack(fd))
|
||||
|
||||
if fd not in range(NR_OPEN):
|
||||
return -1 # errno: EBADF
|
||||
return -EBADF
|
||||
|
||||
f: Optional[ql_file] = ql.os.fd[fd]
|
||||
|
||||
if f is None:
|
||||
return -1 # errno: EBADF
|
||||
return -EBADF
|
||||
|
||||
# set mapping properties for future unmap
|
||||
f._is_map_shared = bool(flags & mmap_flags.MAP_SHARED)
|
||||
@@ -193,7 +193,7 @@ def syscall_mmap_impl(ql: Qiling, addr: int, length: int, prot: int, flags: int,
|
||||
ql.mem.map(lbound, mapping_size, info=label)
|
||||
except QlMemoryMappedError:
|
||||
ql.log.debug(f'{api_name}: out of memory')
|
||||
return -1 # errono: ENOMEM
|
||||
return -ENOMEM
|
||||
else:
|
||||
if data:
|
||||
ql.mem.write(addr, data)
|
||||
|
||||
@@ -40,7 +40,7 @@ def __perms(ql: Qiling, msq: QlMsqId, flag: int) -> int:
|
||||
|
||||
# is there some bit set in requested_mode but not in granted_mode?
|
||||
if request_mode & ~granted_mode & 0o007:
|
||||
return -1 # EACCES
|
||||
return -EACCES
|
||||
|
||||
return 0
|
||||
|
||||
@@ -53,7 +53,7 @@ def ql_syscall_msgget(ql: Qiling, key: int, msgflg: int):
|
||||
"""
|
||||
|
||||
if len(ql.os.msq) >= MSGMNI:
|
||||
return -1 # ENOSPC
|
||||
return -ENOSPC
|
||||
|
||||
mode = flags & ((1 << 9) - 1)
|
||||
|
||||
@@ -77,16 +77,16 @@ def ql_syscall_msgget(ql: Qiling, key: int, msgflg: int):
|
||||
msqid = __create_msq(key, msgflg)
|
||||
|
||||
else:
|
||||
return -1 # ENOENT
|
||||
return -ENOENT
|
||||
|
||||
# a message queue with the specified key exists
|
||||
else:
|
||||
# the user asked to create a new one?
|
||||
if msgflg & (IPC_CREAT | IPC_EXCL):
|
||||
return -1 # EEXIST
|
||||
return -EEXIST
|
||||
|
||||
if __perms(ql, msq, msgflg):
|
||||
return -1 # EACCES
|
||||
return -EACCES
|
||||
|
||||
return msqid
|
||||
|
||||
@@ -95,11 +95,11 @@ def ql_syscall_msgsnd(ql: Qiling, msqid: int, msgp: int, msgsz: int, msgflg: int
|
||||
msq = ql.os.msq.get_by_id(msqid)
|
||||
|
||||
if msq is None:
|
||||
return -1 # EINVAL
|
||||
return -EINVAL
|
||||
|
||||
# Check if the user has write permissions for the message queue
|
||||
if __perms(ql, msq, 0o222): # S_IWUGO
|
||||
return -1 # EACCES
|
||||
return -EACCES
|
||||
|
||||
msg_type = ql.mem.read_ptr(msgp)
|
||||
msg_text = ql.mem.read(msgp + ql.arch.pointersize, msgsz)
|
||||
@@ -109,7 +109,7 @@ def ql_syscall_msgsnd(ql: Qiling, msqid: int, msgp: int, msgsz: int, msgflg: int
|
||||
break
|
||||
|
||||
if msgflg & IPC_NOWAIT:
|
||||
return -1 # EAGAIN
|
||||
return -EAGAIN
|
||||
|
||||
msq.queue.append(QlMsgBuf(msg_type, bytes(msg_text)))
|
||||
|
||||
@@ -120,15 +120,15 @@ def ql_syscall_msgrcv(ql: Qiling, msqid: int, msgp: int, msgsz: int, msgtyp: int
|
||||
msq = ql.os.msq.get_by_id(msqid)
|
||||
|
||||
if msq is None:
|
||||
return -1 # EINVAL
|
||||
return -EINVAL
|
||||
|
||||
if msgflg & MSG_COPY:
|
||||
if msgflg & MSG_EXCEPT or not (msgflg & IPC_NOWAIT):
|
||||
return -1 # EINVAL
|
||||
return -EINVAL
|
||||
|
||||
# Check if the user has read permissions for the message queue
|
||||
if __perms(ql, msq, 0o444): # S_IRUGO
|
||||
return -1 # EACCES
|
||||
return -EACCES
|
||||
|
||||
while True:
|
||||
msg = __find_msg(msq, msgtyp, msgflg)
|
||||
@@ -137,17 +137,17 @@ def ql_syscall_msgrcv(ql: Qiling, msqid: int, msgp: int, msgsz: int, msgtyp: int
|
||||
break
|
||||
|
||||
if msgflg & MSG_COPY:
|
||||
return -1 # ENOMSG
|
||||
return -ENOMSG
|
||||
|
||||
if msgflg & IPC_NOWAIT:
|
||||
return -1 # ENOMSG
|
||||
return -ENOMSG
|
||||
|
||||
if not (msgflg & MSG_COPY):
|
||||
msq.queue.remove(msg)
|
||||
|
||||
if msgsz < len(msg.mtext):
|
||||
if not (msgflg & MSG_NOERROR):
|
||||
return -1 # E2BIG
|
||||
return -E2BIG
|
||||
else:
|
||||
sz = msgsz
|
||||
else:
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
from qiling import Qiling
|
||||
from qiling.arch.x86_const import IA32_FS_BASE_MSR, IA32_GS_BASE_MSR
|
||||
from qiling.os.posix.const import EINVAL
|
||||
|
||||
|
||||
def ql_syscall_arch_prctl(ql: Qiling, code: int, addr: int):
|
||||
@@ -29,7 +30,7 @@ def ql_syscall_arch_prctl(ql: Qiling, code: int, addr: int):
|
||||
if code not in handlers:
|
||||
ql.log.debug(f'prctl code {code:#x} not implemented')
|
||||
|
||||
return -1 # EINVAL
|
||||
return -EINVAL
|
||||
|
||||
handlers[code]()
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ def ql_syscall_shmget(ql: Qiling, key: int, size: int, shmflg: int):
|
||||
"""
|
||||
|
||||
if len(ql.os.shm) >= SHMMNI:
|
||||
return -1 # ENOSPC
|
||||
return -ENOSPC
|
||||
|
||||
mode = flags & ((1 << 9) - 1)
|
||||
|
||||
@@ -54,13 +54,13 @@ def ql_syscall_shmget(ql: Qiling, key: int, size: int, shmflg: int):
|
||||
shmid = __create_shm(key, size, shmflg)
|
||||
|
||||
else:
|
||||
return -1 # ENOENT
|
||||
return -ENOENT
|
||||
|
||||
# a shm with the specified key exists
|
||||
else:
|
||||
# the user asked to create a new one?
|
||||
if shmflg & (IPC_CREAT | IPC_EXCL):
|
||||
return -1 # EEXIST
|
||||
return -EEXIST
|
||||
|
||||
# check whether the user has permissions to access this shm
|
||||
# FIXME: should probably use ql.os.cuid instead, but we don't support it yet
|
||||
@@ -68,7 +68,7 @@ def ql_syscall_shmget(ql: Qiling, key: int, size: int, shmflg: int):
|
||||
return shmid
|
||||
|
||||
else:
|
||||
return -1 # EACCES
|
||||
return -EACCES
|
||||
|
||||
return shmid
|
||||
|
||||
@@ -78,7 +78,7 @@ def ql_syscall_shmat(ql: Qiling, shmid: int, shmaddr: int, shmflg: int):
|
||||
|
||||
# a shm with the specified key does not exist
|
||||
if shm is None:
|
||||
return -1 # EINVAL
|
||||
return -EINVAL
|
||||
|
||||
if shmaddr == 0:
|
||||
# system may choose any suitable page-aligned address
|
||||
@@ -100,7 +100,7 @@ def ql_syscall_shmat(ql: Qiling, shmid: int, shmaddr: int, shmflg: int):
|
||||
else:
|
||||
# shmaddr is expected to be aligned
|
||||
if shmaddr & (ql.mem.pagesize - 1):
|
||||
return -1 # EINVAL
|
||||
return -EINVAL
|
||||
|
||||
attaddr = shmaddr
|
||||
|
||||
@@ -114,11 +114,11 @@ def ql_syscall_shmat(ql: Qiling, shmid: int, shmaddr: int, shmflg: int):
|
||||
|
||||
# user asked to attached the seg as readable; is it allowed?
|
||||
if (perms & UC_PROT_READ) and not (shm.mode & SHM_R):
|
||||
return -1 # EACCES
|
||||
return -EACCES
|
||||
|
||||
# user asked to attached the seg as writable; is it allowed?
|
||||
if (perms & UC_PROT_WRITE) and not (shm.mode & SHM_W):
|
||||
return -1 # EACCES
|
||||
return -EACCES
|
||||
|
||||
# TODO: if segment is already attached, there is no need to map another memory for it.
|
||||
# if we do, data changes will not be reflected between the segment attachments. we could
|
||||
@@ -129,7 +129,7 @@ def ql_syscall_shmat(ql: Qiling, shmid: int, shmaddr: int, shmflg: int):
|
||||
# attach the segment at shmaddr
|
||||
ql.mem.map(attaddr, shm.segsz, perms, '[shm]')
|
||||
except QlMemoryMappedError:
|
||||
return -1 # EINVAL
|
||||
return -EINVAL
|
||||
|
||||
# track attachment
|
||||
shm.attach.append(attaddr)
|
||||
@@ -143,7 +143,7 @@ def ql_syscall_shmdt(ql: Qiling, shmaddr: int):
|
||||
shm = ql.os.shm.get_by_attaddr(shmaddr)
|
||||
|
||||
if shm is None:
|
||||
return -1 # EINVAL
|
||||
return -EINVAL
|
||||
|
||||
shm.attach.remove(shmaddr)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ def ql_syscall_ipc(ql: Qiling, call: int, first: int, second: int, third: int, p
|
||||
|
||||
def __call_shmat(*args: int) -> int:
|
||||
if version == 1:
|
||||
return -1 # EINVAL
|
||||
return -EINVAL
|
||||
|
||||
return ql_syscall_shmat(ql, args[0], args[3], args[1])
|
||||
|
||||
@@ -28,17 +28,17 @@ def ql_syscall_ipc(ql: Qiling, call: int, first: int, second: int, third: int, p
|
||||
|
||||
def __call_shmget(*args: int) -> int:
|
||||
return ql_syscall_shmget(ql, args[0], args[1], args[2])
|
||||
|
||||
|
||||
def __call_msgget(*args: int) -> int:
|
||||
return ql_syscall_msgget(ql, args[0], args[1])
|
||||
|
||||
def __call_msgsnd(*args: int) -> int:
|
||||
return ql_syscall_msgsnd(ql, args[0], args[3], args[1], args[2])
|
||||
|
||||
|
||||
def __call_msgrcv(*args: int) -> int:
|
||||
if version == 0:
|
||||
if args[3] == 0:
|
||||
return -1 # EINVAL
|
||||
return -EINVAL
|
||||
|
||||
msgp = ql.mem.read_ptr(args[3])
|
||||
msgtyp = ql.mem.read_ptr(args[3] + ql.arch.pointersize)
|
||||
@@ -59,7 +59,7 @@ def ql_syscall_ipc(ql: Qiling, call: int, first: int, second: int, third: int, p
|
||||
}
|
||||
|
||||
if call not in ipc_call:
|
||||
return -1 # ENOSYS
|
||||
return -ENOSYS
|
||||
|
||||
return ipc_call[call](first, second, third, ptr, fifth)
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ def ql_syscall_fsync(ql: Qiling, fd: int):
|
||||
f = get_opened_fd(ql.os, fd)
|
||||
|
||||
if f is None:
|
||||
regreturn = -1
|
||||
regreturn = -EBADF
|
||||
|
||||
else:
|
||||
try:
|
||||
@@ -257,7 +257,7 @@ def ql_syscall_faccessat(ql: Qiling, dirfd: int, filename: int, mode: int):
|
||||
if not ql.os.path.is_safe_host_path(hpath):
|
||||
raise PermissionError(f'unsafe path: {hpath}')
|
||||
|
||||
regreturn = 0 if os.path.exists(hpath) else -1
|
||||
regreturn = 0 if os.path.exists(hpath) else -ENOENT
|
||||
|
||||
ql.log.debug(f'faccessat({dirfd:d}, "{vpath}", {mode:d}) = {regreturn}')
|
||||
|
||||
@@ -270,7 +270,7 @@ def ql_syscall_lseek(ql: Qiling, fd: int, offset: int, origin: int):
|
||||
f = get_opened_fd(ql.os, fd)
|
||||
|
||||
if f is None:
|
||||
regreturn = -1
|
||||
regreturn = -EBADF
|
||||
|
||||
else:
|
||||
try:
|
||||
@@ -290,7 +290,7 @@ def ql_syscall__llseek(ql: Qiling, fd: int, offset_high: int, offset_low: int, r
|
||||
f = get_opened_fd(ql.os, fd)
|
||||
|
||||
if f is None:
|
||||
regreturn = -1
|
||||
regreturn = -EBADF
|
||||
|
||||
else:
|
||||
try:
|
||||
@@ -331,7 +331,7 @@ def ql_syscall_access(ql: Qiling, path: int, mode: int):
|
||||
if not ql.os.path.is_safe_host_path(hpath):
|
||||
raise PermissionError(f'unsafe path: {hpath}')
|
||||
|
||||
regreturn = 0 if os.path.exists(hpath) else -1
|
||||
regreturn = 0 if os.path.exists(hpath) else -ENOENT
|
||||
|
||||
ql.log.debug(f'access("{vpath}", 0{mode:o}) = {regreturn}')
|
||||
|
||||
@@ -342,7 +342,7 @@ def ql_syscall_close(ql: Qiling, fd: int):
|
||||
f = get_opened_fd(ql.os, fd)
|
||||
|
||||
if f is None:
|
||||
regreturn = -1
|
||||
regreturn = -EBADF
|
||||
|
||||
else:
|
||||
f.close()
|
||||
@@ -358,7 +358,7 @@ def ql_syscall_pread64(ql: Qiling, fd: int, buf: int, length: int, offt: int):
|
||||
f = get_opened_fd(ql.os, fd)
|
||||
|
||||
if f is None:
|
||||
regreturn = -1
|
||||
return -EBADF
|
||||
|
||||
else:
|
||||
# https://chromium.googlesource.com/linux-syscall-support/+/2c73abf02fd8af961e38024882b9ce0df6b4d19b
|
||||
@@ -386,7 +386,7 @@ def ql_syscall_read(ql: Qiling, fd, buf: int, length: int):
|
||||
f = get_opened_fd(ql.os, fd)
|
||||
|
||||
if f is None:
|
||||
return -1
|
||||
return -EBADF
|
||||
|
||||
try:
|
||||
data = f.read(length)
|
||||
@@ -404,7 +404,7 @@ def ql_syscall_write(ql: Qiling, fd: int, buf: int, count: int):
|
||||
f = get_opened_fd(ql.os, fd)
|
||||
|
||||
if f is None:
|
||||
return -1
|
||||
return -EBADF
|
||||
|
||||
try:
|
||||
data = ql.mem.read(buf, count)
|
||||
@@ -449,7 +449,7 @@ def __do_readlink(ql: Qiling, absvpath: str, outbuf: int) -> int:
|
||||
target = ''
|
||||
|
||||
if target is None:
|
||||
return -1
|
||||
return -ENOENT
|
||||
|
||||
cstr = target.encode('utf-8')
|
||||
|
||||
@@ -507,7 +507,7 @@ def ql_syscall_chdir(ql: Qiling, path_name: int):
|
||||
|
||||
regreturn = 0
|
||||
else:
|
||||
regreturn = -1
|
||||
regreturn = -ENOENT
|
||||
|
||||
ql.log.debug(f'chdir("{absvpath}") = {regreturn}')
|
||||
|
||||
@@ -634,7 +634,7 @@ def ql_syscall_dup(ql: Qiling, oldfd: int):
|
||||
f = get_opened_fd(ql.os, oldfd)
|
||||
|
||||
if f is None:
|
||||
return -1
|
||||
return -EBADF
|
||||
|
||||
newfd = next((i for i in range(NR_OPEN) if ql.os.fd[i] is None), -1)
|
||||
|
||||
@@ -652,10 +652,10 @@ def ql_syscall_dup2(ql: Qiling, oldfd: int, newfd: int):
|
||||
f = get_opened_fd(ql.os, oldfd)
|
||||
|
||||
if f is None:
|
||||
return -1
|
||||
return -EBADF
|
||||
|
||||
if newfd not in range(NR_OPEN):
|
||||
return -1
|
||||
return -EBADF
|
||||
|
||||
newslot = ql.os.fd[newfd]
|
||||
|
||||
@@ -675,10 +675,10 @@ def ql_syscall_dup3(ql: Qiling, oldfd: int, newfd: int, flags: int):
|
||||
f = get_opened_fd(ql.os, oldfd)
|
||||
|
||||
if f is None:
|
||||
return -1
|
||||
return -EBADF
|
||||
|
||||
if newfd not in range(NR_OPEN):
|
||||
return -1
|
||||
return -EBADF
|
||||
|
||||
newslot = ql.os.fd[newfd]
|
||||
|
||||
@@ -714,7 +714,7 @@ def ql_syscall_pipe(ql: Qiling, pipefd: int):
|
||||
idx2 = next(unpopulated_fd, -1)
|
||||
|
||||
if (idx1 == -1) or (idx2 == -1):
|
||||
return -1
|
||||
return -EMFILE
|
||||
|
||||
ql.os.fd[idx1] = rd
|
||||
ql.os.fd[idx2] = wd
|
||||
@@ -769,7 +769,7 @@ def ql_syscall_truncate(ql: Qiling, path: int, length: int):
|
||||
def ql_syscall_ftruncate(ql: Qiling, fd: int, length: int):
|
||||
f = get_opened_fd(ql.os, fd)
|
||||
|
||||
regreturn = -1 if f is None else __do_truncate(ql, f.name, length)
|
||||
regreturn = -EBADF if f is None else __do_truncate(ql, f.name, length)
|
||||
|
||||
ql.log.debug(f'ftruncate({fd}, {length:#x}) = {regreturn}')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user