Execute 'docker run' from within SBCL Common Lisp

Viewed 166

I'm trying to run a function in my lisp program. It is a bot that is connected to an IRC channel and with a special command you can query the bot to evaluate a simple lisp command. Because it is extremely dangerous to execute arbitrary code from people on the internet I want the actual evaluation to happen in a VM that is running a docker for every evaluation query the bot gets.

My function looks like this:

(defun run-command (cmd)
  (uiop:run-program (list "docker" "run" "--rm" "-it" "my/docker" "sbcl" "--noinform" "--no-sysinit" "--no-userinit" "--noprint" "--disable-debugger" "--eval" (string-trim '(#\^M) (format nil "~A" cmd))) "--eval" "'(quit)'") :output '(:string :stripped t))

The idea behind this function is to start a docker that contains SBCL, runs the command via SBCL --eval and prints it to the docker std-out. And this printed string should be the result of run-command.

If I call

docker run --rm -it my/docker sbcl --noinform --no-sysinit --no-userinit --noprint --disable-debugger --eval "(print (+ 2 3))" --eval "(quit)"

on my command line I just get 5 as an result, what is exactly what I want.

But if I run the same command within lisp, with the uiop:run-program function I get

Subprocess #<UIOP/LAUNCH-PROGRAM::PROCESS-INFO {1004FC3923}>
 with command ("docker" "run" "--rm" "-it"
               "my/docker" "sbcl" "--noinform"
               "--no-sysinit" "--no-userinit" "--noprint"
               "--disable-debugger" "--eval" "(+ 2 3)")

as an error message, which means the process failed somehow. But I don't know what exactly could be wrong here. If I just execute for example "ls" I get the output, so the function seems to work properly.

Is there some special knowledge I need about uiop:run-program or am I doing something completely wrong?

Thanks in advance.

Edit: So it turns out that the -it flag caused issues. After removing the flag a new error emerges. Now the bot has not the permissions to execute docker. Is there a way to give it the permissions without granting it sudo rights?

2 Answers

There's, probably, something wrong with the way docker is invoked here (or SBCL). To get the error message, invoke uiop:run-program with :error-output :string argument, and then choose the continue restart to, actually, terminate execution and get the error output printed (if you're running from SLIME or some other REPL). If you call this in a non-interactive environment, you can wrap the call in a handler-bind:

(handler-bind ((uiop/run-program:subprocess-error
                 (lambda (e) (invoke-restart (find-restart 'continue)))))
  (run-command ...))

It turned out the -it did cause trouble. After removing it and elevating the correct permissions to the bot everything worked out fine.

Related