Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Lisp code security
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  Messages 26 - 46 of 46 - Collapse all  -  Translate all to Translated (View all originals) < Older 
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Nikodemus Siivola  
View profile  
 More options Dec 7 2004, 5:14 am
Newsgroups: comp.lang.lisp
From: Nikodemus Siivola <tsiiv...@kekkonen.cs.hut.fi>
Date: 7 Dec 2004 10:14:04 GMT
Local: Tues, Dec 7 2004 5:14 am
Subject: Re: Lisp code security

Chris Capel <ch....@iba.nktech.net> wrote:
> Are there extenuating circumstances where this is particularly hard? I can't
> figure out how to make an infinitely recursing function in SBCL that
> doesn't throw a control-stack-exhausted-error.

In current SBCL you should not be able to: stack overflow protection is
implemented with a pair of protected pages at the end of the allocated stack
space: sbcl-devel definitely wants to know if you manage to bypass that
without first corrupting the image in some other way.

That said, the situation is _really_ slightly hairier. Try this on for size:

 (defun killer ()
    (unwind-protect
       (progn (killer) (killer))
     (killer)))

Not nice, eh?

Cheers,

 -- Nikodemus


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Peter Seibel  
View profile  
 More options Dec 7 2004, 1:42 pm
Newsgroups: comp.lang.lisp
From: Peter Seibel <pe...@javamonkey.com>
Date: Tue, 07 Dec 2004 18:42:04 GMT
Local: Tues, Dec 7 2004 1:42 pm
Subject: Re: Lisp code security

But why do the creatures need to be implemented in full Common Lisp?
Surely they don't need to open files, manipulate pathnames, or any of
a number of other things.

> So I want to define a subset of CL that can be verified so that the
> code that's exchanged can be guaranteed not to do bad things, but
> can still be used to define a sophisticated and efficient creature
> AI.

Hmmmm. So having taken a quick glance at the Terrarium stuff I think
you're making your problem harder than the problem they solved--it
sounds like they just scan the code for certain "operations" which are
disallowed such as accessing the local disk or system registry. I
didn't see anything that suggested the Terrarium environment protects
itself from stack overflow, etc. I think you can get this level
security by walking the tree of source code you get and looking for
occurences of symbols that name bad operations. If you want to be
slick you write a real tree walker that recognizes special operators
and expands macros so you can tell if the suspect symbol is actually
being used as the name of an operation. But more conservatively you
just do a simple tree walk:

  (defun check-code (code)
    (cond
      ((null code) nil)
      ((symbolp code)
       (when (bad-name-p code))
         (error "Malicious code detected: ~s" code))
      ((atom code) nil)
      (t (check-code (car code))
         (check-code (cdr code)))))

(Of course with this implementation you've got to worry about stack
overflow while checking the code. ;-))

I'd be interested to know what Terrarium does about DOS attacks such
as creatures that allocate tons of memory or try to overflow the
stack. (The later is easier to deal with as long as the .NET runtime
signals an appropriate exception--you just have to watch out that
creature code can't touch shared objects that require mutual exclusion
to be thread safe since a creature thread could obtain a lock on an
object, temporarily violate its invariants, and then blow the stack,
leaving that object in a corrupted state. Out of memory is harder
since the final failure may affect an innocent thread that just
happens to allocate memory at the wrong time.

-Peter

--
Peter Seibel                                      pe...@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Eric Daniel  
View profile  
 More options Dec 7 2004, 1:47 pm
Newsgroups: comp.lang.lisp
From: Eric Daniel <eric-use...@barberic.org>
Date: Tue, 07 Dec 2004 12:47:30 -0600
Local: Tues, Dec 7 2004 1:47 pm
Subject: Re: Lisp code security

In article <10ra64uqnhn6...@corp.supernews.com>, Chris Capel wrote:

>  On the other hand, I'm probably not clear on what you mean by "compiler".
>  What does it involve? Something like Pascal was talking about, where you
>  simply wrap functions like

>  (cl:defun cons (car cdr)
>    (cl:if (cl:< *allocated* +max-mem+)
>       (cl:cons car cdr)
>       (error "Too much memory")))

I'm not Pascal, but I think something like this would work for your
purpose. Except that you couldn't track the allocated memory this way,
because you wouldn't know when garbage collections occur. You could
however limit the amount of consing (GC-ed or not) any user program is
allowed to perform.

[...]

>  and so on? If this is what you mean by compiler, then it's not much more
>  than I was talking about originally. Couldn't you simply re-export many of
>  CL's symbols?

It depends whether you a) trust the standard for requiring all the safety
checks that matter to you, and b) the implementation for actually
implementing these checks. If you don't, you would have to include these
checks in your version of cons, +, etc.

THEN you have to trust that c) after the safety checks are passed your
implementation doesn't produce buggy machine code.

Security is annoying :-)

