def wrapped_func(): try: function() except: # Exit if they throw an uncaught exception tracebackrepy.handle_exception() harshexit.harshexit(30)
def run(self): # Elevate our priority, set us to the highest so that we can more effectively throttle success = windows_api.set_current_thread_priority(windows_api.THREAD_PRIORITY_HIGHEST) # If we failed to get HIGHEST priority, try above normal, else we're still at default if not success: windows_api.set_current_thread_priority(windows_api.THREAD_PRIORITY_ABOVE_NORMAL) # Run while the process is running while True: try: # Get the frequency frequency = repy_constants.CPU_POLLING_FREQ_WIN # Base amount of sleeping on return value of # win_check_cpu_use to prevent under/over sleeping slept = win_check_cpu_use(nanny_resource_limits.resource_limit("cpu"), self.pid) if slept == -1: # Something went wrong, try again pass elif (slept < frequency): time.sleep(frequency-slept) except windows_api.DeadProcess: # Process may be dead harshexit.harshexit(97) except: tracebackrepy.handle_exception() print >> sys.stderr, "CPU Nanny died! Trying to kill everything else" harshexit.harshexit(25)
def execute_namespace_until_completion(thisnamespace, thiscontext): # I'll use this to detect when the program is idle so I know when to quit... idlethreadcount = threading.activeCount() # add my thread to the set of threads that are used... event_id = idhelper.getuniqueid() try: nanny.tattle_add_item('events', event_id) except Exception as e: tracebackrepy.handle_internalerror("Failed to acquire event for '" + \ "initialize' event.\n(Exception was: %s)" % e.message, 140) try: thisnamespace.evaluate(thiscontext) except SystemExit: raise except: # I think it makes sense to exit if their code throws an exception... tracebackrepy.handle_exception() harshexit.harshexit(6) finally: nanny.tattle_remove_item('events', event_id) # I've changed to the threading library, so this should increase if there are # pending events while threading.activeCount() > idlethreadcount: # do accounting here? time.sleep(0.25) # Once there are no more events, return... return
def main(options): #prepare network interfaces if options.verbose: print >> sys.stderr, "Preparing networking interfaces %s" % options.interface prepare_interfaces(options.interface) #move file to tmp dir and chown it to executing user if options.verbose: print >> sys.stderr, "Reading program from %s" % options.program try: fp = open(options.program) usercode = fp.read() finally: fp.close() #build usercontext if options.verbose: print >> sys.stderr, "Building script context" import time, nonportable nonportable.getruntime = time.time #change getruntime to time.time to gain preformance build_context(options.quiet) #change directory to directory of safe_check.py os.chdir(os.path.dirname(os.path.realpath(sys.argv[0]))) #drop privileges if not options.runasroot: if options.verbose: print >> sys.stderr, "Dropping privileges (%s)" % options.runas drop_privileges(options.runas_uid, options.runas_gid) else: if options.verbose: print >> sys.stderr, "Not dropping privileges !!!" #run script try: if options.verbose: print >> sys.stderr, "Checking script %s" % options.program namespace = virtual_namespace.VirtualNamespace(usercode, options.program) usercode = None # allow the (potentially large) code string to be garbage collected if options.verbose: print >> sys.stderr, "Initializing resource restrictions %s" % options.resources repy.initialize_nanny(options.resources) if options.verbose: print >> sys.stderr, "Running script %s, arguments = %s" % ( options.program, options.arguments) context = repy.get_safe_context(options.arguments) repy.execute_namespace_until_completion(namespace, context) except KeyboardInterrupt: return except SystemExit: pass except: tracebackrepy.handle_exception() try: import time while True: time.sleep(1.0) except KeyboardInterrupt: return
def wrapped_func(): try: function() except: # Exit if they throw an uncaught exception tracebackrepy.handle_exception() harshexit.harshexit(30) finally: # Remove the event before I exit nanny.tattle_remove_item('events', eventhandle)
def wrapped_func(): try: function() except: # Exit if they throw an uncaught exception tracebackrepy.handle_exception() harshexit.harshexit(30) finally: # Remove the event before I exit nanny.tattle_remove_item('events',eventhandle)
def run(self): # How often the memory will be checked (seconds) memory_check_interval = repy_constants.CPU_POLLING_FREQ_WIN # The ratio of the disk polling time to memory polling time. disk_to_memory_ratio = int(repy_constants.DISK_POLLING_HDD / memory_check_interval) # Which cycle number we're on counter = 0 # Elevate our priority, above normal is higher than the usercode, and is enough for disk/mem windows_api.set_current_thread_priority( windows_api.THREAD_PRIORITY_ABOVE_NORMAL) # need my pid to get a process handle... mypid = os.getpid() # run forever (only exit if an error occurs) while True: try: # Increment the interval counter counter += 1 # Check memory use, get the WorkingSetSize or RSS memused = windows_api.process_memory_info( mypid)['WorkingSetSize'] if memused > nanny.get_resource_limit("memory"): # We will be killed by the other thread... raise Exception, "Memory use '" + str( memused) + "' over limit '" + str( nanny.get_resource_limit("memory")) + "'" # Check if we should check the disk if (counter % disk_to_memory_ratio) == 0: # Check diskused diskused = compute_disk_use( repy_constants.REPY_CURRENT_DIR) if diskused > nanny.get_resource_limit("diskused"): raise Exception, "Disk use '" + str( diskused) + "' over limit '" + str( nanny.get_resource_limit("diskused")) + "'" # Sleep until the next iteration of checking the memory time.sleep(memory_check_interval) except windows_api.DeadProcess: # Process may be dead, or die while checking memory use # In any case, there is no reason to continue running, just exit harshexit.harshexit(99) except: tracebackrepy.handle_exception() print >> sys.stderr, "Nanny died! Trying to kill everything else" harshexit.harshexit(20)
def main(options): #prepare network interfaces if options.verbose: print >>sys.stderr, "Preparing networking interfaces %s" % options.interface prepare_interfaces(options.interface) #move file to tmp dir and chown it to executing user if options.verbose: print >>sys.stderr, "Reading program from %s" % options.program try: fp = open(options.program) usercode = fp.read() finally: fp.close() #build usercontext if options.verbose: print >>sys.stderr, "Building script context" import time, nonportable nonportable.getruntime = time.time #change getruntime to time.time to gain preformance build_context(options.quiet) #change directory to directory of safe_check.py os.chdir(os.path.dirname(os.path.realpath(sys.argv[0]))) #drop privileges if not options.runasroot: if options.verbose: print >>sys.stderr, "Dropping privileges (%s)" % options.runas drop_privileges(options.runas_uid, options.runas_gid) else: if options.verbose: print >>sys.stderr, "Not dropping privileges !!!" #run script try: if options.verbose: print >>sys.stderr, "Checking script %s" % options.program namespace = virtual_namespace.VirtualNamespace(usercode, options.program) usercode = None # allow the (potentially large) code string to be garbage collected if options.verbose: print >>sys.stderr, "Initializing resource restrictions %s" % options.resources repy.initialize_nanny(options.resources) if options.verbose: print >>sys.stderr, "Running script %s, arguments = %s" % (options.program, options.arguments) context = repy.get_safe_context(options.arguments) repy.execute_namespace_until_completion(namespace, context) except KeyboardInterrupt: return except SystemExit: pass except: tracebackrepy.handle_exception() try: import time while True: time.sleep(1.0) except KeyboardInterrupt: return
def run(self): # How often the memory will be checked (seconds) memory_check_interval = repy_constants.CPU_POLLING_FREQ_WIN # The ratio of the disk polling time to memory polling time. disk_to_memory_ratio = int(repy_constants.DISK_POLLING_HDD / memory_check_interval) # Which cycle number we're on counter = 0 # Elevate our priority, above normal is higher than the usercode, and is enough for disk/mem windows_api.set_current_thread_priority(windows_api.THREAD_PRIORITY_ABOVE_NORMAL) # need my pid to get a process handle... mypid = os.getpid() # run forever (only exit if an error occurs) while True: try: # Increment the interval counter counter += 1 # Check memory use, get the WorkingSetSize or RSS memused = windows_api.process_memory_info(mypid)["WorkingSetSize"] if memused > nanny.get_resource_limit("memory"): # We will be killed by the other thread... raise Exception, "Memory use '" + str(memused) + "' over limit '" + str( nanny.get_resource_limit("memory") ) + "'" # Check if we should check the disk if (counter % disk_to_memory_ratio) == 0: # Check diskused diskused = compute_disk_use(repy_constants.REPY_CURRENT_DIR) if diskused > nanny.get_resource_limit("diskused"): raise Exception, "Disk use '" + str(diskused) + "' over limit '" + str( nanny.get_resource_limit("diskused") ) + "'" # Sleep until the next iteration of checking the memory time.sleep(memory_check_interval) except windows_api.DeadProcess: # Process may be dead, or die while checking memory use # In any case, there is no reason to continue running, just exit harshexit.harshexit(99) except: tracebackrepy.handle_exception() print >> sys.stderr, "Nanny died! Trying to kill everything else" harshexit.harshexit(20)
def run(self): # Calculate how often disk should be checked if ostype == "WindowsCE": disk_interval = int(repy_constants.RESOURCE_POLLING_FREQ_WINCE / repy_constants.CPU_POLLING_FREQ_WINCE) else: disk_interval = int(repy_constants.RESOURCE_POLLING_FREQ_WIN / repy_constants.CPU_POLLING_FREQ_WIN) current_interval = 0 # What cycle are we on # Elevate our priority, above normal is higher than the usercode, and is enough for disk/mem windows_api.set_current_thread_priority(windows_api.THREAD_PRIORITY_ABOVE_NORMAL) # need my pid to get a process handle... mypid = os.getpid() # run forever (only exit if an error occurs) while True: try: # Check memory use, get the WorkingSetSize or RSS memused = windows_api.process_memory_info(mypid)['WorkingSetSize'] if memused > nanny_resource_limits.resource_limit("memory"): # We will be killed by the other thread... raise Exception, "Memory use '"+str(memused)+"' over limit '"+str(nanny_resource_limits.resource_limit("memory"))+"'" # Increment the interval we are on current_interval += 1 # Check if we should check the disk if (current_interval % disk_interval) == 0: # Check diskused diskused = compute_disk_use(repy_constants.REPY_CURRENT_DIR) if diskused > nanny_resource_limits.resource_limit("diskused"): raise Exception, "Disk use '"+str(diskused)+"' over limit '"+str(nanny_resource_limits.resource_limit("diskused"))+"'" if ostype == 'WindowsCE': time.sleep(repy_constants.CPU_POLLING_FREQ_WINCE) else: time.sleep(repy_constants.CPU_POLLING_FREQ_WIN) except windows_api.DeadProcess: # Process may be dead, or die while checking memory use # In any case, there is no reason to continue running, just exit harshexit.harshexit(99) except: tracebackrepy.handle_exception() print >> sys.stderr, "Nanny died! Trying to kill everything else" harshexit.harshexit(20)
def main(): if len(sys.argv) != 4: print "Error, didn't get the right number of args:",sys.argv sys.exit(1) ppid = int(sys.argv[1]) limit = float(sys.argv[2]) freq = float(sys.argv[3]) # run forever, checking the process' CPU use and stopping when appropriate try: while True: # Base amount of sleeping on return value of win_check_cpu_use to prevent under/over sleeping slept = nonportable.win_check_cpu_use(limit, ppid) if slept == -1: # Something went wrong, try again pass elif slept == 0: time.sleep(freq) elif (slept < freq): time.sleep(freq-slept) # see if the process exited... status = windows_api.process_exit_code(ppid) # Amazing! They rely on the programmer to not return 259 to know when # something actually exited. Luckily, I do control the return codes... if status != 259: sys.exit(0) except SystemExit: pass except windows_api.DeadProcess: # This can be caused when getting process times for a dead thread or # Trying to timeout a dead thread, either way, we just exit sys.exit(0) except: tracebackrepy.handle_exception() print >> sys.stderr, "Win nanny died! Trying to kill everything else" # kill the program we're monitoring # Use newer api to kill process windows_api.kill_process(ppid)
def functionwrapper(func, timerhandle, args): #restrictions ? # call the function with the arguments try: if timerhandle in timerinfo: del timerinfo[timerhandle] else: # I've been "stopped" by canceltimer return except KeyError: # I've been "stopped" by canceltimer return try: func(*args) except: # Exit if they throw an uncaught exception tracebackrepy.handle_exception() harshexit.harshexit(30) # remove the event before I exit nanny.tattle_remove_item('events',timerhandle)
def functionwrapper(func, timerhandle, args): #restrictions ? # call the function with the arguments try: if timerhandle in timerinfo: del timerinfo[timerhandle] else: # I've been "stopped" by canceltimer return except KeyError: # I've been "stopped" by canceltimer return try: func(*args) except: # Exit if they throw an uncaught exception tracebackrepy.handle_exception() harshexit.harshexit(30) # remove the event before I exit nanny.tattle_remove_item('events', timerhandle)
def repy_main(argv=sys.argv): """Run repy with these command line arguments""" global simpleexec global logfile # Armon: The CMD line path to repy is the first argument repy_location = argv[0] # Get the directory repy is in repy_directory = os.path.dirname(repy_location) # Translate into an absolute path if os.path.isabs(repy_directory): absolute_repy_directory = repy_directory else: # This will join the currect directory with the relative path # and then get the absolute path to that location absolute_repy_directory = os.path.abspath(os.path.join(os.getcwd(), repy_directory)) # Store the absolute path as the repy startup directory repy_constants.REPY_START_DIR = absolute_repy_directory # For security, we need to make sure that the Python path doesn't change even # if the directory does... newsyspath = [] for item in sys.path[:]: if item == '' or item == '.': newsyspath.append(os.getcwd()) else: newsyspath.append(item) # It should be safe now. I'm assuming the user isn't trying to undercut us # by setting a crazy python path sys.path = newsyspath args = argv[1:] try: optlist, fnlist = getopt.getopt(args, '', [ 'simple', 'ip=', 'iface=', 'nootherips', 'logfile=', 'stop=', 'status=', 'cwd=', 'servicelog', 'safebinary' ]) except getopt.GetoptError: usage() sys.exit(1) # Set up the simple variable if needed simpleexec = False # By default we don't want to use the service logger servicelog = False # Default logfile (if the option --logfile isn't passed) logfile = None # Default stopfile (if the option --stopfile isn't passed) stopfile = None # Default stopfile (if the option --stopfile isn't passed) statusfile = None if len(fnlist) < 2: usage("Must supply a resource file and a program file to execute") sys.exit(1) for option, value in optlist: if option == '--simple': simpleexec = True elif option == '--ip': emulcomm.user_ip_interface_preferences = True # Append this ip to the list of available ones if it is new, since # multiple IP's may be specified if (True, value) not in emulcomm.user_specified_ip_interface_list: emulcomm.user_specified_ip_interface_list.append((True, value)) elif option == '--iface': emulcomm.user_ip_interface_preferences = True # Append this interface to the list of available ones if it is new if (False, value) not in emulcomm.user_specified_ip_interface_list: emulcomm.user_specified_ip_interface_list.append((False, value)) # Check if they have told us explicitly not to allow other IP's elif option == '--nootherips': # Set user preference to True emulcomm.user_ip_interface_preferences = True # Disable nonspecified IP's emulcomm.allow_nonspecified_ips = False elif option == '--logfile': # set up the circular log buffer... logfile = value elif option == '--stop': # Watch for the creation of this file and abort when it happens... stopfile = value elif option == '--status': # Write status information into this file... statusfile = value # Set Current Working Directory elif option == '--cwd': os.chdir(value) # Enable logging of internal errors to the service logger. elif option == '--servicelog': servicelog = True # Enable safe binary mode elif option == '--safebinary': safebinary.SAFEBINARY = True # Update repy current directory repy_constants.REPY_CURRENT_DIR = os.path.abspath(os.getcwd()) # Initialize the NM status interface nmstatusinterface.init(stopfile, statusfile) # Write out our initial status statusstorage.write_status("Started") resourcefn = fnlist[0] progname = fnlist[1] progargs = fnlist[2:] # We also need to pass in whether or not we are going to be using the service # log for repy. We provide the repy directory so that the vessel information # can be found regardless of where we are called from... tracebackrepy.initialize(servicelog, absolute_repy_directory) try: main(resourcefn, progname, progargs) except SystemExit: harshexit.harshexit(4) except: tracebackrepy.handle_exception() harshexit.harshexit(3)
"initialize' event.\n(Exception was: %s)" % e.message, 140) try: if profile: p = cProfile.Profile() p.runctx('main_namespace.evaluate(usercontext)', globals(), locals(),) p = pstats.Stats(p) # p.sort_stats('cumulative') p.print_stats() else: main_namespace.evaluate(usercontext) except SystemExit: raise except: # I think it makes sense to exit if their code throws an exception... tracebackrepy.handle_exception() harshexit.harshexit(6) finally: nanny.tattle_remove_item('events', event_id) # I've changed to the threading library, so this should increase if there are # pending events while threading.activeCount() > idlethreadcount: # do accounting here? time.sleep(0.25) # Once there are no more pending events for the user thread, we exit harshexit.harshexit(0)
def main(): repy_location = sys.argv[0] repy_directory = os.path.dirname(repy_location) init_repy_location(repy_directory) usage = "USAGE: repy.py [options] program_to_run.r2py [program args]" parser = optparse.OptionParser(usage=usage) parser.disable_interspersed_args() add_repy_options(parser) options, args = parser.parse_args() if len(args) < 1: print("Repy requires a program to run!") parser.print_help() sys.exit(1) #resourcefn = args[0] progname = args[0] progargs = args[1:] parse_options(options) nmstatusinterface.launch(None) try: filehandle = open(progname) usercode = filehandle.read() filehandle.close() except: print( f"FATAL ERROR: Unable to read the specified program file: {progname}" ) sys.exit(1) try: newnamespace = virtual_namespace.VirtualNamespace(usercode, progname) except CodeUnsafeError as e: print("Specified repy program is unsafe!") print("Static-code analysis failed with error: " + str(e)) harshexit.harshexit(5) del usercode if options.execinfo: print("=" * 40) print("Running program: " + progname) print("Arguments: " + progargs) print("=" * 40) newcontext = get_safe_context(progargs) try: newnamespace.evaluate(newcontext) except SystemExit: raise except: tracebackrepy.handle_exception() harshexit.harshexit(6) harshexit.harshexit(0)
def repy_main(argv=sys.argv): """Run repy with these command line arguments""" global simpleexec global logfile # Armon: The CMD line path to repy is the first argument repy_location = argv[0] # Get the directory repy is in repy_directory = os.path.dirname(repy_location) # Translate into an absolute path if os.path.isabs(repy_directory): absolute_repy_directory = repy_directory else: # This will join the currect directory with the relative path # and then get the absolute path to that location absolute_repy_directory = os.path.abspath( os.path.join(os.getcwd(), repy_directory)) # Store the absolute path as the repy startup directory repy_constants.REPY_START_DIR = absolute_repy_directory # For security, we need to make sure that the Python path doesn't change even # if the directory does... newsyspath = [] for item in sys.path[:]: if item == '' or item == '.': newsyspath.append(os.getcwd()) else: newsyspath.append(item) # It should be safe now. I'm assuming the user isn't trying to undercut us # by setting a crazy python path sys.path = newsyspath args = argv[1:] try: optlist, fnlist = getopt.getopt(args, '', [ 'simple', 'ip=', 'iface=', 'nootherips', 'logfile=', 'stop=', 'status=', 'cwd=', 'servicelog', 'safebinary' ]) except getopt.GetoptError: usage() sys.exit(1) # Set up the simple variable if needed simpleexec = False # By default we don't want to use the service logger servicelog = False # Default logfile (if the option --logfile isn't passed) logfile = None # Default stopfile (if the option --stopfile isn't passed) stopfile = None # Default stopfile (if the option --stopfile isn't passed) statusfile = None if len(fnlist) < 2: usage("Must supply a resource file and a program file to execute") sys.exit(1) for option, value in optlist: if option == '--simple': simpleexec = True elif option == '--ip': emulcomm.user_ip_interface_preferences = True # Append this ip to the list of available ones if it is new, since # multiple IP's may be specified if (True, value) not in emulcomm.user_specified_ip_interface_list: emulcomm.user_specified_ip_interface_list.append((True, value)) elif option == '--iface': emulcomm.user_ip_interface_preferences = True # Append this interface to the list of available ones if it is new if (False, value) not in emulcomm.user_specified_ip_interface_list: emulcomm.user_specified_ip_interface_list.append( (False, value)) # Check if they have told us explicitly not to allow other IP's elif option == '--nootherips': # Set user preference to True emulcomm.user_ip_interface_preferences = True # Disable nonspecified IP's emulcomm.allow_nonspecified_ips = False elif option == '--logfile': # set up the circular log buffer... logfile = value elif option == '--stop': # Watch for the creation of this file and abort when it happens... stopfile = value elif option == '--status': # Write status information into this file... statusfile = value # Set Current Working Directory elif option == '--cwd': os.chdir(value) # Enable logging of internal errors to the service logger. elif option == '--servicelog': servicelog = True # Enable safe binary mode elif option == '--safebinary': safebinary.SAFEBINARY = True # Update repy current directory repy_constants.REPY_CURRENT_DIR = os.path.abspath(os.getcwd()) # Initialize the NM status interface nmstatusinterface.init(stopfile, statusfile) # Write out our initial status statusstorage.write_status("Started") resourcefn = fnlist[0] progname = fnlist[1] progargs = fnlist[2:] # We also need to pass in whether or not we are going to be using the service # log for repy. We provide the repy directory so that the vessel information # can be found regardless of where we are called from... tracebackrepy.initialize(servicelog, absolute_repy_directory) try: main(resourcefn, progname, progargs) except SystemExit: harshexit.harshexit(4) except: tracebackrepy.handle_exception() harshexit.harshexit(3)
usercontext['callargs'] = args[:] initialize_id = idhelper.getuniqueid() try: nanny.tattle_add_item('events', initialize_id) except Exception, e: tracebackrepy.handle_internalerror("Failed to aquire event for '" + \ "initialize' event.\n(Exception was: %s)" % e.message, 140) try: main_namespace.evaluate(usercontext) except SystemExit: raise except: # I think it makes sense to exit if their code throws an exception... tracebackrepy.handle_exception() harshexit.harshexit(6) finally: nanny.tattle_remove_item('events', initialize_id) # I've changed to the threading library, so this should increase if there are # pending events while threading.activeCount() > idlethreadcount: # do accounting here? time.sleep(0.25) # Once there are no more pending events for the user thread, we give them # an "exit" event. This allows them to clean up, etc. if needed.