Esempio n. 1
0
def call_parent(pid, rpipe):
    try:
        status = os.waitpid(pid, 0)[1]
    except:
        os.close(rpipe)
        raise
    if status != 0:
        if os.WIFSIGNALED(status):
            signum = os.WTERMSIG(status)
            if signum == SIGALRM:
                raise Timeout()
            text = "subprocess killed by signal %s" % signum
        elif os.WIFEXITED(status):
            exitcode = os.WEXITSTATUS(status)
            text = "subprocess failed with exit code %s" % exitcode
        else:
            text = "subprocess failed"
        raise SandboxError(text)
    rpipe_file = os.fdopen(rpipe, 'rb')
    try:
        data = pickle.load(rpipe_file)
    finally:
        rpipe_file.close()
    if 'error' in data:
        raise data['error']
    return data['result']
Esempio n. 2
0
def call_parent(config, pid, rpipe):
    import signal
    sigkill = signal.SIGKILL
    try:
        status = wait_child(config, pid, sigkill)
    except:
        os.close(rpipe)
        raise
    if status != 0:
        if os.WIFSIGNALED(status):
            signum = os.WTERMSIG(status)
            text = "subprocess killed by signal %s" % signum
        elif os.WIFEXITED(status):
            exitcode = os.WEXITSTATUS(status)
            text = "subprocess failed with exit code %s" % exitcode
        else:
            text = "subprocess failed"
        raise SandboxError(text)
    rpipe_file = os.fdopen(rpipe, 'rb')
    try:
        data = pickle.load(rpipe_file)
    finally:
        rpipe_file.close()
    if 'error' in data:
        raise data['error']
    return data['result']
Esempio n. 3
0
    def test():
        class A(object):
            pass

        class B(object):
            pass

        class X(A):
            pass

        X.__bases__ = (B, )
        if not issubclass(X, B):
            raise SandboxError("yep")
Esempio n. 4
0
 def proxy(value):
     if isinstance(value, SAFE_TYPES):
         # Safe type, no need to create a proxy
         return value
     elif callable(value):
         return callback_proxy(proxy, value)
     elif isinstance(value, tuple):
         return tuple(proxy(item) for item in value)
     elif isinstance(value, list):
         return createReadOnlyList(value)
     elif isinstance(value, dict):
         return createReadOnlyDict(value)
     elif isinstance(value, OBJECT_TYPES):
         return createReadOnlyObject(value)
     else:
         raise SandboxError("Unable to proxy a value of type %s" %
                            type(value))
Esempio n. 5
0
 def proxy(value):
     if isinstance(value, SAFE_TYPES):
         # Safe type, no need to create a proxy
         return value
     elif is_callable(value):
         return callback_proxy(proxy, value)
     elif isinstance(value, tuple):
         return tuple(proxy(item) for item in value)
     elif isinstance(value, list):
         return createReadOnlyList(value)
     elif isinstance(value, dict):
         return createReadOnlyDict(value)
     elif isinstance(value, OBJECT_TYPES):
         return createReadOnlyObject(value)
     elif str(value.__class__) == "<type 'code'>":
         # This is a horrible horrible hack; it should be able to compare with the actual
         # "code" type. However no proxy is needed as code objects are immutable; see
         # http://docs.python.org/reference/datamodel.html
         return value
     else:
         raise SandboxError("Unable to proxy a value of type %s" %
                            type(value))
