I need to hide dungerous function(s), for example, cl:open for thirdparty code downloaded from internet.
So I can do like this:
(package :dangerous (:use :cl))
(import 'cl:open :dangerous)
(import 'cl:export :dangerous)
...
(unexport 'open :cl)
(unexport 'export :cl)
...
; instead of cl:export which hided implement own export fn and then import it to untrusted package
(load "untrusted-lib.lisp")
As I understand the untrusted code cant call cl:open at all, except using cl::open, right? Is possible to call cl:open by another way?
At first sight CL has potencial to restrict access to API if a double colon access will disabled. Theoretically it becomes possible to create a security manager (permission access manager) Is possible to disable "::" calls for SBCL and another CL compilers?
The code you give is both very nonconforming (you modify the CL package) and would not solve the problem if it was conforming.
Here is an easy way of defeating it:
(setf (fdefinition 'my-open)
(do-symbols (s :cl)
(when (string= (symbol-name s) "OPEN")
(return (fdefinition s)))))
Here's another (this is better, but I thought of it later):
(setf (fdefinition 'my-open)
(fdefinition (find-symbol "OPEN" :cl)))
There will be more.
So something like this is really a hopeless approach to solving the problem, even if was legal Common Lisp, which it is not.
CL is not a language designed with this kind of restriction in mind, so a good solution is somewhere between difficult and impossible.
Perhaps an approach might be as follows.
You may well also want to have a 'sanitize' stage: stash away the package state of the system before each evaluation (this is laborious but possible) and then, after it, check nothing you did not expect has changed. You will probably also want some kind of timeout mechanism you can wrap around evaluations.
I do not claim this is sufficient. I do not claim that this is even completely possible in CL. But something like this may help, if it is.
I happen to know that conduit packages was originally written as part of a system which tried to do some of this. So it's a good way to define a package which reexports only parts of, for instance CL
:
(define-conduit-package :just-conses
(:extends/including :cl
#:cons #:car #:cdr #:nil ...))
In general a better approach is almost certainly to sandbox the system using a platform-level sandbox: people, including at least some who understand security, have worked hard on these things to make them actually secure, and they get tested against malicious people all the time.