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)
|
setup/dirs)
|
||||||
|
|
||||||
(provide gui?
|
(provide gui?
|
||||||
|
sandbox-gui-available
|
||||||
sandbox-init-hook
|
sandbox-init-hook
|
||||||
sandbox-reader
|
sandbox-reader
|
||||||
sandbox-input
|
sandbox-input
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
sandbox-security-guard
|
sandbox-security-guard
|
||||||
sandbox-network-guard
|
sandbox-network-guard
|
||||||
sandbox-exit-handler
|
sandbox-exit-handler
|
||||||
|
sandbox-make-namespace
|
||||||
sandbox-make-inspector
|
sandbox-make-inspector
|
||||||
sandbox-make-code-inspector
|
sandbox-make-code-inspector
|
||||||
sandbox-make-logger
|
sandbox-make-logger
|
||||||
|
@ -53,12 +55,16 @@
|
||||||
exn:fail:resource?
|
exn:fail:resource?
|
||||||
exn:fail:resource-resource)
|
exn:fail:resource-resource)
|
||||||
|
|
||||||
|
; for backward compatibility; maybe it should be removed:
|
||||||
(define gui? (gui-available?))
|
(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
|
(define-syntax mz/mr ; use a value for plain racket, or pull a gui binding
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
[(mz/mr mzval mrsym)
|
[(mz/mr mzval mrsym)
|
||||||
(if gui? (gui-dynamic-require 'mrsym) mzval)]))
|
(if (sandbox-gui-available) (gui-dynamic-require 'mrsym) mzval)]))
|
||||||
|
|
||||||
;; Configuration ------------------------------------------------------------
|
;; Configuration ------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -85,8 +91,11 @@
|
||||||
[sandbox-eval-handlers '(#f #f)])
|
[sandbox-eval-handlers '(#f #f)])
|
||||||
(thunk)))
|
(thunk)))
|
||||||
|
|
||||||
|
(define (sandbox-make-namespace)
|
||||||
|
((mz/mr make-base-namespace make-gui-namespace)))
|
||||||
|
|
||||||
(define sandbox-namespace-specs
|
(define sandbox-namespace-specs
|
||||||
(make-parameter `(,(mz/mr make-base-namespace make-gui-namespace)
|
(make-parameter `(,sandbox-make-namespace
|
||||||
#| no modules here by default |#)))
|
#| no modules here by default |#)))
|
||||||
|
|
||||||
(define (default-sandbox-reader source)
|
(define (default-sandbox-reader source)
|
||||||
|
@ -613,15 +622,7 @@
|
||||||
(uncovered! (list (get) get)))
|
(uncovered! (list (get) get)))
|
||||||
(when (namespace? ns) (current-namespace ns)))
|
(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 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
|
;; special message values for the evaluator procedure, also inside the user
|
||||||
;; context they're used for function applications.
|
;; context they're used for function applications.
|
||||||
|
@ -879,6 +880,8 @@
|
||||||
memory-cust))
|
memory-cust))
|
||||||
(parameterize* ; the order in these matters
|
(parameterize* ; the order in these matters
|
||||||
(;; create a sandbox context first
|
(;; create a sandbox context first
|
||||||
|
[sandbox-gui-available (and (sandbox-gui-available)
|
||||||
|
(gui-available?))]
|
||||||
[current-custodian user-cust]
|
[current-custodian user-cust]
|
||||||
[current-thread-group (make-thread-group)]
|
[current-thread-group (make-thread-group)]
|
||||||
;; paths
|
;; paths
|
||||||
|
@ -944,17 +947,24 @@
|
||||||
[current-command-line-arguments '#()]
|
[current-command-line-arguments '#()]
|
||||||
;; Finally, create the namespace in the restricted environment (in
|
;; Finally, create the namespace in the restricted environment (in
|
||||||
;; particular, it must be created under the new code inspector)
|
;; 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
|
;; Note the above definition of `current-eventspace': in Racket, it
|
||||||
;; is an unused parameter. Also note that creating an eventspace
|
;; is an unused parameter. Also note that creating an eventspace
|
||||||
;; starts a thread that will eventually run the callback code (which
|
;; starts a thread that will eventually run the callback code (which
|
||||||
;; evaluates the program in `run-in-bg') -- so this parameterization
|
;; evaluates the program in `run-in-bg') -- so this parameterization
|
||||||
;; must be nested in the above (which is what paramaterize* does), or
|
;; must be nested in the above (which is what paramaterize* does), or
|
||||||
;; it will not use the new namespace.
|
;; it will not use the new namespace.
|
||||||
[current-eventspace (parameterize-break #f (make-eventspace))])
|
([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)))
|
(define t (bg-run->thread (run-in-bg user-process)))
|
||||||
(set! user-done-evt (handle-evt t (lambda (_) (terminate+kill! #t #t))))
|
(set! user-done-evt (handle-evt t (lambda (_) (terminate+kill! #t #t))))
|
||||||
(set! user-thread t))
|
(set! user-thread t)))
|
||||||
(define r (get-user-result))
|
(define r (get-user-result))
|
||||||
(if (eq? r 'ok)
|
(if (eq? r 'ok)
|
||||||
;; initial program executed ok, so return an evaluator
|
;; initial program executed ok, so return an evaluator
|
||||||
|
|
|
@ -128,8 +128,10 @@ argument:
|
||||||
|
|
||||||
In this case, a new namespace is created using
|
In this case, a new namespace is created using
|
||||||
@racket[sandbox-namespace-specs], which by default creates a
|
@racket[sandbox-namespace-specs], which by default creates a
|
||||||
new namespace using @racket[make-base-namespace] or
|
new namespace using @racket[sandbox-make-namespace] (which, in
|
||||||
@racket[make-gui-namespace] (depending on @racket[gui?]).
|
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
|
In the new namespace, @racket[language] is evaluated as an
|
||||||
expression to further initialize the namespace.}
|
expression to further initialize the namespace.}
|
||||||
|
@ -188,7 +190,8 @@ In all cases, the evaluator operates in an isolated and limited
|
||||||
environment:
|
environment:
|
||||||
@itemize[
|
@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.}
|
true, it is also runs in its own eventspace.}
|
||||||
|
|
||||||
@item{The evaluator works under the @racket[sandbox-security-guard],
|
@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
|
to be attached to the created namespace using
|
||||||
@racket[namespace-attach-module].
|
@racket[namespace-attach-module].
|
||||||
|
|
||||||
The default is @racket[(list make-base-namespace)] if @racket[gui?] is
|
The default is @racket[(list sandbox-make-namespace)].
|
||||||
@racket[#f], @racket[(list make-gui-namespace)] if @racket[gui?] is
|
|
||||||
@racket[#t].
|
|
||||||
|
|
||||||
The module paths are needed for sharing module instantiations between
|
The module paths are needed for sharing module instantiations between
|
||||||
the sandbox and the caller. For example, sandbox code that returns
|
the sandbox and the caller. For example, sandbox code that returns
|
||||||
|
@ -484,10 +485,28 @@ of code can be helpful:
|
||||||
`(,(car specs)
|
`(,(car specs)
|
||||||
,@(cdr specs)
|
,@(cdr specs)
|
||||||
lang/posn
|
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?)]{
|
@defparam[sandbox-override-collection-paths paths (listof path-string?)]{
|
||||||
|
|
||||||
A parameter that determines a list of collection directories to prefix
|
A parameter that determines a list of collection directories to prefix
|
||||||
|
@ -922,12 +941,13 @@ your own permissions, for example,
|
||||||
|
|
||||||
@defthing[gui? boolean?]{
|
@defthing[gui? boolean?]{
|
||||||
|
|
||||||
True if the @racketmodname[racket/gui] module can be used, @racket[#f]
|
For backward compatibility, only: the result of @racket[gui-available?]
|
||||||
otherwise; see @racket[gui-available?].
|
at the time that @racketmodname[racket/sandbox] was instantiated.
|
||||||
|
|
||||||
Various aspects of the @racketmodname[racket/sandbox] library change
|
The value of @racket[gui?] is no longer used by
|
||||||
when the GUI library is available, such as using a new eventspace for
|
@racketmodname[racket/sandbox] itself. Instead,
|
||||||
each evaluator.}
|
@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)]
|
@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
|
Version 5.2.1.6
|
||||||
Added prop:cpointer
|
Added prop:cpointer
|
||||||
Fixed handle-evt to disallow a handle-evt
|
Fixed handle-evt to disallow a handle-evt
|
||||||
|
|
Loading…
Reference in New Issue
Block a user