Esempio n. 6
0
def execute_subprocess(sandbox, code, globals, locals):
    old_umask = os.umask(0177)
    try:
        input_file = tempfile.NamedTemporaryFile()
        output_file = tempfile.NamedTemporaryFile()
    finally:
        os.umask(old_umask)

    try:
        input_data = {
            'code': code,
            'config': sandbox.config,
            'locals': locals,
            'globals': globals,
        }
        args = (
            sys.executable,
            # FIXME: use '-S'
            '-E',
            '-m',
            'sandbox.subprocess_child',
            input_file.name,
            output_file.name)
        pickle.dump(input_data, input_file)
        input_file.flush()
        if sandbox.config.max_input_size:
            size = input_file.tell()
            if size > sandbox.config.max_input_size:
                raise SandboxError(
                    "Input data are too big: %s bytes (max=%s)" %
                    (size, sandbox.config.max_input_size))

        # create the subprocess
        process = subprocess.Popen(args, close_fds=True, shell=False)

        # wait data
        exitcode = process.wait()
        if exitcode:
            if os.name != "nt" and exitcode < 0:
                signum = -exitcode
                if signum == SIGALRM:
                    raise Timeout()
                text = "subprocess killed by signal %s" % signum
            else:
                text = "subprocess failed with exit code %s" % exitcode
            raise SandboxError(text)

        if sandbox.config.max_output_size:
            output_file.seek(0, 2)
            size = output_file.tell()
            output_file.seek(0)
            if size > sandbox.config.max_output_size:
                raise SandboxError(
                    "Output data are too big: %s bytes (max=%s)" %
                    (size, sandbox.config.max_output_size))
        output_data = pickle.load(output_file)
    finally:
        input_file.close()
        output_file.close()

    if 'error' in output_data:
        raise output_data['error']
    if locals is not None:
        locals.clear()
        locals.update(output_data['locals'])
    if globals is not None:
        globals.clear()
        globals.update(output_data['globals'])
    return output_data['result']
Esempio n. 7
0
def readOnlyError():
    raise SandboxError("Read only object")
Esempio n. 8
0
def execute_subprocess(sandbox, code, globals, locals):
    config = sandbox.config
    input_filename = tempfile.mktemp()
    output_filename = tempfile.mktemp()
    args = (
        sys.executable,
        # FIXME: use '-S'
        '-E',
        '-m',
        'sandbox.subprocess_child',
        input_filename,
        output_filename,
    )

    input_data = {
        'code': code,
        'config': config,
        'locals': locals,
        'globals': globals,
    }

    try:
        # serialize input data
        with open(input_filename, 'wb') as input_file:
            pickle.dump(input_data, input_file)
            if config.max_input_size:
                size = input_file.tell()
                if size > config.max_input_size:
                    raise SandboxError(
                        "Input data are too big: %s bytes (max=%s)" %
                        (size, config.max_input_size))

        # create the subprocess
        process = subprocess.Popen(args, close_fds=True, shell=False)

        # wait process exit
        if config.timeout:
            timeout = monotonic_time() + config.timeout
            kill = False
            exitcode = process.poll()
            while exitcode is None:
                dt = timeout - monotonic_time()
                if dt < 0:
                    process.terminate()
                    exitcode = process.wait()
                    raise Timeout()

                if dt > 1.0:
                    pause = 0.5
                else:
                    pause = 0.1
                # TODO: handle SIGCHLD to avoid wasting time in polling
                time.sleep(pause)
                exitcode = process.poll()
        else:
            exitcode = process.wait()
        os.unlink(input_filename)
        input_filename = None

        # handle child process error
        if exitcode:
            if os.name != "nt" and exitcode < 0:
                signum = -exitcode
                text = "subprocess killed by signal %s" % signum
            else:
                text = "subprocess failed with exit code %s" % exitcode
            raise SandboxError(text)

        with open(output_filename, 'rb') as output_file:
            if config.max_output_size:
                output_file.seek(0, 2)
                size = output_file.tell()
                output_file.seek(0)
                if size > config.max_output_size:
                    raise SandboxError(
                        "Output data are too big: %s bytes (max=%s)" %
                        (size, config.max_output_size))
            output_data = pickle.load(output_file)
        os.unlink(output_filename)
        output_filename = None
    finally:
        temp_filenames = []
        if input_filename is not None:
            temp_filenames.append(input_filename)
        if output_filename is not None:
            temp_filenames.append(output_filename)
        for filename in temp_filenames:
            try:
                os.unlink(filename)
            except OSError:
                pass

    if 'error' in output_data:
        raise output_data['error']
    if locals is not None:
        locals.clear()
        locals.update(output_data['locals'])
    if globals is not None:
        globals.clear()
        globals.update(output_data['globals'])
    return output_data['result']
Esempio n. 9
0
 def safe_exit(code=0):
     raise SandboxError("exit() function blocked by the sandbox")
Esempio n. 10
0
 def _blocked(name):
     raise SandboxError("Block access to sys.%s.%s" % (stream_name, name))