Personally I would not let c) bother me, but would be mindful of a) and
b).

Strictly speaking, Pascal is right. But you could also limit the number of
recursive calls at run time (insert the appropriate check in your version
of DEFUN). You would still have to check what else your implementation
uses the stack for.

>  Thomas F. Burdick wrote:
> > ... and you'll then have a
> > tiny CL subset that is effectively protected from accessing the host
> > CL.

>  Would you call a subset that provided CL macros, lists, arrays, a lot of
>  CLOS, and all utility macros and functions "tiny"? At what point close to
>  "tiny" does including more functions dispreportionately increase the danger
>  of missing a security hole?

I don't think anybody knows for sure... Look at the OpenBSD guys. They
set out specifically to produce a secure OS, and they still get holes
every once in a while.

Consider this: even if you rewrite CL-on-top-of-CL, you can still
introduce your own bugs. They wouldn't be related to the system stack or
wild pointers, but they could allow, say, the user to access or modify
objects that should be protected.

This being said, I think your project can come "close enough" to being
secure. It may take more work than the rest of your anthill simulation,
but it would have uses beyond that.

Actually I may need this for some other project. Would you like to work
together on it?

--
Eric Daniel


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Christopher C. Stacy  
View profile  
 More options Dec 7 2004, 3:02 pm
Newsgroups: comp.lang.lisp
From: cst...@news.dtpq.com (Christopher C. Stacy)
Date: Tue, 07 Dec 2004 20:02:24 GMT
Local: Tues, Dec 7 2004 3:02 pm
Subject: Re: Lisp code security
1. Why not use the operating system facilities for limiting the amount
of memory each process can use?  That sounds easier to me than
re-implementing and verifying a Common Lisp implementation to
add such a feature.

2. The way that Java addresses this problem should be instructive.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Chris Capel  
View profile  
 More options Dec 7 2004, 11:40 pm
Newsgroups: comp.lang.lisp
From: Chris Capel <ch....@iba.nktech.net>
Date: Tue, 07 Dec 2004 22:40:14 -0600
Local: Tues, Dec 7 2004 11:40 pm
Subject: Re: Lisp code security

No, not at all. But pathname and package functions are just two really big
holes. Once I've filled in all the big holes, there might be smaller ones.

>> So I want to define a subset of CL that can be verified so that the
>> code that's exchanged can be guaranteed not to do bad things, but
>> can still be used to define a sophisticated and efficient creature
>> AI.

> Hmmmm. So having taken a quick glance at the Terrarium stuff I think
> you're making your problem harder than the problem they solved--it
> sounds like they just scan the code for certain "operations" which are
> disallowed such as accessing the local disk or system registry. I
> didn't see anything that suggested the Terrarium environment protects
> itself from stack overflow, etc.

The .NET runtime environment provides these guarantees. It's pretty
complicated, I understand. Full type safety, for one. Also, it assigns
different parts of the standard library to different permission groups, and
any given code can be executed with a reduced set of permissions based on
just about any kind of policy. Two assemblies (.dll's) that call each other
back and forth can run under two different permission sets, etc. etc.

I'm pretty sure it guarantees that no code that doesn't call out into
foreign functions can crash the runtime. Of course, if an application runs
out of memory, it's going down. But if a sub-process causes everything to
run out of memory, the parent can handle the OutOfMemoryException (called
when memory is low, I believe) and terminate some threads and free
resources so a GC can reclaim it all.

I was running a Terrarium server for a few months way back when it first
started. I never had it crash, or heard anything about there being
successful malware-creatures.

> (Of course with this implementation you've got to worry about stack
> overflow while checking the code. ;-))

Hehe. Good point.

> I'd be interested to know what Terrarium does about DOS attacks such
> as creatures that allocate tons of memory or try to overflow the
> stack.

Terrarium's only safety features that aren't provided by the runtime itself
were cutting off a creature's processing after a certain amount of time (2
to 5 ms). I could be wrong on this, of course.

