def open_queue(name, create=False, consume=False): """Open a message queue via a context manager The message queue will automatically be closed when the context ends. The message queue may also optionally be created and/or consumed. If the "consume" flag is True, the message queue will be unlinked as well when the context ends. Args: name (str): the name of the message queue create (bool): whether to create the message queue or try to open a pre-existing one. consume (bool): whether or not to unlink the message queue when the context ends. Yields: posix_ipc.MessageQueue: the message queue """ flags = 0 if create: flags = posix_ipc.O_CREX queue = MessageQueue(name, flags=flags) try: yield queue finally: queue.close() if consume: queue.unlink()
def pi(n): pids = [] unit = n / 10 q = Queue("/pi", flags=os.O_CREAT) for i in range(10): mink = unit * i maxk = mink + unit pid = os.fork() if pid > 0: pids.append(pid) else: s = slice(mink, maxk) q.send(str(s)) q.close() sys.exit(0) sums = [] for pid in pids: sums.append(float(q.receive()[0])) os.waitpid(pid, 0) q.close() q.unlink() return math.sqrt(sum(sums) * 8)
class RemoteMemoryProtocol(object): """ This class listens to memoryforward requests and lifts them to avatar messages. Likewise it can be directed to emit memoryforward-response messages :param rx_queue_name: Name of the queue for receiving :param tx_queue_name: Name of the queue for sending :param avatar_queue: Queue to dispatch received requests to :param origin: Reference to the Target utilizing this protocol """ def __init__(self, rx_queue_name, tx_queue_name, avatar_queue, origin=None): self._rx_queue = None self._tx_queue = None self._rx_listener = None self.rx_queue_name = rx_queue_name self.tx_queue_name = tx_queue_name self._avatar_queue = avatar_queue self._origin = origin self.log = logging.getLogger('%s.%s' % (origin.log.name, self.__class__.__name__) ) if origin else \ logging.getLogger(self.__class__.__name__) def connect(self): """ Connect to the message queues for remote memory :return True on success, else False """ try: self._rx_queue = MessageQueue(self.rx_queue_name, flags=O_RDONLY, read=True, write=False) except Exception as e: self.log.error("Unable to create rx_queue: %s" % e) return False try: self._tx_queue = MessageQueue(self.tx_queue_name, flags=O_WRONLY, read=False, write=True) except Exception as e: self.log.error("Unable to create tx_queue: %s" % e) self._rx_queue.close() return False self._rx_listener = RemoteMemoryRequestListener( self._rx_queue, self._avatar_queue, self._origin) self._rx_listener.daemon = True self._rx_listener.start() self.log.info("Successfully connected rmp") return True def __del__(self): self.shutdown() def shutdown(self): if self._rx_listener: self._rx_listener.stop() self._rx_listener = None if self._rx_queue: try: self._rx_queue.unlink() self._rx_queue.close() self._rx_queue = None except ExistentialError: self.log.warning("Tried to close/unlink non existent rx_queue") if self._tx_queue: try: self._tx_queue.unlink() self._tx_queue.close() self._tx_queue = None except ExistentialError: self.log.warning("Tried to close/unlink non existent tx_queue") def send_response(self, id, value, success): response = RemoteMemoryResp(id, value, success) try: self._tx_queue.send(response) self.log.debug("Send RemoteMemoryResponse with id %d, %x" % (id, value)) return True except Exception as e: self.log.error("Unable to send response: %s" % e) return False
class ARMV7MInterruptProtocol(Thread): """ This protocol has two purposes: a) injecting interrupts into an analysis target b) extracting interrupt exits and putting them into the avatar queue (b) is necessary in cases where two targets need to be synched on the interrupts. The way a v7m-nvic implements interrupt return is to put a magic value into $pc, and the hardware does the actual magic of popping from the interrupt stack and restoring the context. However, the magic value defines the type of the interrupt return, and is hence synchronized on interrupt exit, alongside with the interrupt number :param origin: Reference to the Target utilizing this protocol :param rx_queue_name: Name of the queue for receiving :param tx_queue_name: Name of the queue for sending """ def __init__(self, origin, rx_queue_name, tx_queue_name): super(self.__class__, self).__init__() self._rx_queue_name = rx_queue_name self._tx_queue_name = tx_queue_name self._rx_queue = None self._tx_queue = None self._avatar_queue = origin.avatar.queue self._origin = origin self._close = Event() self._closed = Event() self._close.clear() self._closed.clear() self.log = logging.getLogger('%s.%s' % (origin.log.name, self.__class__.__name__) ) if origin else \ logging.getLogger(self.__class__.__name__) def run(self): while True: if self._close.is_set(): break request = None try: request = self._rx_queue.receive(0.5) except: continue req_struct = V7MRemoteInterruptNotification.from_buffer_copy( request[0]) if RINOperation(req_struct.operation) == RINOperation.ENTER: msg = RemoteInterruptEnterMessage(self._origin, req_struct.id, req_struct.num_irq) elif RINOperation(req_struct.operation) == RINOperation.EXIT: msg = RemoteInterruptExitMessage(self._origin, req_struct.id, req_struct.type, req_struct.num_irq) self.log.debug( "Received an InterruptExitRequest for irq %d (%x)" % (req_struct.num_irq, req_struct.type)) else: msg = None raise Exception( ("Received V7MRemoteInterrupt Notification with" "unknown operation type %d") % req_struct.operation) self._avatar_queue.put(msg) self._closed.set() def stop(self): self._close.set() self._closed.wait() def enable_interrupts(self): if isinstance(self._origin, QemuTarget): # TODO: Make this more clean, i.e., check for remote memory rmem_rx_qname = self._origin.protocols.remote_memory.rx_queue_name rmem_tx_qname = self._origin.protocols.remote_memory.tx_queue_name # the tx-queue for qemu is the rx-queue for avatar and vice versa self._origin.protocols.monitor.execute_command( 'avatar-armv7m-enable-irq', { 'irq_rx_queue_name': self._tx_queue_name, 'irq_tx_queue_name': self._rx_queue_name, 'rmem_rx_queue_name': rmem_tx_qname, 'rmem_tx_queue_name': rmem_rx_qname }) else: raise Exception("V7MInterruptProtocol is not implemented for %s" % self._origin.__class__) try: self._rx_queue = MessageQueue(self._rx_queue_name, flags=O_RDONLY, read=True, write=False) except Exception as e: self.log.error("Unable to create rx_queue: %s" % e) return False try: self._tx_queue = MessageQueue(self._tx_queue_name, flags=O_WRONLY, read=False, write=True) except Exception as e: self.log.error("Unable to create tx_queue: %s" % e) self._rx_queue.close() return False self.daemon = True self.start() self.log.info("Enabled Interrupt Forwarding for %s" % self._origin) return True def ignore_interrupt_return(self, interrupt_number): if isinstance(self._origin, QemuTarget): self.log.info("Disable handling of irq return for %d" % interrupt_number) self._origin.protocols.monitor.execute_command( 'avatar-armv7m-ignore-irq-return', {'num_irq': interrupt_number}) def unignore_interrupt_return(self, interrupt_number): if isinstance(self._origin, QemuTarget): self.log.info("Re-enable handling of irq return for %d" % interrupt_number) self._origin.protocols.monitor.execute_command( 'avatar-armv7m-unignore-irq-return', {'num_irq': interrupt_number}) def inject_interrupt(self, interrupt_number, cpu_number=0): if isinstance(self._origin, QemuTarget): self.log.info("Injecting interrupt %d" % interrupt_number) self._origin.protocols.monitor.execute_command( 'avatar-armv7m-inject-irq', { 'num_irq': interrupt_number, 'num_cpu': cpu_number }) def set_vector_table_base(self, base, cpu_number=0): if isinstance(self._origin, QemuTarget): self.log.info("Setting vector table base to 0x%x" % base) self._origin.protocols.monitor.execute_command( 'avatar-armv7m-set-vector-table-base', { 'base': base, 'num_cpu': cpu_number }) def send_interrupt_exit_response(self, id, success): response = V7MInterruptNotificationAck(id, success, RINOperation.EXIT.value) try: self._tx_queue.send(response) self.log.debug("Send RemoteInterruptExitResponse with id %d" % id) return True except Exception as e: self.log.error("Unable to send response: %s" % e) return False def send_interrupt_enter_response(self, id, success): response = V7MInterruptNotificationAck(id, success, RINOperation.ENTER.value) try: self._tx_queue.send(response) self.log.debug("Send RemoteInterruptEnterResponse with id %d" % id) return True except Exception as e: self.log.error("Unable to send response: %s" % e) return False def __del__(self): self.shutdown() def shutdown(self): self.stop() if self._rx_queue: try: self._rx_queue.unlink() self._rx_queue.close() self._rx_queue = None except ExistentialError: self.log.warning("Tried to close/unlink non existent rx_queue") if self._tx_queue: try: self._tx_queue.unlink() self._tx_queue.close() self._tx_queue = None except ExistentialError: self.log.warning("Tried to close/unlink non existent tx_queue")
from posix_ipc import MessageQueue as MsgQ import sysv_ipc import os if __name__ == '__main__': q = MsgQ("/tmp", flags=os.O_CREAT, mode=0666) q.send("adfg") rec = q.receive(1) print rec q.close() q.unlink() q2 = sysv_ipc.MessageQueue(16842753, flags=sysv_ipc.IPC_CREAT) q2.send("sferogh", type=1)