From: Adam W. <li...@co...> - 2005-05-27 03:13:17
|
Hi Peter, Thanks for fixing the previous LOOP package bug. In writing a buffer overflow demo for a comp.lang.lisp participant I discovered that ABCL never detected it at any level of safety. I suggest that ABCL should detect it at a positive (1+) level of safety while continuing to omit any check at safety 0 in the interests of performance. Here's the message I posted to comp.lang.lisp: On Fri, 27 May 2005 01:26:04 +0200, André Thieme wrote: > We can use declarations to speed up our Lisp applications. When using > these optimizations, could it then become possible to create security > holes in a program, so that it gets vulnerable to buffer overflow > attacks? Here's a very simple and relatively portable example using displaced arrays: ;;(declaim (optimize (safety 0))) (defparameter *vector* (make-array 4 :initial-element nil)) (defparameter *buffer* (make-array 3 :displaced-to *vector*)) (setf *read-eval* nil) (let ((percent 0)) (defun format-root () (cond ((zerop percent) (format t "Formatting root filesystem ")) ((= percent 100) (error "Format complete")) (t (dotimes (i 5) (format t ".") (force-output) (sleep 0.1)) (format t " ~A% " percent))) (force-output) (incf percent))) (defun accept-input () (format t "Input buffer index between 0 and 2 and a value~%") (let ((index (read)) (value (read))) (setf (aref *buffer* index) value) (format t "Buffer is ~S~%" *buffer*))) (setf (aref *vector* 3) #'accept-input) (loop (funcall (aref *vector* 3))) Let's run the program in a typical Lisp at default optimisation settings: $ sbcl This is SBCL 0.9.0.19, an implementation of ANSI Common Lisp. More information about SBCL is available at <http://www.sbcl.org/>. SBCL is free software, provided as is, with absolutely no warranty. It is mostly in the public domain; some portions are provided under BSD-style licenses. See the CREDITS and COPYING files in the distribution for more information. * (load "buffer") Input buffer index between 0 and 2 and a value 0 abc Buffer is #(ABC NIL NIL) Input buffer index between 0 and 2 and a value 2 567 Buffer is #(ABC NIL 567) Input buffer index between 0 and 2 and a value 3 format-root debugger invoked on a SIMPLE-TYPE-ERROR in thread 2512: invalid array index 3 for #(ABC NIL 567) (should be nonnegative and <3) Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL. restarts (invokable by number or by possibly-abbreviated name): 0: [ABORT] Exit debugger, returning to top level. (ACCEPT-INPUT) 0] You can see that the attempt to overwrite the end of the array named *buffer* was thwarted by a run time check. Now uncomment the line ;;(declaim (optimize (safety 0))) and run the program again: * (load "buffer") STYLE-WARNING: redefining FORMAT-ROOT in DEFUN STYLE-WARNING: redefining ACCEPT-INPUT in DEFUN Input buffer index between 0 and 2 and a value 0 abc Buffer is #(ABC NIL NIL) Input buffer index between 0 and 2 and a value 2 567 Buffer is #(ABC NIL 567) Input buffer index between 0 and 2 and a value 3 format-root Buffer is #(ABC NIL 567) Formatting root filesystem ..... 1% ..... 2% ..... [...] ..... 99% debugger invoked on a SIMPLE-ERROR in thread 2520: Format complete Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL. restarts (invokable by number or by possibly-abbreviated name): 0: [ABORT] Exit debugger, returning to top level. (FORMAT-ROOT) 0] The input data is never explicitly evaluated. Yet I am able to overflow *buffer* with the name of a new function that the input loop happily evaluates. I expect the fastest Lisp implementations to work this way. CLISP is immune to this array overflow. ABCL (an ANSI Common Lisp running on top of the Java Virtual Machine) currently permits this array overflow at all levels of safety. Regards, Adam |