> (The later is easier to deal with as long as the .NET runtime
> signals an appropriate exception--you just have to watch out that
> creature code can't touch shared objects that require mutual exclusion
> to be thread safe since a creature thread could obtain a lock on an
> object, temporarily violate its invariants, and then blow the stack,
> leaving that object in a corrupted state. Out of memory is harder
> since the final failure may affect an innocent thread that just
> happens to allocate memory at the wrong time.

This is an interesting issue that I'm not sure about the answer to.

Chris Capel


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Chris Capel  
View profile  
 More options Dec 8 2004, 12:30 am
Newsgroups: comp.lang.lisp
From: Chris Capel <ch....@iba.nktech.net>
Date: Tue, 07 Dec 2004 23:30:18 -0600
Local: Wed, Dec 8 2004 12:30 am
Subject: Re: Lisp code security

That gives me another idea. Given that we restrict the safety package to
running on implementations with real threads and with
total-allocated-memory type counters, and given that only one sandboxed
process is run at a time, it'd be possible to run a loop in a high-priority
thread that checks to make sure that the sandboxed code (a) hasn't run for
too long and (b) hasn't allocated more than X bytes, and even to keep up
with the total number of bytes allocated by that process and set a limit on
that. If it runs every five thousand cycles, there's not much a process can
do in that time.

Right that this is the only way to portably protect and limit the execution
stack?

In any case, I don't think this is feasible. You end up using the host lisp
process as a virtual machine in which to implement a child lisp! CL wasn't
designed to be a VM!

> This being said, I think your project can come "close enough" to being
> secure. It may take more work than the rest of your anthill simulation,
> but it would have uses beyond that.

That's what I was thinking.

> Actually I may need this for some other project. Would you like to work
> together on it?

I think I might get some first steps published in a Arch archive pretty soon
now. But I really wanted to get a basic simulation up and going first.
After I get the simulator itself down, which shouldn't be too terribly
hard, I'd be happy to collaborate.

Chris Capel
---
(concatenate 'string "pdf" "2" "3ds" "@" "gmail" "." "com")


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Eric Daniel  
View profile  
 More options Dec 8 2004, 1:25 am
Newsgroups: comp.lang.lisp
From: Eric Daniel <eric-use...@barberic.org>
Date: Wed, 08 Dec 2004 00:25:36 -0600
Local: Wed, Dec 8 2004 1:25 am
Subject: Re: Lisp code security

In article <10rd49cecao1...@corp.supernews.com>, Chris Capel wrote:

>  Right that this is the only way to portably protect and limit the execution
>  stack?

As far as I know:
1) there may be implementation-dependent way to know the current size
of the stack (e.g ROOM on CMUCL)

2) it doesn't guarantee safety, because what is needed is to predict that
an operation (function call, etc.) is about to blow the stack before it
happens!

So yes, for full portability you need to rool out your own call stack.
I'm not 100% sure how to do it. A good start would probably be
Chapter 20 on Graham's /On Lisp/ (Continuations).  That is, you would
perform a slightly complicated transformation on the user-provided code,
and compile the resulting Lisp code. This is, by the way, a testament to
the power of Lisp. I wouldn't even consider doing it in any other
language.

--
Eric Daniel


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tim Bradshaw  
View profile  
 More options Dec 8 2004, 5:13 am
Newsgroups: comp.lang.lisp
From: Tim Bradshaw <t...@cley.com>
Date: Wed, 08 Dec 2004 10:13:41 +0000
Local: Wed, Dec 8 2004 5:13 am
Subject: Re: Lisp code security

* Chris Capel wrote:
> I'm interesting in defining a subset of Lisp that is safe in the sense that
> any arbitrary code written in the subset can be executed without fear of
> the code compromising the security of the system, or taking down the lisp
> image (absent impl. bugs), or accessing certain protected information in
> the lisp image, or hanging the lisp image in a tight loop, or doing other
> malicious things. The code would have to be verified to exist in that
> subset with a function that reads in the code from text (with read-time
> evaluation disabled, of course) and returns whether it's safe. Is it
> possible to define such a subset?

I looked at doing this for CL subsets.  My conclusion was that (a) in
practice it is probably doable in a mildly implementation-dependent
way by controlling the subset of symbols you allow (you need to rely
on the implementation catching stack overflows, being able to kill
threads in tight loops and so on), and (b) if you want it done
*properly* you need a language & runtime designed with safety in mind
from the ground up, which CL obviously was not.

Java was intended to satisfy (b) I think, but even then there are
issues both with what you need to do and just plain bugs as far as I
can tell (I've never looked at Java's security stuff).

If I was doing this now I'd use one of the `container' facilities
offered by various systems as well - *BSD jails or Solaris containers
or something.

--tim


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal Bourguignon  
View profile  
 More options Dec 8 2004, 10:11 am
Newsgroups: comp.lang.lisp
From: Pascal Bourguignon <s...@mouse-potato.com>
Date: 08 Dec 2004 16:11:52 +0100
Local: Wed, Dec 8 2004 10:11 am
Subject: Re: Lisp code security

For a small example of (a), see my following implementation of AIM-8
lisp in Common-Lisp (and in AIM-8 lisp).  You don't need any
implementation-dependent stuff to control stack overflow, if the
underlying implementation is safe in this respect, just a
strategically placed HANDLER-CASE.  Only for timeout an implementation
specific API should be used:  WITH-TIMEOUT is provided in the
non-standard PROCESS package.

