Author: Armin Rigo <[email protected]>
Branch: sandbox-2
Changeset: r97295:f4ba641484fa
Date: 2019-08-27 10:33 +0200
http://bitbucket.org/pypy/pypy/changeset/f4ba641484fa/

Log:    Write docs about the @sandbox_review() and
        llexternal(sandboxsafe=..).

diff --git a/rpython/translator/sandbox/graphchecker.py 
b/rpython/translator/sandbox/graphchecker.py
--- a/rpython/translator/sandbox/graphchecker.py
+++ b/rpython/translator/sandbox/graphchecker.py
@@ -2,8 +2,92 @@
 This runs at the start of the database-c step, so it excludes the
 graphs produced later, notably for the GC.  These are "low-level"
 graphs that are assumed to be safe.
+
+Here are again the rules around this check.
+
+- any graph that contains only "safe" lloperations is itself "safe".
+  The "safe" lloperations are the ones marked "tryfold" in
+  rtyper.lltypesystem.lloperation, plus the ones listed explicitly below,
+  plus a few variants of specific operations coded in graph_in_unsafe().
+
+- any graph decorated with @objectmodel.sandbox_review() is "safe".
+  The different flags we can pass to @sandbox_review() are explained next,
+  but the decorated graph is itself always "safe".
+
+- "unsafe" operations are all special rare operations, plus most importantly
+  all *writes* into raw memory.  We assume that *reads* from anywhere are
+  OK to ignore: any information that reaches the sandboxed process can be
+  detected and used by anything that runs inside this process (i.e. there
+  is no really "secret" data inside the sandboxed subprocess itself).
+  At worst, random reads will lead to segfaults.  But random writes are not
+  safe because that could corrupt memory---e.g. overwrite some GC object
+  header, or even (although I'm not sure how) actually cause the sandboxed
+  process to misbehave in more important ways like doing actual system calls
+  that are supposed to be forbidden.
+
+- the decorator @sandbox_review(check_caller=True) means that the graph is
+  safe, but any call to this graph from somewhere else is an unsafe operation.
+  This forces all callers to also be reviewed and marked with some form of
+  @sandbox_review().
+
+- @sandbox_review(reviewed=True) means that the graph is safe and all
+  calls to this graph are also safe.  This should only be used on functions
+  that do internally "unsafe" stuff like writing to raw memory but don't
+  take arguments that could lead them to do bogus things.  A typical counter-
+  example is a function that takes a raw pointer and that writes something to
+  it; this should *not* be marked with reviewed=True.  On the other hand, many
+  RPython wrappers to external C functions can be reviewed=True because
+  they translate GC-safe information (say an RPython string) to raw memory,
+  do the call, and translate the result back to GC-safe information.
+
+- @sandbox_review(abort=True) is reserved for cases where calling this
+  function at runtime should just immediately abort the subprocess.
+
+Note that all flags above should be considered independently of what the
+actual C function calls are supposed to do.  For example, the RPython
+wrapper rposix.system() is something you definitely don't want to allow as-is,
+but the wrapper and the call to the C function are fine.  It's up to the
+controlling process to refuse to reply to the system() external call
+(either by having it return ENOSYS or a similar error, or by killing the
+sandboxed process completely).
+
+Like system(), all calls to external C functions are *by default* removed and
+turned into I/O on stdin/stdout, asking the parent controlling process what
+to do.  This is controlled in more details by rffi.llexternal().  It takes
+its own argument "sandboxsafe", which can be one of the following values:
+
+- sandboxsafe=False (the default): the external C call is not done but turned
+  into I/O on stdin/stdout.  Moreover, *if* the function takes or returns a
+  raw pointer, then it is flagged with @sandbox_review(check_caller=True) to
+  ensure that all callers do something sane with these raw pointers.  If
+  the C function only takes and returns integer or float arguments, there is
+  no real need, so in this case we flag @sandbox_review(reviewed=True) instead.
+
+- sandboxsafe=True: means the external call should be done straight from the
+  sandboxed process.  Reserved for specific functions like rposix.c_strerror(),
+  or some memory-manipulation functions used by the GC itself.
+
+- sandboxsafe="abort": like @sandbox_review(abort=True).
+
+- sandboxsafe="check_caller": forces @sandbox_review(check_caller=True).
+  Useful for llexternal() functions that appear to return an integer but
+  that's really some address that must be carefully managed.
+
+- sandboxsafe="nowrite": forces @sandbox_review(reviewed=True).  This is OK
+  for C functions that have pointer arguments but none of them can point
+  to anything that will be written to (hence the name).  The idea is that
+  for the common case of a function that takes a "const char *" argument,
+  we should just mark that function as reviewed=True, because it is safe:
+  the controller process will at most read things from the sandboxed process,
+  namely what the pointer points to, but it should not attempt to do any
+  write into the sandboxed process' memory.  Typically the caller itself
+  calls rffi.str2charp() and rffi.free_charp() around the call, but these
+  are also @sandbox_review(reviewed=True) helpers, so such a caller doesn't
+  need to be explicitly reviewed.
+
 """
 
+
 from rpython.flowspace.model import SpaceOperation, Constant
 from rpython.rtyper.rmodel import inputconst
 from rpython.rtyper.lltypesystem import lltype, llmemory, rstr
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to