Skip to content

Commit cb875f8

Browse files
author
xwings
committed
more qiling style. update logging and exception
1 parent 2f16ccc commit cb875f8

5 files changed

Lines changed: 31 additions & 26 deletions

File tree

qiling/exception.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ class QlMemoryMappedError(QlErrorBase):
7474
class QlGDTError(QlErrorBase):
7575
pass
7676

77+
class QlProxyConnectionError(QlErrorBase):
78+
pass
79+
7780
class QlSyscallError(QlErrorBase):
7881
def __init__(self, errno, msg):
7982
super(QlSyscallError, self).__init__(msg)

qiling/os/posix/kernel_proxy/__init__.py

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,16 @@
2424
import sys
2525
import socket
2626
import subprocess
27-
import logging
28-
from typing import Optional, TYPE_CHECKING
27+
from typing import Dict, Optional, TYPE_CHECKING
2928

3029
from qiling.const import QL_INTERCEPT, QL_OS
30+
from qiling.exception import QlErrorArch, QlErrorSyscallError, QlErrorSyscallNotFound
3131
from qiling.os.posix.kernel_proxy.ipc import ProxyClient
3232
from qiling.os.posix.kernel_proxy.proxy_fd import ql_proxy_fd
3333

3434
if TYPE_CHECKING:
3535
from qiling import Qiling
3636

37-
log = logging.getLogger(__name__)
38-
3937

4038
class KernelProxy:
4139
"""Forward specific syscalls to a real Linux kernel via a helper process.
@@ -46,13 +44,13 @@ class KernelProxy:
4644

4745
def __init__(self, ql: Qiling):
4846
if sys.platform != 'linux':
49-
raise RuntimeError("KernelProxy requires a Linux host")
47+
raise QlErrorArch("KernelProxy requires a Linux host")
5048

5149
self.ql = ql
5250
self._process: Optional[subprocess.Popen] = None
5351
self._client: Optional[ProxyClient] = None
54-
self._forwarded: dict = {} # name -> syscall_nr
55-
self._reverse_table: Optional[dict] = None # name -> nr (built on first use)
52+
self._forwarded: Dict[str, int] = {} # name -> syscall_nr
53+
self._reverse_table: Optional[Dict[str, int]] = None # name -> nr (built on first use)
5654

5755
self._start_proxy()
5856

@@ -78,14 +76,13 @@ def _start_proxy(self):
7876
child_sock.close()
7977

8078
self._client = ProxyClient(parent_sock)
81-
log.info(f"kernel proxy started (pid={self._process.pid})")
79+
self.ql.log.info(f"kernel proxy started (pid={self._process.pid})")
8280

83-
def _build_reverse_table(self) -> dict:
81+
def _build_reverse_table(self) -> Dict[str, int]:
8482
"""Build name -> syscall_nr mapping from the guest architecture's syscall table."""
8583
if self._reverse_table is not None:
8684
return self._reverse_table
8785

88-
from qiling.os.linux.map_syscall import get_syscall_mapper
8986
from qiling.const import QL_ARCH
9087

9188
# get the raw syscall table dict for this architecture
@@ -102,7 +99,7 @@ def _build_reverse_table(self) -> dict:
10299

103100
table_name = arch_tables.get(self.ql.arch.type)
104101
if table_name is None:
105-
raise RuntimeError(f"KernelProxy: unsupported architecture {self.ql.arch.type}")
102+
raise QlErrorArch(f"KernelProxy: unsupported architecture {self.ql.arch.type}")
106103