;;************************************************************************* ***
;;FILE:               aim-8.lisp
;;LANGUAGE:           Common-Lisp
;;SYSTEM:             Common-Lisp
;;USER-INTERFACE:     NONE
;;DESCRIPTION
;;    
;;    Implements the LISP described in AIM-8 in Common-Lisp.
;;    Usage:  (load "aim-8.lisp")
;;            (aim-8:repl)
;;    Then at the aim-8 prompt, you have LISP, plus:
;;       (DEFINE name sexp)     corresponding to =
;;       (RELOAD)               to reload aim-8 if you edit it.
;;       (DUMP-ENVIRONMENT)     to dump the defined symbols.
;;       (LOAD "path")          to load an aim-8 source. Try "aim-8.aim-8".
;;    
;;AUTHORS
;;    <PJB> Pascal Bourguignon <p...@informatimago.com>
;;MODIFICATIONS
;;    2004-10-24 <PJB> Created.
;;BUGS
;;LEGAL
;;    GPL
;;    
;;    Copyright Pascal Bourguignon 2004 - 2004
;;    
;;    This program is free software; you can redistribute it and/or
;;    modify it under the terms of the GNU General Public License
;;    as published by the Free Software Foundation; either version
;;    2 of the License, or (at your option) any later version.
;;    
;;    This program is distributed in the hope that it will be
;;    useful, but WITHOUT ANY WARRANTY; without even the implied
;;    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;;    PURPOSE.  See the GNU General Public License for more details.
;;    
;;    You should have received a copy of the GNU General Public
;;    License along with this program; if not, write to the Free
;;    Software Foundation, Inc., 59 Temple Place, Suite 330,
;;    Boston, MA 02111-1307 USA
;;************************************************************************* ***
;;    
;; AIM-8 -- 23 MARCH 1959 -- J. MCCARTHY

(DEFPACKAGE "AIM-8"
  (:USE "COMMON-LISP")
  (:EXPORT "REPL")
  (:DOCUMENTATION
   "Implements the lisp of AIM-8 -- 23 MARCH 1959 -- J. McCarthy"));;AIM-8
(IN-PACKAGE "AIM-8")

(DEFPACKAGE "AIM-8-USER"
  (:USE)
  (:IMPORT-FROM "AIM-8"
                "DEFINE" "LAMBDA" "LABEL"
                "COND"  "COMBINE" "FIRST" "REST"
                "NULL" "ATOM" "EQ" "NIL" "T" "QUOTE"));;AIM-8-USER

