mirror of
https://github.com/qilingframework/qiling.git
synced 2026-10-12 02:21:40 +00:00
Add regression test for getdents64 record alignment
Calls ql_syscall_getdents64 on a directory and walks the returned linux_dirent64 records, asserting every record (and thus its leading u64 d_ino) starts on an 8-byte boundary. Before the fix d_reclen was not rounded up, so records were misaligned and a strict-alignment guest (e.g. MIPS) faulted with an unaligned load. Self-contained; runs on stock unicorn. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
012726f272
commit
0e48da4be8
@@ -725,6 +725,43 @@ class ELFTest(unittest.TestCase):
|
||||
|
||||
del ql
|
||||
|
||||
# Regression for getdents64 record alignment. Each linux_dirent64 record
|
||||
# must be padded so the next record's leading u64 d_ino stays 8-byte
|
||||
# aligned; otherwise a strict-alignment guest (e.g. MIPS) faults with an
|
||||
# unaligned load while walking the buffer. x86 tolerates the unaligned read,
|
||||
# which is why it was never caught.
|
||||
def test_linux_getdents64_alignment(self):
|
||||
from qiling.const import QL_ENDIAN
|
||||
from qiling.os.posix.syscall.fcntl import ql_syscall_open
|
||||
from qiling.os.posix.syscall.unistd import ql_syscall_getdents64
|
||||
|
||||
ql = Qiling(code=b"\x00\x00\x00\x00", archtype=QL_ARCH.MIPS, ostype=QL_OS.LINUX,
|
||||
endian=QL_ENDIAN.EB, rootfs="../examples/rootfs/mips32_linux",
|
||||
verbose=QL_VERBOSE.OFF)
|
||||
|
||||
base = 0x100000
|
||||
ql.mem.map(base, 0x4000)
|
||||
path_ptr, buf_ptr = base, base + 0x100
|
||||
ql.mem.write(path_ptr, b"/\x00")
|
||||
|
||||
fd = ql_syscall_open(ql, path_ptr, 0, 0) # O_RDONLY on a directory
|
||||
self.assertGreaterEqual(fd, 0)
|
||||
|
||||
nbytes = ql_syscall_getdents64(ql, fd, buf_ptr, 0x2000)
|
||||
self.assertGreater(nbytes, 0)
|
||||
|
||||
# walk the linux_dirent64 records; every record (hence its leading u64
|
||||
# d_ino) must start at an 8-byte boundary. d_reclen is a u16 at offset 16.
|
||||
buf = bytes(ql.mem.read(buf_ptr, nbytes))
|
||||
off = 0
|
||||
while off < nbytes:
|
||||
self.assertEqual(off % 8, 0, f"dirent at offset {off} is not 8-byte aligned")
|
||||
d_reclen = int.from_bytes(buf[off + 16:off + 18], "big")
|
||||
self.assertNotEqual(d_reclen, 0)
|
||||
off += d_reclen
|
||||
|
||||
del ql
|
||||
|
||||
def test_memory_search(self):
|
||||
ql = Qiling(code=b"\xCC", archtype=QL_ARCH.X8664, ostype=QL_OS.LINUX, verbose=QL_VERBOSE.DEBUG)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user