Simplify linux model interfaces (#233)

This commit is contained in:
Yan 2017-05-05 13:11:59 -04:00 committed by GitHub
parent aafc0e7284
commit 50fd50ee12
2 changed files with 132 additions and 150 deletions

View File

@ -302,22 +302,19 @@ class Linux(object):
assert self._open(stderr) == 2
#Load process and setup socketpairs
self.procs = []
arch = {'x86': 'i386', 'x64': 'amd64', 'ARM': 'armv7'}[ELFFile(file(program)).get_machine_arch()]
cpu = self._mk_proc(arch)
self.load(cpu, program)
self._arch_specific_init(cpu, arch)
self._stack_top = cpu.STACK
self.setup_stack(cpu, [program]+argv, envp)
self.procs = [self._mk_proc(arch)]
self.procs.append(cpu)
self._current = 0
self.load(program)
self._arch_specific_init(arch)
self._stack_top = self.current.STACK
self.setup_stack([program]+argv, envp)
nprocs = len(self.procs)
nfiles = len(self.files)
assert nprocs > 0
self.running = range(nprocs)
self._current = 0
#Each process can wait for one timeout
self.timers = [ None ] * nprocs
@ -416,20 +413,20 @@ class Linux(object):
if '_arm_tls_memory' in state:
self._arm_tls_memory = state['_arm_tls_memory']
def _read_string(self, cpu, buf):
def _read_string(self, buf):
"""
Reads a null terminated concrete buffer form memory
:todo: FIX. move to cpu or memory
"""
filename = ""
for i in xrange(0,1024):
c = Operators.CHR(cpu.read_int(buf + i, 8))
c = Operators.CHR(self.current.read_int(buf + i, 8))
if c == '\x00':
break
filename += c
return filename
def _init_arm_kernel_helpers(self, cpu):
def _init_arm_kernel_helpers(self):
'''
ARM kernel helpers
@ -482,7 +479,7 @@ class Linux(object):
).decode('hex')
# Map a TLS segment
self._arm_tls_memory = cpu.memory.mmap(None, 4, 'rw ')
self._arm_tls_memory = self.current.memory.mmap(None, 4, 'rw ')
__kuser_get_tls = (
'04009FE5' + # ldr r0, [pc, #4]
@ -506,7 +503,7 @@ class Linux(object):
update(0xff0, tls_area)
update(0xffc, version)
cpu.memory.mmap(0xffff0000, len(page_data), 'r x', page_data)
self.current.memory.mmap(0xffff0000, len(page_data), 'r x', page_data)
def load_vdso(self, bits):
#load vdso #TODO or #IGNORE
@ -519,7 +516,7 @@ class Linux(object):
return vdso_addr
def setup_stack(self, cpu, argv, envp):
def setup_stack(self, argv, envp):
'''
:param Cpu cpu: The cpu instance
:param argv: list of parameters for the program to execute.
@ -555,6 +552,7 @@ class Linux(object):
(0xc0000000) < top of stack > 0 (virtual)
----------------------------------------------------------------------
'''
cpu = self.current
# In case setup_stack() is called again, we make sure we're growing the
# stack from the original top
@ -654,7 +652,7 @@ class Linux(object):
push_int(len(argvlst))
def load(self, cpu, filename):
def load(self, filename):
'''
Loads and an ELF program in memory and prepares the initial CPU state.
Creates the stack and loads the environment variables and the arguments in it.
@ -666,6 +664,7 @@ class Linux(object):
'''
#load elf See binfmt_elf.c
#read the ELF object file
cpu = self.current
elf = ELFFile(file(filename))
arch = {'x86':'i386','x64':'amd64', 'ARM': 'armv7'}[elf.get_machine_arch()]
addressbitsize = {'x86':32, 'x64':64, 'ARM': 32}[elf.get_machine_arch()]
@ -945,7 +944,7 @@ class Linux(object):
return fd >= 0 and fd < len(self.files) and self.files[fd] is not None
def sys_lseek(self, cpu, fd, offset, whence):
def sys_lseek(self, fd, offset, whence):
'''
lseek - reposition read/write file offset
@ -978,7 +977,7 @@ class Linux(object):
logger.debug("LSEEK(%d, 0x%08x, %d)"%(fd, offset, whence))
return 0
def sys_read(self, cpu, fd, buf, count):
def sys_read(self, fd, buf, count):
data = ''
if count != 0:
if not self._is_open(fd):
@ -986,7 +985,7 @@ class Linux(object):
return errno.EBADF
# TODO check count bytes from buf
if not buf in cpu.memory: # or not cpu.memory.isValid(buf+count):
if not buf in self.current.memory: # or not self.current.memory.isValid(buf+count):
logger.info("READ: buf points to invalid address. Returning EFAULT")
return errno.EFAULT
@ -996,18 +995,17 @@ class Linux(object):
# Read the data and put in tin memory
data = self.files[fd].read(count)
self.syscall_trace.append(("_read", fd, data))
cpu.write_bytes(buf, data)
self.current.write_bytes(buf, data)
logger.debug("READ(%d, 0x%08x, %d, 0x%08x) -> <%s> (size:%d)"%(fd, buf, count, len(data), repr(data)[:min(count,10)],len(data)))
return len(data)
def sys_write(self, cpu, fd, buf, count):
def sys_write(self, fd, buf, count):
''' write - send bytes through a file descriptor
The write system call writes up to count bytes from the buffer pointed
to by buf to the file descriptor fd. If count is zero, write returns 0
and optionally sets *tx_bytes to zero.
:param cpu current CPU
:param fd a valid file descriptor
:param buf a memory buffer
:param count number of bytes to send
@ -1016,6 +1014,7 @@ class Linux(object):
EFAULT buf or tx_bytes points to an invalid address.
'''
data = []
cpu = self.current
if count != 0:
if not self._is_open(fd):
@ -1042,12 +1041,11 @@ class Linux(object):
return len(data)
def sys_access(self, cpu, buf, mode):
def sys_access(self, buf, mode):
'''
Checks real user's permissions for a file
:rtype: int
:param cpu: current CPU.
:param buf: a buffer containing the pathname to the file to check its permissions.
:param mode: the access permissions to check.
:return:
@ -1056,7 +1054,7 @@ class Linux(object):
'''
filename = ""
for i in xrange(0,255):
c = Operators.CHR(cpu.read_int(buf + i, 8))
c = Operators.CHR(self.current.read_int(buf + i, 8))
if c == '\x00':
break
filename += c
@ -1071,11 +1069,10 @@ class Linux(object):
else:
return -1
def sys_uname(self, cpu, old_utsname):
def sys_uname(self, old_utsname):
'''
Writes system information in the variable C{old_utsname}.
:rtype: int
:param cpu: current CPU.
:param old_utsname: the buffer to write the system info.
:return: C{0} on success
'''
@ -1088,15 +1085,14 @@ class Linux(object):
uname += pad('#4 SMP '+ datetime.now().strftime("%a %b %d %H:%M:%S ART %Y") )
uname += pad('x86_64')
uname += pad('(none)')
cpu.write_bytes(old_utsname, uname)
self.current.write_bytes(old_utsname, uname)
logger.debug("sys_uname(...) -> %s", uname)
return 0
def sys_brk(self, cpu, brk):
def sys_brk(self, brk):
'''
Changes data segment size (moves the C{elf_brk} to the new address)
:rtype: int
:param cpu: current CPU.
:param brk: the new address for C{elf_brk}.
:return: the value of the new C{elf_brk}.
:raises error:
@ -1104,21 +1100,21 @@ class Linux(object):
'''
if brk != 0:
assert brk > self.elf_brk
mem = self.current.memory
size = brk-self.elf_brk
perms = cpu.memory.perms(self.elf_brk-1)
if brk > cpu.memory._ceil(self.elf_brk):
addr = cpu.memory.mmap(cpu.memory._ceil(self.elf_brk), size, perms)
assert cpu.memory._ceil(self.elf_brk) == addr, "Error in brk!"
perms = mem.perms(self.elf_brk-1)
if brk > mem._ceil(self.elf_brk):
addr = mem.mmap(mem._ceil(self.elf_brk), size, perms)
assert mem._ceil(self.elf_brk) == addr, "Error in brk!"
self.elf_brk += size
logger.debug("sys_brk(0x%08x) -> 0x%08x", brk, self.elf_brk)
return self.elf_brk
def sys_arch_prctl(self, cpu, code, addr):
def sys_arch_prctl(self, code, addr):
'''
Sets architecture-specific thread state
:rtype: int
:param cpu: current CPU.
:param code: must be C{ARCH_SET_FS}.
:param addr: the base address of the FS segment.
:return: C{0} on success
@ -1130,23 +1126,23 @@ class Linux(object):
ARCH_GET_FS = 0x1003
ARCH_GET_GS = 0x1004
assert code == ARCH_SET_FS
cpu.FS=0x63
cpu.set_descriptor(cpu.FS, addr, 0x4000, 'rw')
self.current.FS=0x63
self.current.set_descriptor(self.current.FS, addr, 0x4000, 'rw')
logger.debug("sys_arch_prctl(%04x, %016x) -> 0", code, addr)
return 0
def sys_ioctl(self, cpu, fd, request, argp):
def sys_ioctl(self, fd, request, argp):
if fd > 2:
return self.files[fd].ioctl(request, argp)
else:
return 0
def sys_open(self, cpu, buf, flags, mode):
def sys_open(self, buf, flags, mode):
# buf: address of zero-terminated pathname
# flags/access: file access bits
# perms: file permission mode
filename = self._read_string(cpu, buf)
filename = self._read_string(buf)
try :
if os.path.abspath(filename).startswith('/proc/self'):
if filename == '/proc/self/exe':
@ -1167,21 +1163,21 @@ class Linux(object):
return self._open(f)
def sys_getpid(self, cpu, v):
def sys_getpid(self, v):
logger.debug("GETPID, warning pid modeled as concrete 1000")
return 1000
def sys_ARM_NR_set_tls(self, cpu, val):
def sys_ARM_NR_set_tls(self, val):
if hasattr(self, '_arm_tls_memory'):
cpu.write_int(self._arm_tls_memory, val)
self.current.write_int(self._arm_tls_memory, val)
return 0
#Signals..
def sys_kill(self, cpu, pid, sig):
def sys_kill(self, pid, sig):
logger.debug("KILL, Ignoring Sending signal %d to pid %d", sig, pid )
return 0
def sys_sigaction(self, cpu, signum, act, oldact):
def sys_sigaction(self, signum, act, oldact):
logger.debug("SIGACTION, Ignoring changing signal handler for signal %d", signum)
return 0
@ -1189,11 +1185,10 @@ class Linux(object):
logger.debug("SIGACTION, Ignoring changing signal mask set cmd:%d", how)
return 0
def sys_close(self, cpu, fd):
def sys_close(self, fd):
'''
Closes a file descriptor
:rtype: int
:param cpu: current CPU.
:param fd: the file descriptor to close.
:return: C{0} on success.
'''
@ -1202,12 +1197,11 @@ class Linux(object):
logger.debug('sys_close(%d)', fd)
return 0
def sys_readlink(self, cpu, path, buf, bufsize):
def sys_readlink(self, path, buf, bufsize):
'''
Read
:rtype: int
:param cpu: current CPU.
:param path: the "link path id"
:param buf: the buffer where the bytes will be putted.
:param bufsize: the max size for read the link.
@ -1215,90 +1209,85 @@ class Linux(object):
'''
if bufsize <= 0:
return -errno.EINVAL
filename = self._read_string(cpu, path)
filename = self._read_string(path)
data = os.readlink(filename)[:bufsize]
cpu.write_bytes(buf, data)
self.current.write_bytes(buf, data)
logger.debug("READLINK %d %x %d -> %s",path,buf,bufsize,data)
return len(data)
def sys_mprotect(self, cpu, start, size, prot):
def sys_mprotect(self, start, size, prot):
'''
Sets protection on a region of memory. Changes protection for the calling process's
memory page(s) containing any part of the address range in the interval [C{start}, C{start}+C{size}-1].
:rtype: int
:param cpu: current CPU.
:param start: the starting address to change the permissions.
:param size: the size of the portion of memory to change the permissions.
:param prot: the new access permission for the memory.
:return: C{0} on success.
'''
perms = perms_from_protflags(prot)
ret = cpu.memory.mprotect(start, size, perms)
ret = self.current.memory.mprotect(start, size, perms)
logger.debug("sys_mprotect(0x%016x, 0x%x, %s) -> %r (%r)", start, size, perms, ret, prot)
return 0
def sys_munmap(self, cpu, addr, size):
def sys_munmap(self, addr, size):
'''
Unmaps a file from memory. It deletes the mappings for the specified address range
:rtype: int
:param cpu: current CPU.
:param addr: the starting address to unmap.
:param size: the size of the portion to unmap.
:return: C{0} on success.
'''
cpu.memory.munmap(addr, size)
self.current.memory.munmap(addr, size)
return 0
def sys_getuid(self, cpu):
def sys_getuid(self):
'''
Gets user identity.
:rtype: int
:param cpu: current CPU.
:return: this call returns C{1000} for all the users.
'''
return 1000
def sys_getgid(self, cpu):
def sys_getgid(self):
'''
Gets group identity.
:rtype: int
:param cpu: current CPU.
:return: this call returns C{1000} for all the groups.
'''
return 1000
def sys_geteuid(self, cpu):
def sys_geteuid(self):
'''
Gets user identity.
:rtype: int
:param cpu: current CPU.
:return: This call returns C{1000} for all the users.
'''
return 1000
def sys_getegid(self, cpu):
def sys_getegid(self):
'''
Gets group identity.
:rtype: int
:param cpu: current CPU.
:return: this call returns C{1000} for all the groups.
'''
return 1000
def sys_readv(self, cpu, fd, iov, count):
def sys_readv(self, fd, iov, count):
'''
Works just like C{sys_read} except that data is read into multiple buffers.
:rtype: int
:param cpu: current CPU.
:param fd: the file descriptor of the file to read.
:param iov: the buffer where the the bytes to read are stored.
:param count: amount of C{iov} buffers to read from the file.
:return: the amount of bytes read in total.
'''
cpu = self.current
ptrsize = cpu.address_bit_size
sizeof_iovec = 2 * (ptrsize // 8)
total = 0
@ -1313,17 +1302,17 @@ class Linux(object):
logger.debug("READV(%r, %r, %r) -> <%r> (size:%r)"%(fd, buf, size, data, len(data)))
return total
def sys_writev(self, cpu, fd, iov, count):
def sys_writev(self, fd, iov, count):
'''
Works just like C{sys_write} except that multiple buffers are written out.
:rtype: int
:param cpu: current CPU.
:param fd: the file descriptor of the file to write.
:param iov: the buffer where the the bytes to write are taken.
:param count: amount of C{iov} buffers to write into the file.
:return: the amount of bytes written in total.
'''
cpu = self.current
ptrsize = cpu.address_bit_size
sizeof_iovec = 2 * (ptrsize // 8)
total = 0
@ -1340,27 +1329,26 @@ class Linux(object):
total+=size
return total
def sys_set_thread_area32(self, cpu, user_info):
def sys_set_thread_area32(self, user_info):
'''
Sets a thread local storage (TLS) area. Sets the base address of the GS segment.
:rtype: int
:param cpu: current CPU.
:param user_info: the TLS array entry set corresponds to the value of C{u_info->entry_number}.
:return: C{0} on success.
'''
n = cpu.read_int(user_info, 32)
pointer = cpu.read_int(user_info + 4, 32)
m = cpu.read_int(user_info + 8, 32)
flags = cpu.read_int(user_info + 12, 32)
n = self.current.read_int(user_info, 32)
pointer = self.current.read_int(user_info + 4, 32)
m = self.current.read_int(user_info + 8, 32)
flags = self.current.read_int(user_info + 12, 32)
assert n == 0xffffffff
assert flags == 0x51 #TODO: fix
cpu.GS=0x63
cpu.set_descriptor(cpu.GS, pointer, 0x4000, 'rw')
cpu.write_int(user_info, (0x63 - 3) / 8, 32)
self.current.GS=0x63
self.current.set_descriptor(self.current.GS, pointer, 0x4000, 'rw')
self.current.write_int(user_info, (0x63 - 3) / 8, 32)
return 0
def sys_getpriority(self, cpu, which, who):
def sys_getpriority(self, which, who):
'''
System call ignored.
:rtype: int
@ -1370,7 +1358,7 @@ class Linux(object):
logger.debug("Ignoring sys_get_priority")
return 0
def sys_setpriority(self, cpu, which, who, prio):
def sys_setpriority(self, which, who, prio):
'''
System call ignored.
:rtype: int
@ -1380,7 +1368,7 @@ class Linux(object):
logger.debug("Ignoring sys_set_priority")
return 0
def sys_acct(self, cpu, path):
def sys_acct(self, path):
'''
System call not implemented.
:rtype: int
@ -1390,13 +1378,12 @@ class Linux(object):
logger.debug("BSD account not implemented!")
return -1
def sys_exit_group(self, cpu, error_code):
def sys_exit_group(self, error_code):
'''
Exits all threads in a process
:param cpu: current CPU.
:raises Exception: 'Finished'
'''
procid = self.procs.index(cpu)
procid = self.procs.index(self.current)
self.sched()
self.running.remove(procid)
#self.procs[procid] = None
@ -1405,41 +1392,40 @@ class Linux(object):
raise ProcessExit(error_code)
return error_code
def sys_ptrace(self, cpu, request, pid, addr, data):
def sys_ptrace(self, request, pid, addr, data):
logger.debug("sys_ptrace(%016x, %d, %016x, %016x) -> 0", request, pid, addr, data)
return 0
def sys_nanosleep(self, cpu, req, rem):
def sys_nanosleep(self, req, rem):
logger.debug("sys_nanosleep(...)")
return 0
def sys_set_tid_address(self, cpu, tidptr):
def sys_set_tid_address(self, tidptr):
logger.debug("sys_set_tid_address(%016x) -> 0", tidptr)
return 1000 #tha pid
def sys_faccessat(self, cpu, dirfd, pathname, mode, flags):
filename = self._read_string(cpu, pathname)
def sys_faccessat(self, dirfd, pathname, mode, flags):
filename = self._read_string(pathname)
logger.debug("sys_faccessat(%016x, %s, %x, %x) -> 0", dirfd, filename, mode, flags)
return -1
def sys_set_robust_list(self, cpu, head, length):
def sys_set_robust_list(self, head, length):
logger.debug("sys_set_robust_list(%016x, %d) -> -1", head, length)
return -1
def sys_futex(self, cpu, uaddr, op, val, timeout, uaddr2, val3):
def sys_futex(self, uaddr, op, val, timeout, uaddr2, val3):
logger.debug("sys_futex(...) -> -1")
return -1
def sys_getrlimit(self, cpu, resource, rlim):
def sys_getrlimit(self, resource, rlim):
logger.debug("sys_getrlimit(%x, %x) -> -1",resource, rlim)
return -1
def sys_fadvise64(self, cpu, fd, offset, length, advice):
def sys_fadvise64(self, fd, offset, length, advice):
logger.debug("sys_fadvise64(%x, %x, %x, %x) -> 0", fd, offset, length, advice)
return 0
def sys_gettimeofday(self, cpu, tv, tz):
def sys_gettimeofday(self, tv, tz):
logger.debug("sys_gettimeofday(%x, %x) -> 0", tv, tz)
return 0
#Distpatchers...
def syscall(self, cpu):
def syscall(self):
'''
64 bit dispatcher.
:param cpu: current CPU.
'''
syscalls = {
0x0000000000000008: self.sys_lseek,
@ -1498,25 +1484,25 @@ class Linux(object):
}
index, arguments, writeResult = cpu.get_syscall_description()
index, arguments, writeResult = self.current.get_syscall_description()
if index not in syscalls:
raise SyscallNotImplemented(64, index)
func = syscalls[index]
logger.debug("SYSCALL64: %s %r ", func.func_name
, arguments[:func.func_code.co_argcount])
nargs = func.func_code.co_argcount
args = [ cpu ] + arguments
result = func(*args[:nargs-1])
result = func(*arguments[:nargs-1])
writeResult(result)
return result
def int80(self, cpu):
def int80(self):
'''
32 bit dispatcher.
:param cpu: current CPU.
'''
syscalls = { 0x00000001: self.sys_exit_group,
0x00000003: self.sys_read,
@ -1554,7 +1540,7 @@ class Linux(object):
0x00000014: self.sys_getpid,
0x000f0005: self.sys_ARM_NR_set_tls,
}
index, arguments, writeResult = cpu.get_syscall_description()
index, arguments, writeResult = self.current.get_syscall_description()
if index not in syscalls:
raise SyscallNotImplemented(64, index)
@ -1563,21 +1549,20 @@ class Linux(object):
logger.debug("int80: %s %r ", func.func_name
, arguments[:func.func_code.co_argcount])
nargs = func.func_code.co_argcount
args = [ cpu ] + arguments
result = func(*args[:nargs-1])
result = func(*arguments[:nargs-1])
writeResult(result)
return result
def sys_clock_gettime(self, cpu, clock_id, timespec):
def sys_clock_gettime(self, clock_id, timespec):
logger.info("sys_clock_time not really implemented")
return 0
def sys_time(self, cpu, tloc):
def sys_time(self, tloc):
import time
t = time.time()
if tloc != 0 :
cpu.write_int(tloc, int(t), cpu.address_bit_size)
self.current.write_int(tloc, int(t), self.current.address_bit_size)
return int(t)
@ -1709,25 +1694,25 @@ class Linux(object):
self.sched()
except Interruption, e:
try:
syscallret = self.int80(self.current)
syscallret = self.int80()
except RestartSyscall:
pass
except Syscall, e:
try:
syscallret = self.syscall(self.current)
syscallret = self.syscall()
except RestartSyscall:
pass
return True
#64bit syscalls
def sys_fstat64(self, cpu, fd, buf):
def sys_fstat64(self, fd, buf):
'''
Determines information about a file based on its file descriptor (for Linux 64 bits).
:rtype: int
:param cpu: current CPU.
:param fd: the file descriptor of the file that is being inquired.
:param buf: a buffer where data about the file will be stored.
:return: C{0} on success.
@ -1781,35 +1766,34 @@ class Linux(object):
bufstat += struct.pack('<L', 0) #pad
bufstat += struct.pack('<L', 0) #pad
cpu.write_bytes(buf, bufstat)
self.current.write_bytes(buf, bufstat)
return 0
def sys_stat64(self, cpu, path, buf):
def sys_stat64(self, path, buf):
'''
Determines information about a file based on its filename (for Linux 64 bits).
:rtype: int
:param cpu: current CPU.
:param path: the pathname of the file that is being inquired.
:param buf: a buffer where data about the file will be stored.
:return: C{0} on success.
'''
return self._stat(cpu, path, buf, True)
return self._stat(path, buf, True)
def sys_stat32(self, cpu, path, buf):
return self._stat(cpu, path, buf, False)
def sys_stat32(self, path, buf):
return self._stat(path, buf, False)
def _stat(self, cpu, path, buf, is64bit):
fd = self.sys_open(cpu, path, 0, 'r')
def _stat(self, path, buf, is64bit):
fd = self.sys_open(path, 0, 'r')
if is64bit:
ret = self.sys_fstat64(cpu, fd, buf)
ret = self.sys_fstat64(fd, buf)
else:
ret = self.sys_fstat(cpu, fd, buf)
self.sys_close(cpu, fd)
ret = self.sys_fstat(fd, buf)
self.sys_close(fd)
return ret
def _arch_specific_init(self, cpu, arch):
def _arch_specific_init(self, arch):
assert arch in {'i386', 'amd64', 'armv7'}
self._arch_reg_init(cpu, arch)
self._arch_reg_init(arch)
if arch == 'i386':
self.syscall_arg_regs = ['EBX', 'ECX', 'EDX', 'ESI', 'EDI', 'EBP']
@ -1817,10 +1801,10 @@ class Linux(object):
self.syscall_arg_regs = ['RDI', 'RSI', 'RDX', 'R10', 'R8', 'R9']
elif arch == 'armv7':
self.syscall_arg_regs = ['R0', 'R1', 'R2', 'R3', 'R4', 'R5', 'R6']
self._init_arm_kernel_helpers(cpu)
self._init_arm_kernel_helpers()
def _arch_reg_init(self, cpu, arch):
def _arch_reg_init(self, arch):
if arch in {'i386', 'amd64'}:
x86_defaults = {
'CS': 0x23,
@ -1829,7 +1813,7 @@ class Linux(object):
'ES': 0x2b,
}
for reg, val in x86_defaults.iteritems():
cpu.regfile.write(reg, val)
self.current.regfile.write(reg, val)
@staticmethod
def _interp_total_size(interp):
@ -1856,7 +1840,6 @@ class SLinux(Linux):
'''
Builds a symbolic extension of a Decree OS
:param constraints: a constraints.
:param cpus: CPU for this model.
:param mem: memory for this model.
'''
self._constraints = ConstraintSet()
@ -1889,26 +1872,26 @@ class SLinux(Linux):
self.symbolic_files = state['symbolic_files']
super(SLinux, self).__setstate__(state)
#Dispatchers...
def syscall(self, cpu):
def syscall(self):
try:
return super(SLinux, self).syscall(cpu)
return super(SLinux, self).syscall()
except SymbolicSyscallArgument, e:
cpu.PC = cpu.PC - cpu.instruction.size
self.current.PC = self.current.PC - self.current.instruction.size
reg_name = self.syscall_arg_regs[e.reg_num]
raise ConcretizeRegister(reg_name,e.message,e.policy)
def int80(self, cpu):
def int80(self):
try:
return super(SLinux, self).int80(cpu)
return super(SLinux, self).int80()
except SymbolicSyscallArgument, e:
cpu.PC = cpu.PC - cpu.instruction.size
self.current.PC = self.current.PC - self.current.instruction.size
reg_name = self.syscall_arg_regs[e.reg_num]
raise ConcretizeRegister(reg_name,e.message,e.policy)
def sys_read(self, cpu, fd, buf, count):
def sys_read(self, fd, buf, count):
if issymbolic(fd):
logger.debug("Ask to read from a symbolic file descriptor!!")
raise SymbolicSyscallArgument(0)
@ -1921,14 +1904,13 @@ class SLinux(Linux):
logger.debug("Ask to read a symbolic number of bytes ")
raise SymbolicSyscallArgument(2)
return super(SLinux, self).sys_read(cpu, fd, buf, count)
return super(SLinux, self).sys_read(fd, buf, count)
def sys_fstat(self, cpu, fd, buf):
def sys_fstat(self, fd, buf):
'''
Determines information about a file based on its file descriptor.
:rtype: int
:param cpu: current CPU.
:param fd: the file descriptor of the file that is being inquired.
:param buf: a buffer where data about the file will be stored.
:return: C{0} on success.
@ -1966,14 +1948,13 @@ class SLinux(Linux):
bufstat += struct.pack('<Q', stat.st_atime)
bufstat += struct.pack('<Q', stat.st_ctime)
bufstat += struct.pack('<Q', stat.st_mtime)
cpu.write_bytes(buf, bufstat)
self.current.write_bytes(buf, bufstat)
return 0
def sys_mmap2(self, cpu, address, size, prot, flags, fd, offset):
def sys_mmap2(self, address, size, prot, flags, fd, offset):
'''
Creates a new mapping in the virtual address space of the calling process.
:rtype: int
:param cpu: current CPU.
:param address: the starting address for the new mapping. This address is used as hint unless the
flag contains C{MAP_FIXED}.
:param size: the length of the mapping.
@ -1989,14 +1970,13 @@ class SLinux(Linux):
- C{-1} In case you use C{MAP_FIXED} in the flags and the mapping can not be place at the desired address.
- the address of the new mapping.
'''
return self.sys_mmap(cpu, address, size, prot, flags, fd, offset*0x1000)
return self.sys_mmap(address, size, prot, flags, fd, offset*0x1000)
def sys_mmap(self, cpu, address, size, prot, flags, fd, offset):
def sys_mmap(self, address, size, prot, flags, fd, offset):
'''
Creates a new mapping in the virtual address space of the calling process.
:rtype: int
:param cpu: current CPU.
:param address: the starting address for the new mapping. This address is used as hint unless the
flag contains C{MAP_FIXED}.
:param size: the length of the mapping.
@ -2016,6 +1996,8 @@ class SLinux(Linux):
if address == 0:
address = None
cpu = self.current
if flags & 0x10 !=0 :
cpu.memory.munmap(address,size)
@ -2039,7 +2021,7 @@ class SLinux(Linux):
return result
def sys_write(self, cpu, fd, buf, count):
def sys_write(self, fd, buf, count):
if issymbolic(fd):
logger.debug("Ask to write to a symbolic file descriptor!!")
raise SymbolicSyscallArgument(0)
@ -2052,7 +2034,7 @@ class SLinux(Linux):
logger.debug("Ask to write a symbolic number of bytes ")
raise SymbolicSyscallArgument(2)
return super(SLinux, self).sys_write(cpu, fd, buf, count)
return super(SLinux, self).sys_write(fd, buf, count)
class DecreeEmu(object):

View File

@ -37,10 +37,10 @@ class LinuxTest(unittest.TestCase):
envp_ptr = argv_ptr + len(real_argv)*8 + 8
for i, arg in enumerate(real_argv):
self.assertEqual(self.linux._read_string(cpu, cpu.read_int(argv_ptr + i*8)), arg)
self.assertEqual(self.linux._read_string(cpu.read_int(argv_ptr + i*8)), arg)
for i, env in enumerate(envp):
self.assertEqual(self.linux._read_string(cpu, cpu.read_int(envp_ptr + i*8)), env)
self.assertEqual(self.linux._read_string(cpu.read_int(envp_ptr + i*8)), env)
def test_load_maps(self):
mappings = self.linux.current.memory.mappings()