(DEFPARAMETER *ENVIRONMENT* (MAKE-HASH-TABLE :TEST (FUNCTION EQ)))
(DEFMACRO DEF     (NAME)       `(GETHASH ,NAME *ENVIRONMENT*))
(DEFUN   %BOUNDP  (NAME) (MULTIPLE-VALUE-BIND (VAL BND) (DEF NAME)
                          (DECLARE (IGNORE VAL)) BND))
(DEFMACRO DEFINE  (NAME VALUE) `(SETF (GETHASH ',NAME *ENVIRONMENT*) ',VALUE))
(DEFUN   FDEFINE  (NAME VALUE)  (SETF (GETHASH NAME *ENVIRONMENT*) VALUE))

(DEFINE NIL ())
(DEFINE F   ())
(DEFINE T   T)
(DEFINE AND     (LAMBDA (A B) (COND (A (COND (B T) (T NIL))) (T NIL))))
(DEFINE OR      (LAMBDA (A B) (COND (A T) (B T) (T NIL))))
(DEFINE NOT     (LAMBDA (A)   (COND (A NIL) (T NIL))))
(DEFINE MAPLIST
        (LAMBDA (X F)
          (COND ((NULL X) NIL)
                (T (COMBINE (F X) (MAPLIST (REST X) F))))))
(DEFINE SUBST
        (LAMBDA (X Y A)
          (COND ((NULL A) NIL)
                ((ATOM A) (COND ((EQ Y A) X) (T A)))
                (T (COMBINE (SUBST X Y (FIRST A))
                            (SUBST X Y (REST A))))
                )));;SUBST

(DEFUN %SUBST (X Y A)
  (COND ((NULL A) NIL)
        ((ATOM A) (COND ((EQ Y A) X) (T A)))
        (T (CONS (%SUBST X Y (FIRST A)) (%SUBST X Y (REST A))))))

(DEFUN %SUBSQ (X Y Z)
  (COND ((NULL Z) NIL)
        ((ATOM Z) (COND ((EQ Y Z) X)  (T Z)))
        ((EQ (FIRST Z) 'QUOTE) Z)
        (T (CONS (%SUBSQ X Y (FIRST Z)) (%SUBSQ X Y (REST Z))))));;%SUBSQ

(DEFUN %EVCON (C)
  (COND ((%EVAL (FIRST (FIRST C))) (%EVAL (FIRST (REST (FIRST C)))))
        (T (%EVCON (REST C)))))

(DEFUN %EVLAM (VARS EXP ARGS)
  (COND ((NULL VARS) (%EVAL EXP))
        (T (%EVLAM (REST VARS) (%SUBSQ (FIRST ARGS) (FIRST VARS) EXP)
                   (REST ARGS)))))

(DEFUN %APPLY (F ARGS) (%EVAL (CONS F ARGS)))

(DEFUN %EVAL (E)
  (COND
    ;; begin extensions:
    ((ATOM E) (COND ((%BOUNDP E) (DEF E))
                    (T (ERROR "Undefined: ~A" (FIRST E)))))
    ;; end extensions.
    (T (CASE (FIRST E)
         ((NULL)    (NULL  (%EVAL (FIRST (REST E)))))
         ((ATOM)    (ATOM  (%EVAL (FIRST (REST E)))))
         ((QUOTE)   (FIRST (REST E)))
         ((EQ)      (EQ    (%EVAL (FIRST (REST E)))
                           (%EVAL (FIRST (REST (REST E))))))
         ((COMBINE) (CONS  (%EVAL (FIRST (REST E)))
                           (%EVAL (FIRST (REST (REST E))))))
         ((FIRST)   (FIRST (%EVAL (FIRST (REST E)))))
         ((REST)    (REST  (%EVAL (FIRST (REST E)))))
         ((COND)    (%EVCON (REST E)))
         ;; begin extensions:
         ((LOAD)    (LOAD  (%EVAL (FIRST (REST E)))))
         ((PRINT)   (PRINT (%EVAL (FIRST (REST E)))))
         ((READ)    (READ))
         (OTHERWISE
          (COND
            ((ATOM (FIRST E))
             (COND ((%BOUNDP (FIRST E)) (%APPLY (DEF (FIRST E)) (REST E)))
                   (T (ERROR "Undefined: ~A" (FIRST E)))))
            ;; end extensions.
            (T (CASE (FIRST (FIRST E))
                 ((LAMBDA) (%EVLAM (FIRST (REST (FIRST E)))
                              (FIRST (REST (REST (FIRST E))))
                              (REST E)))
                 ((LABEL) (%EVAL (CONS (%SUBST (FIRST E)
                                               (FIRST (REST (FIRST E)))
                                               (FIRST (REST (REST (FIRST E)))))
                                       (REST E))))
                 (OTHERWISE (ERROR "Invalid: ~A" (FIRST E)))))))))));;%EVAL

(DEFUN HELP ()
  (FORMAT T "~&You've got:  
    DEFINE LAMBDA LABEL
    COND AND OR NOT  COMBINE FIRST REST
    NULL ATOM EQ NIL T QUOTE
    QUIT"));;HELP

(DEFMACRO HANDLING-ERRORS (&BODY BODY)
  `(HANDLER-CASE (PROGN ,@BODY)
     (ERROR (ERR)
            (APPLY (FUNCTION FORMAT) *ERROR-OUTPUT*
                   (SIMPLE-CONDITION-FORMAT-CONTROL ERR)
                   (SIMPLE-CONDITION-FORMAT-ARGUMENTS ERR)))));;HANDLING-ERRORS

(DEFUN REPL ()
  (LET ((*PACKAGE* (FIND-PACKAGE "AIM-8")))
    (HELP)
    (LOOP
       (TERPRI)
       (PRINC "AIM-8> ")
       (HANDLING-ERRORS
        (LET ((SEXP (READ)))
          (COND
            ((EQUAL SEXP '(QUIT))
             (FORMAT T "GOOD BYE") (RETURN-FROM REPL))
            ((EQUAL SEXP '(RELOAD))
             (LOAD "aim-8") (REPL) (RETURN-FROM REPL))
            ((EQUAL SEXP '(DUMP-ENVIRONMENT))
             (FORMAT T "~:{~16@A = ~A~%~}"
                     (LET ((RES '()))
                       (MAPHASH (LAMBDA (K V) (PUSH (LIST K V) RES))
                                *ENVIRONMENT*) RES)))
            ((AND (LISTP SEXP) (EQ (FIRST SEXP) 'DEFINE))
             (FDEFINE (SECOND SEXP) (THIRD SEXP))
             (FORMAT T "~A" (SECOND SEXP)))
            (T
             (FORMAT T "~S" (%EVAL SEXP))))))))
  (TERPRI)
  (VALUES));;REPL

;; (in-package "COMMON-LISP-USER")
;; (aim-8:repl)

;;;; aim-8.lisp                       --                     --          ;;;;

;; -*- mode: Lisp -*-
;;************************************************************************* ***
;;FILE:               aim-8.aim-8
;;LANGUAGE:           AIM-8 LISP
;;SYSTEM:             AIM-8 LISP
;;USER-INTERFACE:     NONE
;;DESCRIPTION
;;    
;;    Implements the LISP described in AIM-8 in AIM-8 LISP
;;    Usage: At the AIM-8> prompt:  
;;      (LOAD (QUOTE "aim-8.aim-8"))
;;      (REPL)
;;    The AIM-8 evaluation algorithm is pure substitution, no binding!
;;    Therefore (read) is called every time it's _used_:
;;    you need to enter the same sexp several times to get it processed!
;;
;;      (EVAL (QUOTE (FF1 (QUOTE ((())()()((A)B C)))))
;;            (QUOTE ((FF1 LAMBDA (X) (COND ((OR (NULL X) (ATOM X)) X)
;;                                 (T (COND ((FF1 (FIRST X)) (FF1 (FIRST X)))
;;                                          (T (FF1 (REST X)))))))))
;;   Note: Since this implements an substitution interpreter on an interpreter
;;   on a lisp system, it usually quite slow to compute the result of non
;;   trivial functions.
;;
;;AUTHORS
;;
...

read more »


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal Bourguignon  
View profile  
 More options Dec 8 2004, 9:45 am
Newsgroups: comp.lang.lisp
From: Pascal Bourguignon <s...@mouse-potato.com>
Date: 08 Dec 2004 15:45:46 +0100
Local: Wed, Dec 8 2004 9:45 am
Subject: Re: Lisp code security

Chris Capel <ch....@iba.nktech.net> writes:
> Right that this is the only way to portably protect and limit the execution
> stack?

> In any case, I don't think this is feasible. You end up using the host lisp
> process as a virtual machine in which to implement a child lisp! CL wasn't
> designed to be a VM!

Ah but you should not underestimate the power of virtual machines.

Common-Lisp is a general language, you can use it to implement a
virtual machine. It's even easy and fast to do. (Writting it in
Modula-2 could give a faster VM, but it would be harder and slower to
implement).

Now, the killer feature of Common-Lisp for virtual machines is JIT:
once you've got a sequence a VM instructions, you can build a
Common-Lisp function from the VM microcode and compile it, which would
produce an optimized native code for the original function.

Since you can do this with a page or two of Common-Lisp code, and
could not do this with less than a lot more of C (even if you tried to
system("gcc ...") and dlopen("lib...")). Well, if it was so simple in
C, Apple would have delivered Xcode ten years ago.

--
__Pascal Bourguignon__                     http://www.informatimago.com/
The world will now reboot; don't bother saving your artefacts.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tim Bradshaw  
View profile  
 More options Dec 8 2004, 12:20 pm
Newsgroups: comp.lang.lisp
From: Tim Bradshaw <t...@cley.com>
Date: Wed, 08 Dec 2004 17:20:32 +0000
Local: Wed, Dec 8 2004 12:20 pm
Subject: Re: Lisp code security

* Pascal Bourguignon wrote:
> For a small example of (a), see my following implementation of AIM-8
> lisp in Common-Lisp (and in AIM-8 lisp).  You don't need any
> implementation-dependent stuff to control stack overflow, if the
> underlying implementation is safe in this respect, just a
> strategically placed HANDLER-CASE.  

That's what I meant by `mildly implementation-dependent': you need to
know that the implementation is safe. In particular the code should
refuse to run on one that is not.

--tim


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Thomas F. Burdick  
View profile  
 More options Dec 8 2004, 4:24 pm
Newsgroups: comp.lang.lisp
From: t...@conquest.OCF.Berkeley.EDU (Thomas F. Burdick)
Date: 08 Dec 2004 13:24:28 -0800
Local: Wed, Dec 8 2004 4:24 pm
Subject: Re: Lisp code security

I mean a program that takes input in the form of s-expressions, views
that input as the source code to a CL-safe program, and produces an
equivalent CL program.  You can then compile that CL code with the
host compiler.  The guts of it might look something like this:

  (defun compile-form (form env)
    (let ((form (macroexpand form env)))
      (cond
        ((symbolp form)
         (if (forbidden-symbol-p form)
             (error "Access to this symbol is forbidden: ~S" form)
             form))
        ((not (listp form))
         (if (forbidden-object-p form)
             (error "Access to this object is forbidden: ~S" form)
             form))
        ((special-operator-p (first form))
         (ecase (first form)
           (quote
             (if (forbidden-object-p (second form))
                 (error "You get the idea.")
                 `(quote ,(second form))))
           (unwind-protect
             (destructuring-bind (protected &rest cleanup) (rest form)
               `(unwind-protect
                     ,(compile-form protected env)
                  ;; We want to be able to throw past user code if we're trying
                  ;; to abort their execution.
                  (unless *aborting*
                    ,@(mapcar (lambda (x) (compile-form x env))
                              cleanup)))))
           ;; ... etc ...
           ))
        ((not (symbolp (first form)))
         (compile-form `(funcall #',(first form) ,@(rest form)) env))
        ;; If we get here, we have a normal function call
        ((or (find-lexical-function (first form) env)
             (safe-function-p (first form)))
         (list* (first form) (mapcar (lambda (x) (compile-form x env))
                                     (rest form))))
        (t `(funcall (get-safe-fun ',(first form))
                     ,@(mapcar (lambda (x) (compile-form x env))
                               (rest form)))))))

I'm kind of fudging on the issue of lexical environments above, but if
you reuse your implementation's lexical environments, you can do it
like this.  Also, you'll might want to check for the safety of macros
before you expand them.  Now you can compile CL-safe functions to CL:

  (defun safe-eval (form)
    (let ((cl (compile-form form (make-null-environment))))
      (eval cl)))

The functions SAFE-FUNCTION-P, FORBIDDEN-SYMBOL-P, and
FORBIDDEN-OBJECT-P define the allowed subset, probably by looking
things up in tables.

> Thomas F. Burdick wrote:
> > ... and you'll then have a
> > tiny CL subset that is effectively protected from accessing the host
> > CL.

> Would you call a subset that provided CL macros, lists, arrays, a lot of
> CLOS, and all utility macros and functions "tiny"? At what point close to
> "tiny" does including more functions dispreportionately increase the danger
> of missing a security hole?

I meant you'll have a tiny subset before you populate the tables used
by SAFE-FUNCTION-P, etc.  At first your CL-safe subset won't be able
to call any functions except those it defines itself.  So, no CONS, no
LIST, no ERROR.  Not all that useful, but the host Lisp is protected
from it.  Then you start exposing parts of the host Lisp, to make it
useful, which is the hard part, not the compiler per se.

Oh, and in SBCL, I'd consider any access to CLOS unsafe, because PCL
can really fuck itself up, breaking any CLOS-using code in the image.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Matthias Buelow  
View profile  
 More options Dec 9 2004, 8:11 pm
Newsgroups: comp.lang.lisp
From: Matthias Buelow <m...@mukappabeta.de>
Date: Fri, 10 Dec 2004 02:11:26 +0100
Local: Thurs, Dec 9 2004 8:11 pm
Subject: Re: Lisp code security

Pascal Bourguignon wrote:
> program you get informed immediately.  For collisions between the
> stack and the heap, it's more difficult.  And in any case, you're back

All contemporary Unix systems have at least one unmapped page between
the top of the "heap" and the bottom of the stack, and stack overflows
are always caught.  I bet that goes for Windows aswell.

--
   Matthias Buelow; mkb@{mukappabeta,informatik.uni-wuerzburg}.de


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal Bourguignon  
View profile  
 More options Dec 9 2004, 8:21 pm
Newsgroups: comp.lang.lisp
From: Pascal Bourguignon <s...@mouse-potato.com>
Date: 10 Dec 2004 02:21:36 +0100
Local: Thurs, Dec 9 2004 8:21 pm
Subject: Re: Lisp code security

Matthias Buelow <m...@mukappabeta.de> writes:
> Pascal Bourguignon wrote:
> > program you get informed immediately.  For collisions between the
> > stack and the heap, it's more difficult.  And in any case, you're back

> All contemporary Unix systems have at least one unmapped page between
> the top of the "heap" and the bottom of the stack, and stack overflows
> are always caught.  I bet that goes for Windows aswell.

That does not help much. Try: alloca(1024*1024*1024);

--
__Pascal Bourguignon__                     http://www.informatimago.com/
The world will now reboot; don't bother saving your artefacts.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tim Bradshaw  
View profile  
 More options Dec 10 2004, 7:44 am
Newsgroups: comp.lang.lisp
From: Tim Bradshaw <t...@cley.com>
Date: Fri, 10 Dec 2004 12:44:37 +0000
Local: Fri, Dec 10 2004 7:44 am
Subject: Re: Lisp code security

* Pascal Bourguignon wrote:
> That does not help much. Try: alloca(1024*1024*1024);

Are you assuming some broken implementation of alloca which does not
check?

--tim


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal Bourguignon  
View profile  
 More options Dec 10 2004, 1:09 pm
Newsgroups: comp.lang.lisp
From: Pascal Bourguignon <s...@mouse-potato.com>
Date: 10 Dec 2004 19:09:42 +0100
Local: Fri, Dec 10 2004 1:09 pm
Subject: Re: Lisp code security

Tim Bradshaw <t...@cley.com> writes:
> * Pascal Bourguignon wrote:

> > That does not help much. Try: alloca(1024*1024*1024);

> Are you assuming some broken implementation of alloca which does not
> check?

What would you check exactly?

--
__Pascal Bourguignon__                     http://www.informatimago.com/
The world will now reboot; don't bother saving your artefacts.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tim Bradshaw  
View profile  
 More options Dec 13 2004, 6:40 am
Newsgroups: comp.lang.lisp
From: Tim Bradshaw <t...@cley.com>
Date: Mon, 13 Dec 2004 11:40:38 +0000
Local: Mon, Dec 13 2004 6:40 am
Subject: Re: Lisp code security

* Pascal Bourguignon wrote:
> Tim Bradshaw <t...@cley.com> writes:
>> Are you assuming some broken implementation of alloca which does not
>> check?
> What would you check exactly?

that it hasn't overflowed the stack.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal Bourguignon  
View profile  
 More options Dec 13 2004, 11:27 am
Newsgroups: comp.lang.lisp
From: Pascal Bourguignon <s...@mouse-potato.com>
Date: 13 Dec 2004 17:27:20 +0100
Local: Mon, Dec 13 2004 11:27 am
Subject: Re: Lisp code security

Tim Bradshaw <t...@cley.com> writes:
> * Pascal Bourguignon wrote:
> > Tim Bradshaw <t...@cley.com> writes:

> >> Are you assuming some broken implementation of alloca which does not
> >> check?

> > What would you check exactly?

> that it hasn't overflowed the stack.

So it would have to browse a table of mapped pages, the current value
of sbrk(), to identify the heap zones and the other stacks (eg. in
case of multithreading), and to check whether the stack pointer would
cross any heap zone or other stack.  That would quite defeat the
purpose of alloca which is to get a fast allocation on stack.  I don't
think many do.

--
__Pascal Bourguignon__                     http://www.informatimago.com/
The world will now reboot; don't bother saving your artefacts.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tim Bradshaw  
View profile  
 More options Dec 13 2004, 12:44 pm
Newsgroups: comp.lang.lisp
From: Tim Bradshaw <t...@cley.com>
Date: Mon, 13 Dec 2004 17:44:32 +0000
Local: Mon, Dec 13 2004 12:44 pm
Subject: Re: Lisp code security

* Pascal Bourguignon wrote:
> So it would have to browse a table of mapped pages, the current value
> of sbrk(), to identify the heap zones and the other stacks (eg. in
> case of multithreading), and to check whether the stack pointer would
> cross any heap zone or other stack.  That would quite defeat the
> purpose of alloca which is to get a fast allocation on stack.  I don't
> think many do.

Um. No, of course it wouldn't.  It just needs to do a single bound
check (`am I trying to allocate beyond the end of the heap').  If that
fails it might have to do something complicated, but more likely just
return failure.

--tim


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Pascal Bourguignon  
View profile  
 More options Dec 13 2004, 2:34 pm
Newsgroups: comp.lang.lisp
From: Pascal Bourguignon <s...@mouse-potato.com>
Date: 13 Dec 2004 20:34:02 +0100
Local: Mon, Dec 13 2004 2:34 pm
Subject: Re: Lisp code security

Tim Bradshaw <t...@cley.com> writes:
> * Pascal Bourguignon wrote:

> > So it would have to browse a table of mapped pages, the current value
> > of sbrk(), to identify the heap zones and the other stacks (eg. in
> > case of multithreading), and to check whether the stack pointer would
> > cross any heap zone or other stack.  That would quite defeat the
> > purpose of alloca which is to get a fast allocation on stack.  I don't
> > think many do.

> Um. No, of course it wouldn't.  It just needs to do a single bound
> check (`am I trying to allocate beyond the end of the heap').  If that
> fails it might have to do something complicated, but more likely just
> return failure.

The limit is dependent on the stack (there are several stacks with
multithreading) and varies each time you call mmap, shmat, sbrk, etc.
If you allow FFI and foreign libraries, you cannot count on them to
update the stack limit table, so you'll have to scan more than what is
done currently. You'd have the choice between doing it at alloca time
or whenever a FFI returns, with perhaps some more optimization
depending on the actual stack you're on,  but this is not something
that's done by alloca(3).

--
__Pascal Bourguignon__                     http://www.informatimago.com/
The world will now reboot; don't bother saving your artefacts.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tim Bradshaw  
View profile  
 More options Dec 14 2004, 10:39 am
Newsgroups: comp.lang.lisp
From: Tim Bradshaw <t...@cley.com>
Date: Tue, 14 Dec 2004 15:39:12 +0000
Local: Tues, Dec 14 2004 10:39 am
Subject: Re: Lisp code security

* Pascal Bourguignon wrote:
> The limit is dependent on the stack (there are several stacks with
> multithreading) and varies each time you call mmap, shmat, sbrk, etc.
> If you allow FFI and foreign libraries, you cannot count on them to
> update the stack limit table, so you'll have to scan more than what is
> done currently. You'd have the choice between doing it at alloca time
> or whenever a FFI returns, with perhaps some more optimization
> depending on the actual stack you're on,  but this is not something
> that's done by alloca(3).

So, how do all the systems which treat stack pages specially (no
execute perm for instance) do it?  Let's see... they know the bounds
of the stack.  All the time.

--tim


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages < Older 
« Back to Discussions « Newer topic     Older topic »