I try to install a security manager
from a Clojure
program and am stuck short after a good start.
This one works for me in Clojures simple REPL
, in the Lein REPL, and in the Cider REPL in Emacs. It prevents the use of (System/exit n
).
(def SM (proxy [SecurityManager] []
(checkPermission
[^java.security.Permission p]
(when (.startsWith (.getName p) "exitVM")
(throw (SecurityException. "exit"))))))
(System/setSecurityManager SM)
But I want to do this security manager to do more. E.g. log any access
.
Surprisingly many Clojure functions seem to call the security manager, and thus, when used inside of it, give an infinite loop, aka StackOverflowException
.
My failed try:
(def security-log (atom ()))
(def SM (proxy [SecurityManager] []
(checkPermission
([^java.security.Permission p]
(let [now (.toString (System/currentTimeMillis))
log (str "[" now "] " "[cp/1] SM is asked for " p)]
(swap! security-log conj log))
(when (.startsWith (.getName p) "exitVM")
(throw (SecurityException. "exit"))))
([^java.security.Permission p ^Object o]
(let [now (.toString (System/currentTimeMillis))
log (str
"[" now "] "
"[cp/2] SM is asked for " p " on " o)]
(swap! security-log conj log))))))
(System/setSecurityManager SM)
Both failed, putting the log into an atom, and just printing it.
So I have two questions.
- Am I doing something wrong?
- Is there a systematic (and easy) way I can find out which functions I can use inside of a security manager, without putting it into a loop?