From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Alan Grover Newsgroups: gmane.lisp.guile.user Subject: Re: modify environments to make sandboxes Date: Thu, 22 Jun 2006 14:36:54 -0400 Message-ID: <449AE346.3050306@mail.msen.com> References: <20060612182036.2c989469@localhost.localdomain> <87ver6z5ga.fsf@laas.fr> <871wtuuj1v.fsf@ossau.uklinux.net> <873bdxtlml.fsf@laas.fr> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: sea.gmane.org 1151001459 19689 80.91.229.2 (22 Jun 2006 18:37:39 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Thu, 22 Jun 2006 18:37:39 +0000 (UTC) Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Thu Jun 22 20:37:32 2006 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1FtU36-0008LN-22 for guile-user@m.gmane.org; Thu, 22 Jun 2006 20:37:04 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1FtU35-00062j-Hd for guile-user@m.gmane.org; Thu, 22 Jun 2006 14:37:03 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1FtU30-00062P-C8 for guile-user@gnu.org; Thu, 22 Jun 2006 14:36:58 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1FtU2y-000625-Ic for guile-user@gnu.org; Thu, 22 Jun 2006 14:36:57 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1FtU2y-000622-Ex for guile-user@gnu.org; Thu, 22 Jun 2006 14:36:56 -0400 Original-Received: from [148.59.80.48] (helo=ww8.msen.com) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA:32) (Exim 4.52) id 1FtUE0-0006Zw-3X for guile-user@gnu.org; Thu, 22 Jun 2006 14:48:20 -0400 X-Sent-To: Original-Received: from [192.168.1.104] ([151.196.5.195]) (authenticated bits=0) by ww8.msen.com (8.13.6/8.13.6) with ESMTP id k5MIarP5071823 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) for ; Thu, 22 Jun 2006 14:36:54 -0400 (EDT) (envelope-from awgrover@mail.msen.com) User-Agent: Mozilla Thunderbird 1.0.6 (X11/20050716) X-Accept-Language: en-us, en Original-To: guile-user@gnu.org In-Reply-To: <873bdxtlml.fsf@laas.fr> X-Milter: Spamilter (Reciever: ww8.msen.com; Sender-ip: 151.196.5.195; Sender-helo: [192.168.1.104]; ) X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-user-bounces+guile-user=m.gmane.org@gnu.org Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.user:5385 Archived-At: Ludovic Court=E8s wrote: > Hi, >=20 > Neil Jerram writes: >=20 >=20 >>ludovic.courtes@laas.fr (Ludovic Court=E8s) writes: >> >> >>>Code confinement is indeed an interesting feature. Fortunately, Guile= >>>offers various ways to do it (AFAIK, there's no standard way to do thi= s >>>in R5RS Scheme). :-) [...] One approach is to write your own security-manager/white-list. You scan the s-expr, check the symbols in the head of any (sub-)list, and fail if they aren't approved. The comments of http://schemecookbook.org/Cookbook/DynamicUntrustedEval gives an outline of how to do this (minus parsing). You actually have to parse a bit: so you can ignore argument-lists to lambda, the variables in "let", etc. An example parser is in your guile distribution, scripts/lint, see the detect-free-variables procedure (usually somewhere like /usr/share/guile/1.6/scripts). Of course, you don't have to parse if you don't allow let/lambda and friends. I think there is a R5RS way of doing code-confinement. The R5RS spec says that the null-environment "is empty except for the (syntactic) bindings for all syntactic keywords defined in this report that are either required or both optional and supported by the implementation." I take it to mean that you are guaranteed the required keywords, might have the optional keywords, but won't have anything else. So, you could do this: (define (safe-eval s-expr) (let* ( (lambda-expr-that-provides-some-procs ; extend null-environment with "+" `(lambda (+) ,s-expr)) (actual-lambda (eval lambda-expr-that-provides-some-procs (null-environment 5)))) (actual-lambda +))) ; provide + (safe-eval '(begin (define (x y) 1) (x 2))) (safe-eval '1) (safe-eval '(+ 1 2)) (safe-eval '(- 1 2)) ; fails, there is no "-" available You can provide more procedures where I just provided "+". The trick has two parts: * Eval the untrusted expression in null-environment. A minimum of procedures/etc. is available. * "import" the other-procedures by providing them to a lambda, which provides the lexical environment. You could "black-list" keywords, maybe like this: (define (safe-eval s-expr) (let* ( (lambda-expr-that-provides-some-procs `(lambda (+ error) ; re-bind "define" to something that won't work (let ((define (lambda args (error "Not allowed")))) ,s-expr))) (actual-lambda (eval lambda-expr-that-provides-some-procs (null-environment 5)))) (actual-lambda + error))) (safe-eval '1) (safe-eval '(+ 1 2)) (safe-eval '(begin (define (x y) 1) (x 2))) But, note that this doesn't quite fail the way you want: it will eval (x y) and then call the local "define", which means you'll get an unbound error on x. Well, at least you disabled "define". FYI, here's the list of symbols in null-environment for guile 1.6: and begin case cond define define-syntax delay do if lambda let let* let-syntax letrec letrec-syntax or quasiquote quote set! Beware, you have to provide a comprehensive black-list. Imagine if the guile 1.6 null-environment didn't include every optional-keyword, but 1.8 did. Untrusted code could take advantage of the difference. You also have to carefully consider the impact of allowing any keyword. For example, "let" would allow the untrusted code to do an infinite loop (via named-let). I can't find the place where I originally found this method, but there is another example at http://www.cap-lore.com/CapTheory/Language/Scheme/SchemeFactory.html and the preceding pages. You may want to read these pages to understand some other issues around untrusted code. And in thread: http://ecos.sourceware.org/ml/guile/1999-02/msg00233.html > Note that control over a module's name space (as described in my post) > is not the only thing needed to safely evaluate untrusted code. The > user would also need finer control over all the resources used by the > code at hand (in order to prevent DoS attacks), particularly memory > (heap and stack) and CPU. >=20 > Unfortunately, I don't think this can be realized using Guile, except > maybe by running the untrusted code in a separate process and relying o= n > the OS' resource accounting mechanisms (e.g., `setrlimit' --- but Guile= > core doesn't provide bindings for it). However, running untrusted code= > in a separate process would preclude, practically, resource sharing wit= h > the user's trusted code (e.g., an Xchat Scheme plug-in would be useless= > as a separate process because it would be unable to access the data > structures of the "real" Xchat). >=20 > The "ideal" solution would imply things like: >=20 > * changing the evaluator so that several evaluators with different > `eval-options' can be instantiated (pretty much like the > `guile-reader' approach); this way, untrusted code could be > evaluated with an evaluator that has custom stack limits; >=20 > * having, roughly, a `current-heap' fluid that would be referred to > anytime heap is allocated (hmm...); >=20 > * similarly, have CPU time slice capabilities that would be passed > to `eval' either explicitly or via a fluid. You can also write a safe-interpreter in scheme, and thus in the same process. You solve the above issues by charging the expression each time it applies a procedure, each time it consumes heap (roughly at each "cons"), etc. This one is for chicken: http://www.call-with-current-continuation.org/eggs/sandbox.scm And, again, I can't locate a reference to the original example of this, I believe it was R5RS though. _______________________________________________ Guile-user mailing list Guile-user@gnu.org http://lists.gnu.org/mailman/listinfo/guile-user