def callafter(self, pid, call, result, state): if call == 'rt_sigaction' or call == 'sigaction' or call == 'signal': if state != None and not (-1024 < result < 0): sig = state[0] f = self.allflags[pid] handler = state[1] if sig == signal.SIGCHLD: sa_flags = ptrace.peekdata(pid, handler + 4) f['SA_NOCLDSTOP'] = sa_flags & 0x1 # SA_NOCLDSTOP else: if call != 'signal': handler = ptrace.peekdata(pid, handler) f[signalmap.lookup_name(sig)] = handler elif call == 'wait4' or call == 'waitpid': f = self.allflags[pid] if f.has_key('waitresult'): wpid, statusptr, status = f['waitresult'] del f['waitresult'] del f['waiting'] if statusptr != 0: try: ptrace.pokedata(pid, statusptr, status) except OSError, e: if e.errno != errno.ESRCH: # FIX assert 0, "wait status pointer bad? (%s)" % e else: print 'waiter dead or not stopped' # XXX return wpid # XXX: is this actually correct and useful? if result == -errno_internal.ERESTARTNOHAND: # like pause return -errno_internal.ERESTARTSYS # like wait
def callbefore(self, pid, call, args): # delay read/write calls here according to bandwidth limit # track network fds (including across fork/vfork/clone) if not self.fds.has_key(pid): self.fds[pid] = {} if call == 'socketcall': subcall = args[0] if subcall == 1: # socket # FIX: might fail if ptrace.peekdata(pid, args[1]) == socket.AF_INET: return (('fd', ), None, None, None) elif subcall == 5: # accept return (('fd', ), None, None, None) elif call == 'dup' or call == 'dup2': return (('dup', args[0]), None, None, None) elif call == 'close': return (('close', args[0]), None, None, None) elif call == 'open': # if open works, we missed prior close (on fork/exec?) return (('open', ), None, None, None) elif call == 'fork' or call == 'vfork' or call == 'clone': return (('fork', pid), None, None, None) elif call == 'read' or call == 'write': if self.fds[pid].has_key(args[0]): #print 'io: [%s] %s on %s of %s bytes' % (pid, call, args[0], args[2]) return (('netio', ), None, None, None)
def callbefore(self, pid, call, args): # delay read/write calls here according to bandwidth limit # track network fds (including across fork/vfork/clone) if not self.fds.has_key(pid): self.fds[pid] = {} if call == 'socketcall': subcall = args[0] if subcall == 1: # socket # FIX: might fail if ptrace.peekdata(pid, args[1]) == socket.AF_INET: return (('fd',), None, None, None) elif subcall == 5: # accept return (('fd',), None, None, None) elif call == 'dup' or call == 'dup2': return (('dup', args[0]), None, None, None) elif call == 'close': return (('close', args[0]), None, None, None) elif call == 'open': # if open works, we missed prior close (on fork/exec?) return (('open',), None, None, None) elif call == 'fork' or call == 'vfork' or call == 'clone': return (('fork', pid), None, None, None) elif call == 'read' or call == 'write': if self.fds[pid].has_key(args[0]): #print 'io: [%s] %s on %s of %s bytes' % (pid, call, args[0], args[2]) return (('netio',), None, None, None)
def callbefore(self, pid, call, args): # print pid, call, args def doreadwrite(callt, args): # print 'doreadwrite',call,callt,args, fd = args[0] pfd = pid, fd fdinfo = self.__do_fail.get(pfd, None) # if fdinfo: # print fdinfo if fdinfo and callt in fdinfo.modes: if callt == 'r': #after = self.afterr if not fdinfo.rerrs: return after = min([err.after for err in fdinfo.rerrs]) failinfo = fdinfo.r else: #after = self.afterw if not fdinfo.werrs: return after = min([err.after for err in fdinfo.werrs]) failinfo = fdinfo.w failcount, bytes = failinfo.failed, failinfo.bytes if failcount > 5: print 'exiting on %ith failed %s of %i' % (failcount, callt, pfd) import sys sys.exit(1) if bytes < after: size = args[2] if bytes + size > after: size = after - bytes print pfd, callt, (fd, args[1], size), 'was', args return (pfd, None, None, (fd, args[1], size)) failinfo.failed += 1 print pid, 'failing', call, callt, '#%i' % failcount, 'for fd', fd return (pfd, -errno.EIO, None, None) # else: # print 'allowing',call,'for',args[0] if call == 'read': return doreadwrite('r', args) elif call == 'write': return doreadwrite('w', args) elif call == 'close': fd = args[0] pfd = pid, fd fdinfo = self.__do_fail.get(pfd, None) # print pfd, call, args, fdinfo if fdinfo and fdinfo.cerrs: return (pfd, -errno.EIO, None, None) return (pfd, None, None, None) elif call == 'dup' or call == 'dup2': return (args[0], None, None, None) elif call == 'open': getarg = Memory.getMemory(pid).get_string fn = getarg(args[0]) # print pid,call,[fn]+args[1:],args[1]&O_ACCMODE fes = [] m = '' flags = args[1] & O_ACCMODE for fe in self.ferrs: if (flags == os.O_RDWR or (flags == os.O_WRONLY and 'w' in fe.modes) or (flags == os.O_RDONLY and 'r' in fe.modes)): if fe.match.search(fn): fes.append(fe) if fes: fdinfo = FDInfo(fes) #if flags == FCNTL.O_WRONLY: # after = min([err.after for err in fdinfo.werrs]) #elif flags == FCNTL.O_RDONLY: # after = min([err.after for err in fdinfo.rerrs]) #else: #elif flags == FCNTL.O_RDWR: after = min([err.after for err in fdinfo.errs]) if after < 0: print pid, 'failing', call, [fn] + args[1:] return (None, -errno.EIO, None, None) return (fdinfo, None, None, None) elif call == 'socketcall': # print pid, call, args subcall = args[0] do = 0 if subcall == 1: # socket # FIX: might fail if ptrace.peekdata(pid, args[1]) in (socket.AF_INET, socket.AF_INET6): do = -2 elif subcall == 3: # connect do = -1 elif subcall == 4: # listen do = -1 elif subcall == 5: # accept do = -1 elif subcall in (9, 10): # send/recv if subcall == 9: # send r = doreadwrite('w', (ptrace.peekdata( pid, args[1]), ptrace.peekdata(pid, args[1] + 4), ptrace.peekdata(pid, args[1] + 8))) subcalln = 'write' elif subcall == 10: # recv r = doreadwrite('r', (ptrace.peekdata( pid, args[1]), ptrace.peekdata(pid, args[1] + 4), ptrace.peekdata(pid, args[1] + 8))) subcalln = 'read' if not r or r[ 1]: # if default return or error, we can return it with no probs. return r #otherwise we have to convert from doreadwrite return which is in read()/write() format to socketcall format ptrace.pokedata(args[1] + 8, r[3][2]) # set new recv/write size return ((subcalln, r[0]), r[1], r[2], args) if do: #ses = [] #for se in self.serrs: after = min([err.after for err in self.serrs]) if after == do: print pid, 'failing', call, args return (None, -errno.EIO, None, None) errs = [err for err in self.serrs if err.after >= 0] if errs: fdinfo = FDInfo(errs) return (('open', fdinfo), None, None, None) elif call == 'rename': getarg = Memory.getMemory(pid).get_string sfn = getarg(args[0]) dfn = getarg(args[1]) # print pid,call,sfn,dfn for rene in self.renameerrs: if rene.srcmatch.search(sfn) and rene.dstmatch.search(dfn): print pid, 'failing', call, sfn, dfn return (None, -errno.EIO, None, None)
def _get_timeval_2(pid, addr): sec = ptrace.peekdata(pid, addr) usec = ptrace.peekdata(pid, addr + 4) return (sec, usec)
def _readbyte(self, address): """Read one byte (ptrace allows us to read words, only). This needs to be changed for non-i386.""" word = ptrace.peekdata(self.pid, address & ~3) return (word >> ((address & 3) * 8)) & 0xFF
def _readbyte(self, address): """Read one byte (ptrace allows us to read words, only). This needs to be changed for non-i386.""" word = ptrace.peekdata(self.pid, address & ~3) return (word >> ((address & 3)*8)) & 0xff