* fixes #291 for incorrect syscall returns and some indent issues * relative import fix * commented weakref removal
This commit is contained in:
parent
776f6125ad
commit
584206f3f7
@ -1,21 +1,22 @@
|
||||
import fcntl
|
||||
|
||||
import cgcrandom
|
||||
import weakref
|
||||
import errno
|
||||
import os, struct
|
||||
import fcntl
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
import struct
|
||||
|
||||
from elftools.elf.elffile import ELFFile
|
||||
|
||||
from ..utils.helpers import issymbolic
|
||||
from ..core.cpu.abstractcpu import Interruption, Syscall, ConcretizeArgument
|
||||
from ..core.cpu.cpufactory import CpuFactory
|
||||
from ..core.memory import SMemory32, SMemory64, Memory32, Memory64
|
||||
from ..core.smtlib import Operators, ConstraintSet
|
||||
from ..platforms.platform import Platform
|
||||
from elftools.elf.elffile import ELFFile
|
||||
import logging
|
||||
import random
|
||||
from ..core.cpu.arm import *
|
||||
from ..core.executor import SyscallNotImplemented, ProcessExit
|
||||
from . import linux_syscalls
|
||||
|
||||
logger = logging.getLogger("PLATFORM")
|
||||
|
||||
|
||||
@ -98,7 +99,6 @@ class SymbolicFile(object):
|
||||
path = File(path, mode)
|
||||
assert isinstance(path, File)
|
||||
|
||||
#self._constraints = weakref.ref(constraints)
|
||||
WILDCARD = '+'
|
||||
|
||||
symbols_cnt = 0
|
||||
@ -181,7 +181,7 @@ class SymbolicFile(object):
|
||||
'''
|
||||
Reads up to C{count} bytes from the file.
|
||||
:rtype: list
|
||||
:return: the list of symbolic bytes read
|
||||
:return: the list of symbolic bytes read
|
||||
'''
|
||||
if self.pos > self.max_size :
|
||||
return []
|
||||
@ -193,7 +193,7 @@ class SymbolicFile(object):
|
||||
|
||||
def write(self, data):
|
||||
'''
|
||||
Writes the symbolic bytes in C{data} onto the file.
|
||||
Writes the symbolic bytes in C{data} onto the file.
|
||||
'''
|
||||
for c in data:
|
||||
size = min(len(data),self.max_size-self.pos)
|
||||
@ -201,7 +201,7 @@ class SymbolicFile(object):
|
||||
self.array[i] = data[i-self.pos]
|
||||
|
||||
|
||||
class Socket(object):
|
||||
class Socket(object):
|
||||
def stat(self):
|
||||
from collections import namedtuple
|
||||
stat_result = namedtuple('stat_result', ['st_mode','st_ino','st_dev','st_nlink','st_uid','st_gid','st_size','st_atime','st_mtime','st_ctime', 'st_blksize','st_blocks','st_rdev'])
|
||||
@ -274,7 +274,7 @@ class Linux(Platform):
|
||||
|
||||
self.program = program
|
||||
self.clocks = 0
|
||||
self.files = []
|
||||
self.files = []
|
||||
self.syscall_trace = []
|
||||
self.files = []
|
||||
|
||||
@ -451,7 +451,7 @@ class Linux(Platform):
|
||||
self._syscall_abi = state['syscallabi']
|
||||
self._uname_machine = state['uname_machine']
|
||||
if '_arm_tls_memory' in state:
|
||||
self._arm_tls_memory = state['_arm_tls_memory']
|
||||
self._arm_tls_memory = state['_arm_tls_memory']
|
||||
|
||||
def _init_arm_kernel_helpers(self):
|
||||
'''
|
||||
@ -464,55 +464,55 @@ class Linux(Platform):
|
||||
|
||||
# Extracted from a RPi2
|
||||
preamble = (
|
||||
'ff0300ea' +
|
||||
'650400ea' +
|
||||
'f0ff9fe5' +
|
||||
'430400ea' +
|
||||
'220400ea' +
|
||||
'810400ea' +
|
||||
'000400ea' +
|
||||
'870400ea'
|
||||
).decode('hex')
|
||||
'ff0300ea' +
|
||||
'650400ea' +
|
||||
'f0ff9fe5' +
|
||||
'430400ea' +
|
||||
'220400ea' +
|
||||
'810400ea' +
|
||||
'000400ea' +
|
||||
'870400ea'
|
||||
).decode('hex')
|
||||
|
||||
# XXX(yan): The following implementations of cmpxchg and cmpxchg64 were
|
||||
# handwritten to not use any exclusive instructions (e.g. ldrexd) or
|
||||
# handwritten to not use any exclusive instructions (e.g. ldrexd) or
|
||||
# locking. For actual implementations, refer to
|
||||
# arch/arm64/kernel/kuser32.S in the Linux source code.
|
||||
__kuser_cmpxchg64 = (
|
||||
'30002de9' + # push {r4, r5}
|
||||
'08c09de5' + # ldr ip, [sp, #8]
|
||||
'30009ce8' + # ldm ip, {r4, r5}
|
||||
'010055e1' + # cmp r5, r1
|
||||
'00005401' + # cmpeq r4, r0
|
||||
'0100a013' + # movne r0, #1
|
||||
'0000a003' + # moveq r0, #0
|
||||
'0c008c08' + # stmeq ip, {r2, r3}
|
||||
'3000bde8' + # pop {r4, r5}
|
||||
'1eff2fe1' # bx lr
|
||||
).decode('hex')
|
||||
'30002de9' + # push {r4, r5}
|
||||
'08c09de5' + # ldr ip, [sp, #8]
|
||||
'30009ce8' + # ldm ip, {r4, r5}
|
||||
'010055e1' + # cmp r5, r1
|
||||
'00005401' + # cmpeq r4, r0
|
||||
'0100a013' + # movne r0, #1
|
||||
'0000a003' + # moveq r0, #0
|
||||
'0c008c08' + # stmeq ip, {r2, r3}
|
||||
'3000bde8' + # pop {r4, r5}
|
||||
'1eff2fe1' # bx lr
|
||||
).decode('hex')
|
||||
|
||||
__kuser_dmb = (
|
||||
'5bf07ff5' + # dmb ish
|
||||
'1eff2fe1' # bx lr
|
||||
).decode('hex')
|
||||
'5bf07ff5' + # dmb ish
|
||||
'1eff2fe1' # bx lr
|
||||
).decode('hex')
|
||||
|
||||
__kuser_cmpxchg = (
|
||||
'003092e5' + # ldr r3, [r2]
|
||||
'000053e1' + # cmp r3, r0
|
||||
'0000a003' + # moveq r0, #0
|
||||
'00108205' + # streq r1, [r2]
|
||||
'0100a013' + # movne r0, #1
|
||||
'1eff2fe1' # bx lr
|
||||
).decode('hex')
|
||||
'003092e5' + # ldr r3, [r2]
|
||||
'000053e1' + # cmp r3, r0
|
||||
'0000a003' + # moveq r0, #0
|
||||
'00108205' + # streq r1, [r2]
|
||||
'0100a013' + # movne r0, #1
|
||||
'1eff2fe1' # bx lr
|
||||
).decode('hex')
|
||||
|
||||
# Map a TLS segment
|
||||
self._arm_tls_memory = self.current.memory.mmap(None, 4, 'rw ')
|
||||
|
||||
__kuser_get_tls = (
|
||||
'04009FE5' + # ldr r0, [pc, #4]
|
||||
'010090e8' + # ldm r0, {r0}
|
||||
'1eff2fe1' # bx lr
|
||||
).decode('hex') + struct.pack('<I', self._arm_tls_memory)
|
||||
'04009FE5' + # ldr r0, [pc, #4]
|
||||
'010090e8' + # ldm r0, {r0}
|
||||
'1eff2fe1' # bx lr
|
||||
).decode('hex') + struct.pack('<I', self._arm_tls_memory)
|
||||
|
||||
tls_area = '\x00'*12
|
||||
|
||||
@ -537,7 +537,7 @@ class Linux(Platform):
|
||||
vdso_top = {32: 0x7fff0000, 64: 0x7fff00007fff0000}[bits]
|
||||
vdso_size = len(file('vdso%2d.dump'%bits).read())
|
||||
vdso_addr = self.memory.mmapFile(self.memory._floor(vdso_top - vdso_size),
|
||||
vdso_size, 'r x',
|
||||
vdso_size, 'r x',
|
||||
{32: 'vdso32.dump', 64: 'vdso64.dump'}[bits],
|
||||
0 )
|
||||
return vdso_addr
|
||||
@ -558,24 +558,24 @@ class Linux(Platform):
|
||||
[ argv[..] (pointer) ] 4 * x
|
||||
[ argv[n - 1] (pointer) ] 4
|
||||
[ argv[n] (pointer) ] 4 (= NULL)
|
||||
|
||||
|
||||
[ envp[0] (pointer) ] 4
|
||||
[ envp[1] (pointer) ] 4
|
||||
[ envp[..] (pointer) ] 4
|
||||
[ envp[term] (pointer) ] 4 (= NULL)
|
||||
|
||||
|
||||
[ auxv[0] (Elf32_auxv_t) ] 8
|
||||
[ auxv[1] (Elf32_auxv_t) ] 8
|
||||
[ auxv[..] (Elf32_auxv_t) ] 8
|
||||
[ auxv[term] (Elf32_auxv_t) ] 8 (= AT_NULL vector)
|
||||
|
||||
|
||||
[ padding ] 0 - 16
|
||||
|
||||
|
||||
[ argument ASCIIZ strings ] >= 0
|
||||
[ environment ASCIIZ str. ] >= 0
|
||||
|
||||
|
||||
(0xbffffffc) [ end marker ] 4 (= NULL)
|
||||
|
||||
|
||||
(0xc0000000) < top of stack > 0 (virtual)
|
||||
----------------------------------------------------------------------
|
||||
'''
|
||||
@ -622,34 +622,35 @@ class Linux(Platform):
|
||||
#The "secure execution" mode of secure_getenv() is controlled by the
|
||||
#AT_SECURE flag contained in the auxiliary vector passed from the
|
||||
#kernel to user space.
|
||||
auxvnames = {'AT_IGNORE': 1, # Entry should be ignored
|
||||
'AT_EXECFD': 2, # File descriptor of program
|
||||
'AT_PHDR': 3, # Program headers for program
|
||||
'AT_PHENT':4, # Size of program header entry
|
||||
'AT_PHNUM':5, # Number of program headers
|
||||
'AT_PAGESZ': 6, # System page size
|
||||
'AT_BASE': 7, # Base address of interpreter
|
||||
'AT_FLAGS':8, # Flags
|
||||
'AT_ENTRY':9, # Entry point of program
|
||||
'AT_NOTELF': 10, # Program is not ELF
|
||||
'AT_UID':11, # Real uid
|
||||
'AT_EUID': 12, # Effective uid
|
||||
'AT_GID':13, # Real gid
|
||||
'AT_EGID': 14, # Effective gid
|
||||
'AT_CLKTCK': 17, # Frequency of times()
|
||||
'AT_PLATFORM': 15, # String identifying platform.
|
||||
'AT_HWCAP':16, # Machine-dependent hints about processor capabilities.
|
||||
'AT_FPUCW':18, # Used FPU control word.
|
||||
'AT_SECURE': 23, # Boolean, was exec setuid-like?
|
||||
'AT_BASE_PLATFORM': 24, # String identifying real platforms.
|
||||
'AT_RANDOM': 25, # Address of 16 random bytes.
|
||||
'AT_EXECFN': 31, # Filename of executable.
|
||||
'AT_SYSINFO':32, #Pointer to the global system page used for system calls and other nice things.
|
||||
'AT_SYSINFO_EHDR': 33, #Pointer to the global system page used for system calls and other nice things.
|
||||
auxvnames = {
|
||||
'AT_IGNORE': 1, # Entry should be ignored
|
||||
'AT_EXECFD': 2, # File descriptor of program
|
||||
'AT_PHDR': 3, # Program headers for program
|
||||
'AT_PHENT':4, # Size of program header entry
|
||||
'AT_PHNUM':5, # Number of program headers
|
||||
'AT_PAGESZ': 6, # System page size
|
||||
'AT_BASE': 7, # Base address of interpreter
|
||||
'AT_FLAGS':8, # Flags
|
||||
'AT_ENTRY':9, # Entry point of program
|
||||
'AT_NOTELF': 10, # Program is not ELF
|
||||
'AT_UID':11, # Real uid
|
||||
'AT_EUID': 12, # Effective uid
|
||||
'AT_GID':13, # Real gid
|
||||
'AT_EGID': 14, # Effective gid
|
||||
'AT_CLKTCK': 17, # Frequency of times()
|
||||
'AT_PLATFORM': 15, # String identifying platform.
|
||||
'AT_HWCAP':16, # Machine-dependent hints about processor capabilities.
|
||||
'AT_FPUCW':18, # Used FPU control word.
|
||||
'AT_SECURE': 23, # Boolean, was exec setuid-like?
|
||||
'AT_BASE_PLATFORM': 24, # String identifying real platforms.
|
||||
'AT_RANDOM': 25, # Address of 16 random bytes.
|
||||
'AT_EXECFN': 31, # Filename of executable.
|
||||
'AT_SYSINFO':32, #Pointer to the global system page used for system calls and other nice things.
|
||||
'AT_SYSINFO_EHDR': 33, #Pointer to the global system page used for system calls and other nice things.
|
||||
}
|
||||
#AT_NULL
|
||||
cpu.push_int(0)
|
||||
cpu.push_int(0)
|
||||
cpu.push_int(0)
|
||||
cpu.push_int(0)
|
||||
for name, val in auxv.items():
|
||||
cpu.push_int(val)
|
||||
cpu.push_int(auxvnames[name])
|
||||
@ -673,14 +674,14 @@ class Linux(Platform):
|
||||
|
||||
def load(self, filename):
|
||||
'''
|
||||
Loads and an ELF program in memory and prepares the initial CPU state.
|
||||
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.
|
||||
|
||||
:param filename: pathname of the file to be executed. (used for auxv)
|
||||
:raises error:
|
||||
- 'Not matching cpu': if the program is compiled for a different architecture
|
||||
- 'Not matching memory': if the program is compiled for a different address size
|
||||
:todo: define va_randomize and read_implies_exec personality
|
||||
:todo: define va_randomize and read_implies_exec personality
|
||||
'''
|
||||
#load elf See binfmt_elf.c
|
||||
#read the ELF object file
|
||||
@ -715,7 +716,7 @@ class Linux(Platform):
|
||||
else:
|
||||
executable_stack = False
|
||||
break
|
||||
|
||||
|
||||
base = 0
|
||||
elf_bss = 0
|
||||
end_code = 0
|
||||
@ -783,7 +784,7 @@ class Linux(Platform):
|
||||
logger.debug("Main elf bss:%x"%elf_bss)
|
||||
logger.debug("Main elf brk %x:"%elf_brk)
|
||||
|
||||
#FIXME Need a way to inspect maps and perms so
|
||||
#FIXME Need a way to inspect maps and perms so
|
||||
#we can rollback all to the initial state after zeroing
|
||||
#if elf_brk-elf_bss > 0:
|
||||
# saved_perms = cpu.mem.perms(elf_bss)
|
||||
@ -805,7 +806,7 @@ class Linux(Platform):
|
||||
else:
|
||||
stack_top = 0x800000000000
|
||||
stack_base = stack_top - stack_size
|
||||
stack = cpu.memory.mmap(stack_base, stack_size, 'rwx', name='stack') + stack_size
|
||||
stack = cpu.memory.mmap(stack_base, stack_size, 'rwx', name='stack') + stack_size
|
||||
assert stack_top == stack
|
||||
|
||||
reserved = cpu.memory.mmap(base+vaddr+memsz,0x1000000,' ')
|
||||
@ -822,7 +823,7 @@ class Linux(Platform):
|
||||
continue
|
||||
align = 0x1000#elf_segment.header.p_align
|
||||
vaddr = elf_segment.header.p_vaddr
|
||||
filesz = elf_segment.header.p_filesz
|
||||
filesz = elf_segment.header.p_filesz
|
||||
flags = elf_segment.header.p_flags
|
||||
offset = elf_segment.header.p_offset
|
||||
memsz = elf_segment.header.p_memsz
|
||||
@ -837,7 +838,7 @@ class Linux(Platform):
|
||||
if base == 0 and interpreter.header.e_type == 'ET_DYN':
|
||||
assert vaddr == 0
|
||||
total_size = self._interp_total_size(interpreter)
|
||||
base = stack_base - total_size
|
||||
base = stack_base - total_size
|
||||
|
||||
if base == 0:
|
||||
assert vaddr == 0
|
||||
@ -846,7 +847,7 @@ class Linux(Platform):
|
||||
if hint == 0:
|
||||
hint = None
|
||||
|
||||
base = cpu.memory.mmapFile(hint, memsz, perms, elf_segment.stream.name, offset)
|
||||
base = cpu.memory.mmapFile(hint, memsz, perms, elf_segment.stream.name, offset)
|
||||
base -= vaddr
|
||||
logger.debug("Loading interpreter offset: %08x addr:%08x %08x %s%s%s" %(offset, base+vaddr, base+vaddr+memsz, (flags&1 and 'r' or ' '), (flags&2 and 'w' or ' '), (flags&4 and 'x' or ' ')))
|
||||
|
||||
@ -902,23 +903,23 @@ class Linux(Platform):
|
||||
at_execfn = cpu.push_bytes(filename+'\x00')
|
||||
|
||||
self.auxv = {
|
||||
'AT_PHDR' : load_addr+elf.header.e_phoff, # Program headers for program
|
||||
'AT_PHDR' : load_addr+elf.header.e_phoff, # Program headers for program
|
||||
'AT_PHENT' : elf.header.e_phentsize, # Size of program header entry
|
||||
'AT_PHNUM' : elf.header.e_phnum, # Number of program headers
|
||||
'AT_PAGESZ' : cpu.memory.page_size, # System page size
|
||||
'AT_BASE' : interpreter_base, # Base address of interpreter
|
||||
'AT_FLAGS' : elf.header.e_flags, # Flags
|
||||
'AT_ENTRY' : elf_entry, # Entry point of program
|
||||
'AT_UID' : 1000, # Real uid
|
||||
'AT_EUID' : 1000, # Effective uid
|
||||
'AT_GID' : 1000, # Real gid
|
||||
'AT_EGID' : 1000, # Effective gid
|
||||
'AT_CLKTCK' : 100, # Frequency of times()
|
||||
'AT_PHNUM' : elf.header.e_phnum, # Number of program headers
|
||||
'AT_PAGESZ' : cpu.memory.page_size, # System page size
|
||||
'AT_BASE' : interpreter_base, # Base address of interpreter
|
||||
'AT_FLAGS' : elf.header.e_flags, # Flags
|
||||
'AT_ENTRY' : elf_entry, # Entry point of program
|
||||
'AT_UID' : 1000, # Real uid
|
||||
'AT_EUID' : 1000, # Effective uid
|
||||
'AT_GID' : 1000, # Real gid
|
||||
'AT_EGID' : 1000, # Effective gid
|
||||
'AT_CLKTCK' : 100, # Frequency of times()
|
||||
'AT_HWCAP' : 0, # Machine-dependent hints about processor capabilities.
|
||||
'AT_RANDOM' : at_random, # Address of 16 random bytes.
|
||||
'AT_EXECFN' : at_execfn, # Filename of executable.
|
||||
}
|
||||
|
||||
|
||||
def _open(self, f):
|
||||
'''
|
||||
It opens a file on the given a file descriptor
|
||||
@ -940,7 +941,7 @@ class Linux(Platform):
|
||||
Closes a file descriptor
|
||||
:rtype: int
|
||||
:param fd: the file descriptor to close.
|
||||
:return: C{0} on success.
|
||||
:return: C{0} on success.
|
||||
'''
|
||||
self.files[fd] = None
|
||||
|
||||
@ -949,7 +950,7 @@ class Linux(Platform):
|
||||
Duplicates a file descriptor
|
||||
:rtype: int
|
||||
:param fd: the file descriptor to close.
|
||||
:return: C{0} on success.
|
||||
:return: C{0} on success.
|
||||
'''
|
||||
return self._open(self.files[fd])
|
||||
|
||||
@ -989,20 +990,20 @@ class Linux(Platform):
|
||||
:param self: current CPU.
|
||||
:param fd: a valid file descriptor
|
||||
:param offset: the offset in bytes
|
||||
:param whence: SEEK_SET: The file offset is set to offset bytes.
|
||||
:param whence: SEEK_SET: The file offset is set to offset bytes.
|
||||
SEEK_CUR: The file offset is set to its current location plus offset bytes.
|
||||
SEEK_END: The file offset is set to the size of the file plus offset bytes.
|
||||
|
||||
|
||||
:return: 0 (Success), or EBADF (fd is not a valid file descriptor or is not open)
|
||||
|
||||
'''
|
||||
if not self._is_open(fd):
|
||||
logger.info("LSEEK: Not valid file descriptor on lseek. Returning EBADF")
|
||||
return errno.EBADF
|
||||
return -errno.EBADF
|
||||
|
||||
if isinstance(self.files[fd], Socket):
|
||||
logger.info("LSEEK: Not valid file descriptor on lseek. Fd not seekable. Returning EBADF")
|
||||
return errno.EBADF
|
||||
return -errno.EBADF
|
||||
|
||||
# Read the data and put in tin memory
|
||||
self.files[fd].seek(offset)
|
||||
@ -1010,18 +1011,18 @@ class Linux(Platform):
|
||||
|
||||
logger.debug("LSEEK(%d, 0x%08x, %d)"%(fd, offset, whence))
|
||||
return 0
|
||||
|
||||
|
||||
def sys_read(self, fd, buf, count):
|
||||
data = ''
|
||||
if count != 0:
|
||||
if not self._is_open(fd):
|
||||
logger.info("READ: Not valid file descriptor on read. Returning EBADF")
|
||||
return errno.EBADF
|
||||
return -errno.EBADF
|
||||
|
||||
# TODO check count bytes from buf
|
||||
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
|
||||
return -errno.EFAULT
|
||||
|
||||
if isinstance(self.files[fd],Socket) and self.files[fd].is_empty():
|
||||
return 0
|
||||
@ -1042,7 +1043,7 @@ class Linux(Platform):
|
||||
|
||||
:param fd a valid file descriptor
|
||||
:param buf a memory buffer
|
||||
:param count number of bytes to send
|
||||
:param count number of bytes to send
|
||||
:return: 0 Success
|
||||
EBADF fd is not a valid file descriptor or is not open.
|
||||
EFAULT buf or tx_bytes points to an invalid address.
|
||||
@ -1077,12 +1078,12 @@ class Linux(Platform):
|
||||
|
||||
def sys_access(self, buf, mode):
|
||||
'''
|
||||
Checks real user's permissions for a file
|
||||
Checks real user's permissions for a file
|
||||
:rtype: int
|
||||
|
||||
|
||||
:param buf: a buffer containing the pathname to the file to check its permissions.
|
||||
:param mode: the access permissions to check.
|
||||
:return:
|
||||
:return:
|
||||
- C{0} if the calling process can access the file in the desired mode.
|
||||
- C{-1} if the calling process can not access the file in the desired mode.
|
||||
'''
|
||||
@ -1108,7 +1109,7 @@ class Linux(Platform):
|
||||
Writes system information in the variable C{old_utsname}.
|
||||
:rtype: int
|
||||
:param old_utsname: the buffer to write the system info.
|
||||
:return: C{0} on success
|
||||
:return: C{0} on success
|
||||
'''
|
||||
from datetime import datetime
|
||||
|
||||
@ -1134,7 +1135,7 @@ class Linux(Platform):
|
||||
:rtype: int
|
||||
:param brk: the new address for C{elf_brk}.
|
||||
:return: the value of the new C{elf_brk}.
|
||||
:raises error:
|
||||
:raises error:
|
||||
- "Error in brk!" if there is any error allocating the memory
|
||||
'''
|
||||
if brk != 0:
|
||||
@ -1147,13 +1148,13 @@ class Linux(Platform):
|
||||
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
|
||||
return self.elf_brk
|
||||
|
||||
def sys_arch_prctl(self, code, addr):
|
||||
'''
|
||||
Sets architecture-specific thread state
|
||||
:rtype: int
|
||||
|
||||
|
||||
:param code: must be C{ARCH_SET_FS}.
|
||||
:param addr: the base address of the FS segment.
|
||||
:return: C{0} on success
|
||||
@ -1174,7 +1175,7 @@ class Linux(Platform):
|
||||
if fd > 2:
|
||||
return self.files[fd].ioctl(request, argp)
|
||||
else:
|
||||
return -errno.EINVAL
|
||||
return -errno.EINVAL
|
||||
|
||||
|
||||
def sys_open(self, buf, flags, mode):
|
||||
@ -1244,7 +1245,7 @@ class Linux(Platform):
|
||||
def sys_getpid(self, v):
|
||||
logger.debug("GETPID, warning pid modeled as concrete 1000")
|
||||
return 1000
|
||||
|
||||
|
||||
def sys_ARM_NR_set_tls(self, val):
|
||||
if hasattr(self, '_arm_tls_memory'):
|
||||
self.current.write_int(self._arm_tls_memory, val)
|
||||
@ -1276,7 +1277,7 @@ class Linux(Platform):
|
||||
Closes a file descriptor
|
||||
:rtype: int
|
||||
:param fd: the file descriptor to close.
|
||||
:return: C{0} on success.
|
||||
:return: C{0} on success.
|
||||
'''
|
||||
if fd > 0 :
|
||||
self._close(fd)
|
||||
@ -1287,9 +1288,9 @@ class Linux(Platform):
|
||||
'''
|
||||
Read
|
||||
:rtype: int
|
||||
|
||||
|
||||
:param path: the "link path id"
|
||||
:param buf: the buffer where the bytes will be putted.
|
||||
:param buf: the buffer where the bytes will be putted.
|
||||
:param bufsize: the max size for read the link.
|
||||
:todo: Out eax number of bytes actually sent | EAGAIN | EBADF | EFAULT | EINTR | errno.EINVAL | EIO | ENOSPC | EPIPE
|
||||
'''
|
||||
@ -1306,10 +1307,10 @@ class Linux(Platform):
|
||||
|
||||
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].
|
||||
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 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.
|
||||
@ -1324,10 +1325,10 @@ class Linux(Platform):
|
||||
'''
|
||||
Unmaps a file from memory. It deletes the mappings for the specified address range
|
||||
:rtype: int
|
||||
|
||||
|
||||
:param addr: the starting address to unmap.
|
||||
:param size: the size of the portion to unmap.
|
||||
:return: C{0} on success.
|
||||
:return: C{0} on success.
|
||||
'''
|
||||
self.current.memory.munmap(addr, size)
|
||||
return 0
|
||||
@ -1336,32 +1337,32 @@ class Linux(Platform):
|
||||
'''
|
||||
Gets user identity.
|
||||
:rtype: int
|
||||
|
||||
:return: this call returns C{1000} for all the users.
|
||||
|
||||
:return: this call returns C{1000} for all the users.
|
||||
'''
|
||||
return 1000
|
||||
def sys_getgid(self):
|
||||
'''
|
||||
Gets group identity.
|
||||
:rtype: int
|
||||
|
||||
:return: this call returns C{1000} for all the groups.
|
||||
|
||||
:return: this call returns C{1000} for all the groups.
|
||||
'''
|
||||
return 1000
|
||||
def sys_geteuid(self):
|
||||
'''
|
||||
Gets user identity.
|
||||
:rtype: int
|
||||
|
||||
:return: This call returns C{1000} for all the users.
|
||||
|
||||
:return: This call returns C{1000} for all the users.
|
||||
'''
|
||||
return 1000
|
||||
def sys_getegid(self):
|
||||
'''
|
||||
Gets group identity.
|
||||
:rtype: int
|
||||
|
||||
:return: this call returns C{1000} for all the groups.
|
||||
|
||||
:return: this call returns C{1000} for all the groups.
|
||||
'''
|
||||
return 1000
|
||||
|
||||
@ -1395,9 +1396,9 @@ class Linux(Platform):
|
||||
'''
|
||||
Works just like C{sys_write} except that multiple buffers are written out.
|
||||
:rtype: int
|
||||
|
||||
|
||||
:param fd: the file descriptor of the file to write.
|
||||
:param iov: the buffer where the the bytes to write are taken.
|
||||
: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.
|
||||
'''
|
||||
@ -1422,9 +1423,9 @@ class Linux(Platform):
|
||||
'''
|
||||
Sets a thread local storage (TLS) area. Sets the base address of the GS segment.
|
||||
:rtype: int
|
||||
|
||||
|
||||
:param user_info: the TLS array entry set corresponds to the value of C{u_info->entry_number}.
|
||||
:return: C{0} on success.
|
||||
:return: C{0} on success.
|
||||
'''
|
||||
n = self.current.read_int(user_info, 32)
|
||||
pointer = self.current.read_int(user_info + 4, 32)
|
||||
@ -1439,9 +1440,9 @@ class Linux(Platform):
|
||||
|
||||
def sys_getpriority(self, which, who):
|
||||
'''
|
||||
System call ignored.
|
||||
System call ignored.
|
||||
:rtype: int
|
||||
|
||||
|
||||
:return: C{0}
|
||||
'''
|
||||
logger.debug("Ignoring sys_get_priority")
|
||||
@ -1451,7 +1452,7 @@ class Linux(Platform):
|
||||
'''
|
||||
System call ignored.
|
||||
:rtype: int
|
||||
|
||||
|
||||
:return: C{0}
|
||||
'''
|
||||
logger.debug("Ignoring sys_setpriority")
|
||||
@ -1461,7 +1462,7 @@ class Linux(Platform):
|
||||
'''
|
||||
System call not implemented.
|
||||
:rtype: int
|
||||
|
||||
|
||||
:return: C{-1}
|
||||
'''
|
||||
logger.debug("BSD account not implemented!")
|
||||
@ -1517,7 +1518,7 @@ class Linux(Platform):
|
||||
|
||||
#Distpatchers...
|
||||
def syscall(self):
|
||||
'''
|
||||
'''
|
||||
Syscall dispatcher.
|
||||
'''
|
||||
|
||||
@ -1594,7 +1595,7 @@ class Linux(Platform):
|
||||
for fd in writefds:
|
||||
self.twait[fd].add(self._current)
|
||||
if timeout is not None:
|
||||
self.timers[self._current] = self.clocks + timeout
|
||||
self.timers[self._current] = self.clocks + timeout
|
||||
procid = self._current
|
||||
#self.sched()
|
||||
next_index = (self.running.index(procid) + 1) % len(self.running)
|
||||
@ -1664,7 +1665,7 @@ class Linux(Platform):
|
||||
Execute one cpu instruction in the current thread (only one supported).
|
||||
:rtype: bool
|
||||
:return: C{True}
|
||||
|
||||
|
||||
:todo: This is where we could implement a simple schedule.
|
||||
"""
|
||||
syscallret = None
|
||||
@ -1682,17 +1683,17 @@ class Linux(Platform):
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
#64bit syscalls
|
||||
|
||||
|
||||
def sys_newfstat(self, fd, buf):
|
||||
'''
|
||||
Determines information about a file based on its file descriptor.
|
||||
:rtype: int
|
||||
: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.
|
||||
:param buf: a buffer where data about the file will be stored.
|
||||
:return: C{0} on success.
|
||||
'''
|
||||
stat = self.files[fd].stat()
|
||||
|
||||
@ -1716,7 +1717,7 @@ class Linux(Platform):
|
||||
bufstat += add(4, stat.st_gid) # 32 gid
|
||||
bufstat += add(4, 0) # 32 _pad
|
||||
bufstat += add(nw, stat.st_rdev) # long st_rdev
|
||||
bufstat += add(nw, stat.st_size) # long st_size
|
||||
bufstat += add(nw, stat.st_size) # long st_size
|
||||
bufstat += add(nw, stat.st_blksize) # long st_blksize
|
||||
bufstat += add(nw, stat.st_blocks) # long st_blocks
|
||||
bufstat += to_timespec(nw, stat.st_atime) # long st_atime, nsec;
|
||||
@ -1734,9 +1735,9 @@ class Linux(Platform):
|
||||
Determines information about a file based on its file descriptor (for Linux 64 bits).
|
||||
:rtype: int
|
||||
:param fd: the file descriptor of the file that is being inquired.
|
||||
:param buf: a buffer where data about the file will be stored.
|
||||
:param buf: a buffer where data about the file will be stored.
|
||||
:return: C{0} on success.
|
||||
:todo: Fix device number.
|
||||
:todo: Fix device number.
|
||||
'''
|
||||
stat = self.files[fd].stat()
|
||||
|
||||
@ -1766,7 +1767,7 @@ class Linux(Platform):
|
||||
bufstat += to_timespec(stat.st_mtime) # unsigned long st_mtime;
|
||||
bufstat += to_timespec(stat.st_ctime) # unsigned long st_ctime;
|
||||
bufstat += add(8, stat.st_ino) # unsigned long long st_ino;
|
||||
|
||||
|
||||
self.current.write_bytes(buf, bufstat)
|
||||
return 0
|
||||
|
||||
@ -1781,8 +1782,8 @@ class Linux(Platform):
|
||||
Determines information about a file based on its filename (for Linux 64 bits).
|
||||
:rtype: int
|
||||
: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.
|
||||
:param buf: a buffer where data about the file will be stored.
|
||||
:return: C{0} on success.
|
||||
'''
|
||||
return self._stat(path, buf, True)
|
||||
|
||||
@ -1797,7 +1798,7 @@ class Linux(Platform):
|
||||
ret = self.sys_fstat(fd, buf)
|
||||
self.sys_close(fd)
|
||||
return ret
|
||||
|
||||
|
||||
def _arch_specific_init(self):
|
||||
assert self.arch in {'i386', 'amd64', 'armv7'}
|
||||
|
||||
@ -1901,8 +1902,8 @@ class SLinux(Linux):
|
||||
Determines information about a file based on its file descriptor.
|
||||
:rtype: int
|
||||
: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.
|
||||
:param buf: a buffer where data about the file will be stored.
|
||||
:return: C{0} on success.
|
||||
'''
|
||||
stat = self.files[fd].stat()
|
||||
|
||||
@ -1940,43 +1941,43 @@ class SLinux(Linux):
|
||||
return self.sys_mmap2(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 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.
|
||||
:param prot: the desired memory protection of the mapping.
|
||||
:param flags: determines whether updates to the mapping are visible to other
|
||||
processes mapping the same region, and whether updates are carried
|
||||
through to the underlying file.
|
||||
:param fd: the contents of a file mapping are initialized using C{size} bytes starting at
|
||||
:param flags: determines whether updates to the mapping are visible to other
|
||||
processes mapping the same region, and whether updates are carried
|
||||
through to the underlying file.
|
||||
:param fd: the contents of a file mapping are initialized using C{size} bytes starting at
|
||||
offset C{offset} in the file referred to by the file descriptor C{fd}.
|
||||
:param offset: the contents of a file mapping are initialized using C{size} bytes starting at
|
||||
:param offset: the contents of a file mapping are initialized using C{size} bytes starting at
|
||||
offset C{offset}*0x1000 in the file referred to by the file descriptor C{fd}.
|
||||
:return:
|
||||
:return:
|
||||
- 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(address, size, prot, flags, fd, offset*0x1000)
|
||||
|
||||
def sys_mmap(self, address, size, prot, flags, fd, offset):
|
||||
'''
|
||||
Creates a new mapping in the virtual address space of the calling process.
|
||||
'''
|
||||
Creates a new mapping in the virtual address space of the calling process.
|
||||
:rtype: int
|
||||
|
||||
|
||||
: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.
|
||||
:param prot: the desired memory protection of the mapping.
|
||||
:param flags: determines whether updates to the mapping are visible to other
|
||||
processes mapping the same region, and whether updates are carried
|
||||
through to the underlying file.
|
||||
:param fd: the contents of a file mapping are initialized using C{size} bytes starting at
|
||||
:param flags: determines whether updates to the mapping are visible to other
|
||||
processes mapping the same region, and whether updates are carried
|
||||
through to the underlying file.
|
||||
:param fd: the contents of a file mapping are initialized using C{size} bytes starting at
|
||||
offset C{offset} in the file referred to by the file descriptor C{fd}.
|
||||
:param offset: the contents of a file mapping are initialized using C{size} bytes starting at
|
||||
:param offset: the contents of a file mapping are initialized using C{size} bytes starting at
|
||||
offset C{offset} in the file referred to by the file descriptor C{fd}.
|
||||
:return:
|
||||
:return:
|
||||
- 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 (that must be the same as address in case you included C{MAP_FIXED} in flags).
|
||||
:todo: handle exception.
|
||||
@ -2041,7 +2042,7 @@ class DecreeEmu(object):
|
||||
|
||||
@staticmethod
|
||||
def cgc_random(platform, buf, count, rnd_bytes):
|
||||
import cgcrandom
|
||||
from . import cgcrandom
|
||||
if issymbolic(buf):
|
||||
logger.info("Ask to write random bytes to a symbolic buffer")
|
||||
raise ConcretizeArgument(0)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user