racket/sandbox: use `gui-available?' at sandbox creation
Previously, sandbox creation used `gui?', which is the result of `gui-available?' at the time that `racket/sandbox' is instanited. This change makes sandbox behavior less sensitive tothe order in which modules `require'd into a program are intiantiated. The change depends on a new `sandbox-make-namespace' default function for `sandbox-namespace-specs'. The new function uses either `make-base-namespace' or `make-gui-namespace', depending on whether the GUI library is available at that point. A new `sandbox-gui-enabled' parameter can disable use of the GUI library even if it is available. The `gui?' binding is still exported for backward compatibility, but it shouldn't be used anymore.
This commit is contained in:
parent
a976c56cb9
commit
5630a3a1ca
|
@ -10,6 +10,7 @@
|
|||
setup/dirs)
|
||||
|
||||
(provide gui?
|
||||
sandbox-gui-available
|
||||
sandbox-init-hook
|
||||
sandbox-reader
|
||||
sandbox-input
|
||||
|
@ -23,6 +24,7 @@
|
|||
sandbox-security-guard
|
||||
sandbox-network-guard
|
||||
sandbox-exit-handler
|
||||
sandbox-make-namespace
|
||||
sandbox-make-inspector
|
||||
sandbox-make-code-inspector
|
||||
sandbox-make-logger
|
||||
|
@ -53,12 +55,16 @@
|
|||
exn:fail:resource?
|
||||
exn:fail:resource-resource)
|
||||
|
||||
; for backward compatibility; maybe it should be removed:
|
||||
(define gui? (gui-available?))
|
||||
|
||||
;; When this parameter is #t, it is adjusted when creating a sandbox:
|
||||
(define sandbox-gui-available (make-parameter #t (lambda (v) (and v #t))))
|
||||
|
||||
(define-syntax mz/mr ; use a value for plain racket, or pull a gui binding
|
||||
(syntax-rules ()
|
||||
[(mz/mr mzval mrsym)
|
||||
(if gui? (gui-dynamic-require 'mrsym) mzval)]))
|
||||
(if (sandbox-gui-available) (gui-dynamic-require 'mrsym) mzval)]))
|
||||
|
||||
;; Configuration ------------------------------------------------------------
|
||||
|
||||
|
@ -85,8 +91,11 @@
|
|||
[sandbox-eval-handlers '(#f #f)])
|
||||
(thunk)))
|
||||
|
||||
(define (sandbox-make-namespace)
|
||||
((mz/mr make-base-namespace make-gui-namespace)))
|
||||
|
||||
(define sandbox-namespace-specs
|
||||
(make-parameter `(,(mz/mr make-base-namespace make-gui-namespace)
|
||||
(make-parameter `(,sandbox-make-namespace
|
||||
#| no modules here by default |#)))
|
||||
|
||||
(define (default-sandbox-reader source)
|
||||
|
@ -613,15 +622,7 @@
|
|||
(uncovered! (list (get) get)))
|
||||
(when (namespace? ns) (current-namespace ns)))
|
||||
|
||||
(define current-eventspace (mz/mr (make-parameter #f) current-eventspace))
|
||||
(define make-eventspace (mz/mr void make-eventspace))
|
||||
(define run-in-bg (mz/mr thread queue-callback))
|
||||
(define null-input (open-input-bytes #""))
|
||||
(define bg-run->thread
|
||||
(if gui?
|
||||
(lambda (ignored)
|
||||
((mz/mr void eventspace-handler-thread) (current-eventspace)))
|
||||
values))
|
||||
|
||||
;; special message values for the evaluator procedure, also inside the user
|
||||
;; context they're used for function applications.
|
||||
|
@ -879,6 +880,8 @@
|
|||
memory-cust))
|
||||
(parameterize* ; the order in these matters
|
||||
(;; create a sandbox context first
|
||||
[sandbox-gui-available (and (sandbox-gui-available)
|
||||
(gui-available?))]
|
||||
[current-custodian user-cust]
|
||||
[current-thread-group (make-thread-group)]
|
||||
;; paths
|
||||
|
@ -944,17 +947,24 @@
|
|||
[current-command-line-arguments '#()]
|
||||
;; Finally, create the namespace in the restricted environment (in
|
||||
;; particular, it must be created under the new code inspector)
|
||||
[current-namespace (make-evaluation-namespace)]
|
||||
[current-namespace (make-evaluation-namespace)])
|
||||
(define current-eventspace (mz/mr (make-parameter #f) current-eventspace))
|
||||
(parameterize*
|
||||
;; Note the above definition of `current-eventspace': in Racket, it
|
||||
;; is an unused parameter. Also note that creating an eventspace
|
||||
;; starts a thread that will eventually run the callback code (which
|
||||
;; evaluates the program in `run-in-bg') -- so this parameterization
|
||||
;; must be nested in the above (which is what paramaterize* does), or
|
||||
;; it will not use the new namespace.
|
||||
[current-eventspace (parameterize-break #f (make-eventspace))])
|
||||
(define t (bg-run->thread (run-in-bg user-process)))
|
||||
(set! user-done-evt (handle-evt t (lambda (_) (terminate+kill! #t #t))))
|
||||
(set! user-thread t))
|
||||
([current-eventspace (parameterize-break #f ((mz/mr void make-eventspace)))])
|
||||
(define run-in-bg (mz/mr thread queue-callback))
|
||||
(define bg-run->thread (if (sandbox-gui-available)
|
||||
(lambda (ignored)
|
||||
((mz/mr void eventspace-handler-thread) (current-eventspace)))
|
||||
values))
|
||||
(define t (bg-run->thread (run-in-bg user-process)))
|
||||
(set! user-done-evt (handle-evt t (lambda (_) (terminate+kill! #t #t))))
|
||||
(set! user-thread t)))
|
||||
(define r (get-user-result))
|
||||
(if (eq? r 'ok)
|
||||
;; initial program executed ok, so return an evaluator
|
||||
|
|
|
@ -128,8 +128,10 @@ argument:
|
|||
|
||||
In this case, a new namespace is created using
|
||||
@racket[sandbox-namespace-specs], which by default creates a
|
||||
new namespace using @racket[make-base-namespace] or
|
||||
@racket[make-gui-namespace] (depending on @racket[gui?]).
|
||||
new namespace using @racket[sandbox-make-namespace] (which, in
|
||||
turn, uses @racket[make-base-namespace] or
|
||||
@racket[make-gui-namespace] depending on
|
||||
@racket[sandbox-gui-available] and @racket[gui-available?]).
|
||||
|
||||
In the new namespace, @racket[language] is evaluated as an
|
||||
expression to further initialize the namespace.}
|
||||
|
@ -188,7 +190,8 @@ In all cases, the evaluator operates in an isolated and limited
|
|||
environment:
|
||||
@itemize[
|
||||
|
||||
@item{It uses a new custodian and namespace. When @racket[gui?] is
|
||||
@item{It uses a new custodian and namespace. When
|
||||
@racket[gui-available?] and @racket[sandbox-gui-available] produce
|
||||
true, it is also runs in its own eventspace.}
|
||||
|
||||
@item{The evaluator works under the @racket[sandbox-security-guard],
|
||||
|
@ -463,9 +466,7 @@ that creates the namespace, and the rest are module paths for modules
|
|||
to be attached to the created namespace using
|
||||
@racket[namespace-attach-module].
|
||||
|
||||
The default is @racket[(list make-base-namespace)] if @racket[gui?] is
|
||||
@racket[#f], @racket[(list make-gui-namespace)] if @racket[gui?] is
|
||||
@racket[#t].
|
||||
The default is @racket[(list sandbox-make-namespace)].
|
||||
|
||||
The module paths are needed for sharing module instantiations between
|
||||
the sandbox and the caller. For example, sandbox code that returns
|
||||
|
@ -484,10 +485,28 @@ of code can be helpful:
|
|||
`(,(car specs)
|
||||
,@(cdr specs)
|
||||
lang/posn
|
||||
,@(if gui? '(mrlib/cache-image-snip) '()))))
|
||||
,@(if (gui-available?) '(mrlib/cache-image-snip) '()))))
|
||||
]}
|
||||
|
||||
|
||||
@defproc[(sandbox-make-namespace) namespace?]{
|
||||
|
||||
Calls @racket[make-gui-namespace] when @racket[(sandbox-gui-available)]
|
||||
produces true, @racket[make-base-namespace] otherwise.}
|
||||
|
||||
|
||||
@defboolparam[sandbox-gui-available avail?]{
|
||||
|
||||
Determines whether the @racketmodname[racket/gui] module can be used
|
||||
when a sandbox evaluator is created. If @racket[gui-available?]
|
||||
produces @racket[#f] during the creation of a sandbox evaluator, this
|
||||
parameter is forced to @racket[#f] during initialization of the
|
||||
sandbox. The default value of the parameter is @racket[#t].
|
||||
|
||||
Various aspects of the library change when the GUI library is
|
||||
available, such as using a new eventspace for each evaluator.}
|
||||
|
||||
|
||||
@defparam[sandbox-override-collection-paths paths (listof path-string?)]{
|
||||
|
||||
A parameter that determines a list of collection directories to prefix
|
||||
|
@ -922,12 +941,13 @@ your own permissions, for example,
|
|||
|
||||
@defthing[gui? boolean?]{
|
||||
|
||||
True if the @racketmodname[racket/gui] module can be used, @racket[#f]
|
||||
otherwise; see @racket[gui-available?].
|
||||
For backward compatibility, only: the result of @racket[gui-available?]
|
||||
at the time that @racketmodname[racket/sandbox] was instantiated.
|
||||
|
||||
Various aspects of the @racketmodname[racket/sandbox] library change
|
||||
when the GUI library is available, such as using a new eventspace for
|
||||
each evaluator.}
|
||||
The value of @racket[gui?] is no longer used by
|
||||
@racketmodname[racket/sandbox] itself. Instead,
|
||||
@racket[gui-available?] and @racket[sandbox-gui-available] are
|
||||
checked at the time that a sandbox evaluator is created.}
|
||||
|
||||
|
||||
@defproc[(call-with-limits [secs (or/c exact-nonnegative-integer? #f)]
|
||||
|
|
48
collects/tests/racket/sandbox-gui.rkt
Normal file
48
collects/tests/racket/sandbox-gui.rkt
Normal file
|
@ -0,0 +1,48 @@
|
|||
#lang racket
|
||||
(require racket/sandbox
|
||||
racket/gui/dynamic)
|
||||
|
||||
(define-syntax-rule (test expect expr)
|
||||
(do-test 'expr expect expr))
|
||||
|
||||
(define (do-test which expect got)
|
||||
(unless (equal? expect got)
|
||||
(error 'test "failed: ~s expect: ~e got: ~e" which expect got)))
|
||||
|
||||
;; GUI is initialled allowed by sandbox, but not initially available:
|
||||
|
||||
(test #t (sandbox-gui-available))
|
||||
(test #f (gui-available?))
|
||||
|
||||
;; Create a pre-GUI evaluator:
|
||||
|
||||
(define e (call-with-trusted-sandbox-configuration
|
||||
(lambda ()
|
||||
(make-evaluator 'racket))))
|
||||
(test (void) (e '(require racket/gui/dynamic)))
|
||||
(test #f (e '(gui-available?)))
|
||||
|
||||
;; Load GUI library
|
||||
|
||||
(test (void) (dynamic-require 'racket/gui #f))
|
||||
|
||||
;; Now the GUI is available:
|
||||
|
||||
(test #t (gui-available?))
|
||||
|
||||
;; Create a post-GUI evaluator:
|
||||
|
||||
(define ge (call-with-trusted-sandbox-configuration
|
||||
(lambda ()
|
||||
(make-evaluator 'racket))))
|
||||
(test (void) (ge '(require racket/gui/dynamic)))
|
||||
(test #t (ge '(gui-available?)))
|
||||
|
||||
;; A post-GUI evaluator, but with GUI disabled:
|
||||
|
||||
(define pe (parameterize ([sandbox-gui-available #f])
|
||||
(call-with-trusted-sandbox-configuration
|
||||
(lambda ()
|
||||
(make-evaluator 'racket)))))
|
||||
(test (void) (pe '(require racket/gui/dynamic)))
|
||||
(test #f (pe '(gui-available?)))
|
|
@ -1,3 +1,8 @@
|
|||
Version 5.2.1.7
|
||||
racket/sandbox: added sandbox-gui-enabled and sandbox-make-namespace;
|
||||
deprecated gui?, which is no long used internally; changed the default
|
||||
for sandbox-namespace-specs to sandbox-make-namespsace
|
||||
|
||||
Version 5.2.1.6
|
||||
Added prop:cpointer
|
||||
Fixed handle-evt to disallow a handle-evt
|
||||
|
|
Loading…
Reference in New Issue
Block a user