107104
import qiling.os.linux.map_syscall as mod
108105
table = getattr(mod, table_name)
@@ -115,7 +112,7 @@ def _resolve_syscall_nr(self, name: str) -> int:
115112
"""Resolve a syscall name to its number for the guest architecture."""
116113
table = self._build_reverse_table()
117114
if name not in table:
118-
raise ValueError(
115+
raise QlErrorSyscallNotFound(
119116
f"KernelProxy: syscall '{name}' not found in {self.ql.arch.type.name} syscall table"
120117
)
121118
return table[name]
@@ -135,8 +132,8 @@ def forward_syscall(self, name: str, returns_fd: bool = False):
135132
forwarder = self._make_forwarder(name, nr, returns_fd)
136133
self.ql.os.set_syscall(name, forwarder, QL_INTERCEPT.CALL)
137134

138-
log.info(f"forwarding syscall '{name}' (nr={nr}) to kernel proxy"
139-
f"{' [returns FD]' if returns_fd else ''}")
135+
self.ql.log.info(f"forwarding syscall '{name}' (nr={nr}) to kernel proxy"
136+
f"{' [returns FD]' if returns_fd else ''}")
140137

141138
def _make_forwarder(self, name: str, guest_nr: int, returns_fd: bool):
142139
"""Create a CALL hook closure for one syscall."""
@@ -170,17 +167,16 @@ def _get_host_syscall_nr(self, name: str) -> int:
170167
self._host_table = self._load_host_syscall_table()
171168

172169
if name not in self._host_table:
173-
raise RuntimeError(f"KernelProxy: syscall '{name}' not available on host")
170+
raise QlErrorSyscallNotFound(f"KernelProxy: syscall '{name}' not available on host")
174171

175172
return self._host_table[name]
176173

177-
def _load_host_syscall_table(self) -> dict:
174+
def _load_host_syscall_table(self) -> Dict[str, int]:
178175
"""Load the host's syscall name->nr mapping.
179176
180177
Uses the same Qiling tables, indexed by the host architecture.
181178
"""
182179
import platform
183-
from qiling.const import QL_ARCH
184180
import qiling.os.linux.map_syscall as mod
185181

186182
machine = platform.machine()
@@ -195,7 +191,7 @@ def _load_host_syscall_table(self) -> dict:
195191

196192
table_name = host_arch_map.get(machine)
197193
if table_name is None:
198-
raise RuntimeError(f"KernelProxy: unsupported host architecture '{machine}'")
194+
raise QlErrorArch(f"KernelProxy: unsupported host architecture '{machine}'")
199195

200196
table = getattr(mod, table_name)
201197
return {name: nr for nr, name in table.items()}
@@ -208,7 +204,7 @@ def _alloc_fd(ql, fd_obj) -> int:
208204
ql.os.fd[i] = fd_obj
209205
return i
210206

211-
raise OSError("kernel_proxy: FD table full")
207+
raise QlErrorSyscallError("kernel_proxy: FD table full")
212208

213209
def stop(self):
214210
"""Stop the proxy process."""
@@ -226,7 +222,7 @@ def stop(self):
226222
except subprocess.TimeoutExpired:
227223
self._process.kill()
228224
self._process.wait()
229-
log.info(f"kernel proxy stopped (pid={self._process.pid})")
225+
self.ql.log.info(f"kernel proxy stopped (pid={self._process.pid})")
230226
self._process = None
231227

232228
def __del__(self):

qiling/os/posix/kernel_proxy/ipc.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import socket
1818
from enum import IntEnum
1919

20+
from qiling.exception import QlProxyConnectionError
21+
2022

2123
class MsgType(IntEnum):
2224
SYSCALL = 1
@@ -64,7 +66,7 @@ def _recvall(sock: socket.socket, n: int) -> bytes:
6466
while len(buf) < n:
6567
chunk = sock.recv(n - len(buf))
6668
if not chunk:
67-
raise ConnectionError("kernel proxy connection closed")
69+
raise QlProxyConnectionError("kernel proxy connection closed")
6870
buf.extend(chunk)
6971
return bytes(buf)
7072

@@ -162,7 +164,7 @@ def recv_request(self) -> tuple:
162164
return MsgType.FD_OP, (FdOp(op), proxy_fd, arg1, arg2, data)
163165

164166
else:
165-
raise ValueError(f"unknown message type: {msg_type}")
167+
raise QlProxyConnectionError(f"unknown message type: {msg_type}")
166168

167169
def send_syscall_response(self, retval: int, errno_val: int):
168170
payload = struct.pack(SYSCALL_RESP_FMT, retval, errno_val)

qiling/os/posix/kernel_proxy/proxy.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
python -m qiling.os.posix.kernel_proxy.proxy <socket_fd>
1414
"""
1515

16+
import logging
1617
import os
1718
import sys
1819
import ctypes
@@ -24,10 +25,12 @@
2425
ProxyServer, MsgType, FdOp
2526
)
2627

28+
log = logging.getLogger("qiling.os.posix.kernel_proxy.proxy")
29+
2730
# load libc for raw syscall()
2831
_libc_path = ctypes.util.find_library("c")
2932
if _libc_path is None:
30-
print("kernel_proxy: cannot find libc", file=sys.stderr)
33+
log.critical("kernel_proxy: cannot find libc")
3134
sys.exit(1)
3235

3336
_libc = ctypes.CDLL(_libc_path, use_errno=True)
@@ -86,7 +89,7 @@ def handle_fd_op(op: FdOp, proxy_fd: int, arg1: int, arg2: int, data: bytes) ->
8689

8790
def main():
8891
if len(sys.argv) != 2:
89-
print(f"usage: {sys.argv[0]} <socket_fd>", file=sys.stderr)
92+
log.error(f"usage: {sys.argv[0]} <socket_fd>")
9093
sys.exit(1)
9194

9295
sock_fd = int(sys.argv[1])

tests/test_kernel_proxy.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,13 +283,14 @@ def test_ipc_roundtrip(self):
283283
# -------------------------------------------------------------------------
284284

285285
def test_forward_invalid_syscall_name(self):
286-
"""forward_syscall with bogus name raises ValueError."""
286+
"""forward_syscall with bogus name raises QlErrorSyscallNotFound."""
287287
from qiling.os.posix.kernel_proxy import KernelProxy
288+
from qiling.exception import QlErrorSyscallNotFound
288289

289290
ql = Qiling([self.HELLO_BIN], self.ROOTFS, verbose=QL_VERBOSE.OFF)
290291
proxy = KernelProxy(ql)
291292

292-
with self.assertRaises(ValueError):
293+
with self.assertRaises(QlErrorSyscallNotFound):
293294
proxy.forward_syscall('nonexistent_syscall_xyz')
294295

295296
proxy.stop()

0 commit comments

Comments
 (0)